Universal advanced pathfinder. (Spannish)
Key RequiredUniversal

Universal advanced pathfinder. (Spannish)

Universal ScriptEnvprytoncat1Envprytoncat1 376 views 194 executesUpdated Sep 16, 2026
Unrated
00
Lua Script•1674 lines (71023 chars)
-- This script is made by Gemini, I don't deserve the rights to it.

-- ==========================================
-- SISTEMA DE REINICIO AUTOMÁTICO (CLEANUP)
-- ==========================================
local globalEnv = getgenv and getgenv() or _G
if globalEnv.XenoCleanup then
    pcall(function() globalEnv.XenoCleanup() end)
end

local isScriptRunning = true
local connections = {}

local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local PathfindingService = game:GetService("PathfindingService")
local StarterGui = game:GetService("StarterGui")
local RunService = game:GetService("RunService")

local LocalPlayer = Players.LocalPlayer
local mouse = LocalPlayer:GetMouse()

local function notify(title, text)
    pcall(function()
        StarterGui:SetCore("SendNotification", {
            Title = title,
            Text = text,
            Duration = 3
        })
    end)
end

-- ==========================================
-- VARIABLES GLOBALES Y CONFIGURACIÓN
-- ==========================================
local isTracking = false
local targetMode = "Todos" 
local movementMode = "Perseguir" -- "Perseguir", "Huir", "Merodear", "ClickToMove"
local clickToMovePos = nil
local wanderTarget = nil

local entityMode = "Jugadores" 
local manualTargetEntity = nil 
local activeTargetRoot = nil 

-- Configuraciones F1
local allowJumping = true
local ignoreSpecialBlocks = false
local autoAttack = false
local unequipAfterUse = false 
local ignoreDead = true
local autoJumpHazards = false 
local isFreelock = false
local attackDistance = 10
local trackingRadius = math.huge
local deadRadius = 0 
local maxDropDistance = math.huge

local trackingTask = nil
local rigCheckTask = nil
local currentLookTarget = nil 
local lastRigType = nil
local cachedNPCs = {} 
local globalHeartbeatJumpTime = 0

local isESPEnabled = false
local espBoxes = {}

-- Elementos de Interfaz
local btnESP = nil
local settingsFrame = nil
local mainFrame = nil

local pathVisualsFolder = workspace:FindFirstChild("XenoPathVisuals")
local espVisualsFolder = workspace:FindFirstChild("XenoESPVisualsFolder")
if not espVisualsFolder then
    espVisualsFolder = Instance.new("Folder")
    espVisualsFolder.Name = "XenoESPVisualsFolder"
    espVisualsFolder.Parent = workspace
end
if not pathVisualsFolder then
    pathVisualsFolder = Instance.new("Folder")
    pathVisualsFolder.Name = "XenoPathVisuals"
    pathVisualsFolder.Parent = workspace
end

local function toggleESP()
    isESPEnabled = not isESPEnabled
    notify("Visual", "ESP Objetivos: " .. (isESPEnabled and "ACTIVADO" or "DESACTIVADO"))
    
    if btnESP then
        btnESP.Text = isESPEnabled and "SI" or "NO"
        btnESP.TextColor3 = isESPEnabled and Color3.fromRGB(0, 200, 50) or Color3.fromRGB(200, 50, 50)
        local stroke = btnESP:FindFirstChildOfClass("UIStroke")
        if stroke then
            stroke.Color = isESPEnabled and Color3.fromRGB(0, 200, 50) or Color3.fromRGB(200, 50, 50)
        end
    end
    
    if not isESPEnabled then
        for char, box in pairs(espBoxes) do
            if box.proxyPart then box.proxyPart:Destroy() end
        end
        table.clear(espBoxes)
        if espVisualsFolder then
            espVisualsFolder:ClearAllChildren()
        end
    end
end

local isJumpingHazard = false
local hazardJumpDirection = Vector3.zero

-- ==========================================
-- EVENTO CLICK TO MOVE
-- ==========================================
table.insert(connections, mouse.Button1Down:Connect(function()
    if isScriptRunning and isTracking and movementMode == "ClickToMove" then
        if mouse.Hit then
            clickToMovePos = mouse.Hit.Position
            notify("Ruta", "Moviendo a la ubicación seleccionada")
        end
    end
end))

-- ==========================================
-- FUNCIÓN PARA VOLVER ARRASTRABLES LAS VENTANAS
-- ==========================================
local function enableDragging(frame, dragHandle)
    dragHandle = dragHandle or frame
    local dragging = false
    local dragInput, dragStart, startPos

    table.insert(connections, dragHandle.InputBegan:Connect(function(input)
        if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
            dragging = true
            dragStart = input.Position
            startPos = frame.Position

            input.Changed:Connect(function()
                if input.UserInputState == Enum.UserInputState.End then
                    dragging = false
                end
            end)
        end
    end))

    table.insert(connections, dragHandle.InputChanged:Connect(function(input)
        if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then
            dragInput = input
        end
    end))

    table.insert(connections, UserInputService.InputChanged:Connect(function(input)
        if input == dragInput and dragging then
            local delta = input.Position - dragStart
            frame.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y)
        end
    end))
end

-- ==========================================
-- INTERFAZ DE CONTROLES Y CONFIGURACIÓN (UI)
-- ==========================================
local sg = Instance.new("ScreenGui")
sg.Name = "XenoControlsGui"
sg.ResetOnSpawn = false

local success = pcall(function()
    sg.Parent = LocalPlayer:FindFirstChild("PlayerGui") or game:GetService("CoreGui")
end)

local function createControlsUI()
    if not success then return end

    mainFrame = Instance.new("Frame")
    mainFrame.Size = UDim2.new(0, 240, 0, 310)
    mainFrame.Position = UDim2.new(0, 30, 0.5, -155)
    mainFrame.BackgroundColor3 = Color3.fromRGB(18, 18, 20)
    mainFrame.BackgroundTransparency = 0.7
    mainFrame.BorderSizePixel = 0
    mainFrame.Parent = sg

    local mainCorner = Instance.new("UICorner")
    mainCorner.CornerRadius = UDim.new(0, 16)
    mainCorner.Parent = mainFrame

    local mainStroke = Instance.new("UIStroke")
    mainStroke.Color = Color3.fromRGB(255, 255, 255)
    mainStroke.Thickness = 1.5
    mainStroke.Parent = mainFrame

    local headerFrame = Instance.new("Frame")
    headerFrame.Size = UDim2.new(1, 0, 0, 42)
    headerFrame.BackgroundTransparency = 1
    headerFrame.Parent = mainFrame

    local titleLabel = Instance.new("TextLabel")
    titleLabel.Size = UDim2.new(1, -90, 1, 0)
    titleLabel.Position = UDim2.new(0, 15, 0, 0)
    titleLabel.BackgroundTransparency = 1
    titleLabel.Text = "Controles"
    titleLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
    titleLabel.Font = Enum.Font.SourceSans
    titleLabel.TextSize = 22
    titleLabel.TextXAlignment = Enum.TextXAlignment.Left
    titleLabel.Parent = headerFrame

    local btnMin = Instance.new("TextButton")
    btnMin.Size = UDim2.new(0, 32, 0, 32)
    btnMin.Position = UDim2.new(1, -75, 0, 5)
    btnMin.BackgroundColor3 = Color3.fromRGB(25, 25, 28)
    btnMin.Text = "—"
    btnMin.TextColor3 = Color3.fromRGB(255, 255, 255)
    btnMin.Font = Enum.Font.SourceSansBold
    btnMin.TextSize = 16
    btnMin.Parent = headerFrame

    local minCorner = Instance.new("UICorner")
    minCorner.CornerRadius = UDim.new(1, 0)
    minCorner.Parent = btnMin

    local minStroke = Instance.new("UIStroke")
    minStroke.Color = Color3.fromRGB(255, 255, 255)
    minStroke.Thickness = 1.2
    minStroke.Parent = btnMin

    local btnClose = Instance.new("TextButton")
    btnClose.Size = UDim2.new(0, 32, 0, 32)
    btnClose.Position = UDim2.new(1, -38, 0, 5)
    btnClose.BackgroundColor3 = Color3.fromRGB(25, 25, 28)
    btnClose.Text = "X"
    btnClose.TextColor3 = Color3.fromRGB(255, 255, 255)
    btnClose.Font = Enum.Font.SourceSansBold
    btnClose.TextSize = 16
    btnClose.Parent = headerFrame

    local closeCorner = Instance.new("UICorner")
    closeCorner.CornerRadius = UDim.new(1, 0)
    closeCorner.Parent = btnClose

    local closeStroke = Instance.new("UIStroke")
    closeStroke.Color = Color3.fromRGB(255, 255, 255)
    closeStroke.Thickness = 1.2
    closeStroke.Parent = btnClose

    local contentFrame = Instance.new("Frame")
    contentFrame.Size = UDim2.new(1, -20, 1, -50)
    contentFrame.Position = UDim2.new(0, 10, 0, 42)
    contentFrame.BackgroundTransparency = 1
    contentFrame.Parent = mainFrame

    local contentLayout = Instance.new("UIListLayout")
    contentLayout.Parent = contentFrame
    contentLayout.SortOrder = Enum.SortOrder.LayoutOrder
    contentLayout.Padding = UDim.new(0, 6)

    local controlsList = {
        "F1: Abrir conf. adicional",
        "F2: Jugadores/ NPC's",
        "F3: Pers/Huir/Merodear/Click",
        "F4: Activar / Desactivar",
        "F5: Filtrar Alid. / Enem.",
        "F6: Ciclar objetivos",
        "Mantener F6: Modo autom."
    }

    for _, text in ipairs(controlsList) do
        local lbl = Instance.new("TextLabel")
        lbl.Size = UDim2.new(1, 0, 0, 22)
        lbl.BackgroundTransparency = 1
        lbl.Text = text
        lbl.TextColor3 = Color3.fromRGB(255, 255, 255)
        lbl.Font = Enum.Font.SourceSans
        lbl.TextSize = 16
        lbl.TextXAlignment = Enum.TextXAlignment.Center
        lbl.Parent = contentFrame
    end

    enableDragging(mainFrame, headerFrame)

    local isMinimized = false
    table.insert(connections, btnMin.MouseButton1Click:Connect(function()
        isMinimized = not isMinimized
        contentFrame.Visible = not isMinimized
        mainFrame.Size = isMinimized and UDim2.new(0, 240, 0, 42) or UDim2.new(0, 240, 0, 310)
    end))

    table.insert(connections, btnClose.MouseButton1Click:Connect(function()
        if globalEnv.XenoCleanup then
            globalEnv.XenoCleanup()
        end
    end))

    settingsFrame = Instance.new("Frame")
    settingsFrame.Size = UDim2.new(0, 230, 0, 490) 
    settingsFrame.Position = UDim2.new(0, 280, 0.5, -245)
    settingsFrame.BackgroundColor3 = Color3.fromRGB(18, 18, 20)
    settingsFrame.BackgroundTransparency = 0.7
    settingsFrame.BorderSizePixel = 0
    settingsFrame.Visible = false
    settingsFrame.Parent = sg

    local settingsCorner = Instance.new("UICorner")
    settingsCorner.CornerRadius = UDim.new(0, 16)
    settingsCorner.Parent = settingsFrame

    local settingsStroke = Instance.new("UIStroke")
    settingsStroke.Color = Color3.fromRGB(255, 255, 255)
    settingsStroke.Thickness = 1.5
    settingsStroke.Parent = settingsFrame

    local settingsHeader = Instance.new("Frame")
    settingsHeader.Size = UDim2.new(1, 0, 0, 35)
    settingsHeader.BackgroundTransparency = 1
    settingsHeader.Parent = settingsFrame

    local settingsTitle = Instance.new("TextLabel")
    settingsTitle.Size = UDim2.new(1, 0, 1, 0)
    settingsTitle.BackgroundTransparency = 1
    settingsTitle.Text = "Configuración adicional"
    settingsTitle.TextColor3 = Color3.fromRGB(255, 255, 255)
    settingsTitle.Font = Enum.Font.SourceSans
    settingsTitle.TextSize = 20
    settingsTitle.Parent = settingsHeader

    enableDragging(settingsFrame, settingsHeader)

    local settingsListContainer = Instance.new("Frame")
    settingsListContainer.Size = UDim2.new(1, -20, 1, -60)
    settingsListContainer.Position = UDim2.new(0, 10, 0, 35)
    settingsListContainer.BackgroundTransparency = 1
    settingsListContainer.Parent = settingsFrame

    local settingsListLayout = Instance.new("UIListLayout")
    settingsListLayout.Parent = settingsListContainer
    settingsListLayout.SortOrder = Enum.SortOrder.LayoutOrder
    settingsListLayout.Padding = UDim.new(0, 7)

    local function createToggleRow(labelText, defaultState, callback)
        local row = Instance.new("Frame")
        row.Size = UDim2.new(1, 0, 0, 28)
        row.BackgroundTransparency = 1
        row.Parent = settingsListContainer

        local label = Instance.new("TextLabel")
        label.Size = UDim2.new(0.68, 0, 1, 0)
        label.BackgroundTransparency = 1
        label.Text = labelText .. " :"
        label.TextColor3 = Color3.fromRGB(255, 255, 255)
        label.Font = Enum.Font.SourceSans
        label.TextSize = 15
        label.TextXAlignment = Enum.TextXAlignment.Left
        label.Parent = row

        local btn = Instance.new("TextButton")
        btn.Size = UDim2.new(0.32, 0, 1, 0)
        btn.Position = UDim2.new(0.68, 0, 0, 0)
        btn.BackgroundColor3 = Color3.fromRGB(25, 25, 28)
        btn.BackgroundTransparency = 0.5
        btn.Text = defaultState and "SI" or "NO"
        btn.TextColor3 = defaultState and Color3.fromRGB(0, 200, 50) or Color3.fromRGB(200, 50, 50)
        btn.Font = Enum.Font.SourceSansBold
        btn.TextSize = 14
        btn.Parent = row

        local pillCorner = Instance.new("UICorner")
        pillCorner.CornerRadius = UDim.new(0.5, 0)
        pillCorner.Parent = btn

        local btnStroke = Instance.new("UIStroke")
        btnStroke.Color = defaultState and Color3.fromRGB(0, 200, 50) or Color3.fromRGB(200, 50, 50)
        btnStroke.Thickness = 1.5
        btnStroke.Parent = btn

        table.insert(connections, btn.MouseButton1Click:Connect(function()
            local newState = callback()
            btn.Text = newState and "SI" or "NO"
            btn.TextColor3 = newState and Color3.fromRGB(0, 200, 50) or Color3.fromRGB(200, 50, 50)
            btnStroke.Color = newState and Color3.fromRGB(0, 200, 50) or Color3.fromRGB(200, 50, 50)
        end))

        return btn
    end

    local function createInputRow(labelText, defaultValue, callback)
        local row = Instance.new("Frame")
        row.Size = UDim2.new(1, 0, 0, 28)
        row.BackgroundTransparency = 1
        row.Parent = settingsListContainer

        local label = Instance.new("TextLabel")
        label.Size = UDim2.new(0.68, 0, 1, 0)
        label.BackgroundTransparency = 1
        label.Text = labelText .. " :"
        label.TextColor3 = Color3.fromRGB(255, 255, 255)
        label.Font = Enum.Font.SourceSans
        label.TextSize = 15
        label.TextXAlignment = Enum.TextXAlignment.Left
        label.Parent = row

        local box = Instance.new("TextBox")
        box.Size = UDim2.new(0.32, 0, 1, 0)
        box.Position = UDim2.new(0.68, 0, 0, 0)
        box.BackgroundColor3 = Color3.fromRGB(25, 25, 28)
        box.Text = tostring(defaultValue)
        box.TextColor3 = Color3.fromRGB(255, 255, 255)
        box.Font = Enum.Font.SourceSansBold
        box.TextSize = 14
        box.Parent = row

        local boxCorner = Instance.new("UICorner")
        boxCorner.CornerRadius = UDim.new(0.5, 0)
        boxCorner.Parent = box

        local boxStroke = Instance.new("UIStroke")
        boxStroke.Color = Color3.fromRGB(255, 255, 255)
        boxStroke.Thickness = 1
        boxStroke.Parent = box

        table.insert(connections, box.FocusLost:Connect(function()
            callback(box)
        end))
    end

    createToggleRow("Saltar", allowJumping, function()
        allowJumping = not allowJumping
        return allowJumping
    end)

    createToggleRow("Ignorar peligros", ignoreSpecialBlocks, function()
        ignoreSpecialBlocks = not ignoreSpecialBlocks
        return ignoreSpecialBlocks
    end)

    createToggleRow("Saltar peligros", autoJumpHazards, function()
        autoJumpHazards = not autoJumpHazards
        return autoJumpHazards
    end)

    createToggleRow("Ignorar muertos", ignoreDead, function()
        ignoreDead = not ignoreDead
        return ignoreDead
    end)

    btnESP = createToggleRow("Ver objetivos", isESPEnabled, function()
        toggleESP()
        return isESPEnabled
    end)

    createToggleRow("Auto usar herramientas", autoAttack, function()
        autoAttack = not autoAttack
        return autoAttack
    end)
    
    createToggleRow("Deseleccionar al usar", unequipAfterUse, function()
        unequipAfterUse = not unequipAfterUse
        return unequipAfterUse
    end)
    
    createToggleRow("Freelock", isFreelock, function()
        isFreelock = not isFreelock
        return isFreelock
    end)

    createInputRow("Rango uso herr.", attackDistance, function(box)
        local num = tonumber(box.Text)
        if num and num >= 0 then attackDistance = num end
        box.Text = tostring(attackDistance)
    end)

    createInputRow("Rango de búsqueda", "Inf", function(box)
        local txt = box.Text
        local num = tonumber(txt)
        if not num or num < 0 then
            if txt:lower() == "inf" or txt == "" then
                trackingRadius = math.huge
                box.Text = "Inf"
            else
                box.Text = trackingRadius == math.huge and "Inf" or tostring(trackingRadius)
            end
        else
            trackingRadius = num
            box.Text = tostring(trackingRadius)
        end
    end)

    createInputRow("Zona muerta", deadRadius, function(box)
        local num = tonumber(box.Text)
        if not num or num < 0 then
            box.Text = tostring(deadRadius)
            return
        end
        deadRadius = num
        box.Text = tostring(deadRadius)
    end)

    createInputRow("Dist. de caída máx.", "Inf", function(box)
        local txt = box.Text
        local num = tonumber(txt)
        if not num or num < 0 then
            if txt:lower() == "inf" or txt == "" then
                maxDropDistance = math.huge
                box.Text = "Inf"
            else
                box.Text = maxDropDistance == math.huge and "Inf" or tostring(maxDropDistance)
            end
        else
            maxDropDistance = num
            box.Text = tostring(maxDropDistance)
        end
    end)

    local footerLabel = Instance.new("TextLabel")
    footerLabel.Size = UDim2.new(1, 0, 0, 20)
    footerLabel.Position = UDim2.new(0, 0, 1, -25)
    footerLabel.BackgroundTransparency = 1
    footerLabel.Text = "(F1 para cerrar ventana)"
    footerLabel.TextColor3 = Color3.fromRGB(200, 200, 200)
    footerLabel.Font = Enum.Font.SourceSansItalic
    footerLabel.TextSize = 14
    footerLabel.Parent = settingsFrame
end

createControlsUI()

-- ==========================================
-- SISTEMA DE DETECCIÓN Y MODIFICADORES
-- ==========================================
local function checkPartForModifiers(obj)
    if obj:IsA("BasePart") then
        local name = string.lower(obj.Name)
        
        if obj:IsA("TrussPart") or string.find(name, "ladder") or string.find(name, "escalera") or string.find(name, "climb") or string.find(name, "truss") then
            if not obj:FindFirstChildOfClass("PathfindingLink") then
                local halfHeight = obj.Size.Y / 2
                
                local attBottom = Instance.new("Attachment")
                attBottom.Name = "XenoLadderBottom"
                attBottom.Position = Vector3.new(0, -halfHeight + 1.5, 0)
                attBottom.Parent = obj
                
                local attTop = Instance.new("Attachment")
                attTop.Name = "XenoLadderTop"
                attTop.Position = Vector3.new(0, halfHeight - 1, 0)
                attTop.Parent = obj
                
                local link = Instance.new("PathfindingLink")
                link.Attachment0 = attBottom
                link.Attachment1 = attTop
                link.IsBidirectional = true
                link.Label = "Climbable"
                link.Parent = obj
            end
            return
        end
        
        if obj:FindFirstChildOfClass("PathfindingModifier") then return end
        
        if obj:IsA("Seat") or obj:IsA("VehicleSeat") then
            local modifier = Instance.new("PathfindingModifier")
            modifier.Label = "SeatHazard"
            modifier.Parent = obj
            return
        end
        
        if string.find(name, "kill") or string.find(name, "lava") or string.find(name, "damage") or string.find(name, "spike") or string.find(name, "acid") or string.find(name, "hurt") 
        or string.find(name, "muerte") or string.find(name, "daño") or string.find(name, "dano") or string.find(name, "pincho") or string.find(name, "trampa")
        or string.find(name, "trip") then
            local isSmallHazard = (obj.Size.X <= 4 or obj.Size.Z <= 4) and obj.Size.Y <= 1
            local modifier = Instance.new("PathfindingModifier")
            modifier.Label = isSmallHazard and "SmallHazard" or "Hazard"
            modifier.Parent = obj
        elseif string.find(name, "seat") or string.find(name, "asiento") then
            local modifier = Instance.new("PathfindingModifier")
            modifier.Label = "Hazard"
            modifier.Parent = obj
        elseif string.find(name, "teleport") or string.find(name, "portal") or string.find(name, "tp") or string.find(name, "pad") then
            local modifier = Instance.new("PathfindingModifier")
            modifier.Label = "Teleporter"
            modifier.Parent = obj
        elseif string.find(name, "conveyor") or string.find(name, "belt") or string.find(name, "cinta") or string.find(name, "transportadora") or (obj.Anchored and obj.AssemblyLinearVelocity.Magnitude > 1) then
            local modifier = Instance.new("PathfindingModifier")
            modifier.Label = "Conveyor"
            modifier.Parent = obj
        elseif obj.Material == Enum.Material.Ice or string.find(name, "ice") or string.find(name, "hielo") or string.find(name, "slide") or string.find(name, "slip") or string.find(name, "desliza") or string.find(name, "resbala") then
            local modifier = Instance.new("PathfindingModifier")
            modifier.Label = "Slippery"
            modifier.Parent = obj
        end
    end
end

local function checkNPC(obj)
    if obj:IsA("Model") and obj ~= LocalPlayer.Character then
        local hum = obj:FindFirstChildOfClass("Humanoid")
        if hum then
            local root = obj:FindFirstChild("HumanoidRootPart") or obj.PrimaryPart
            if root and not Players:GetPlayerFromCharacter(obj) then
                local exists = false
                for _, npc in ipairs(cachedNPCs) do
                    if npc == obj then exists = true break end
                end
                if not exists then table.insert(cachedNPCs, obj) end
            end
        end
    end
end

task.spawn(function()
    local descendants = workspace:GetDescendants()
    for i, obj in ipairs(descendants) do
        if not isScriptRunning then break end
        checkPartForModifiers(obj)
        if obj:IsA("Model") then checkNPC(obj) end
        if i % 1000 == 0 then task.wait() end
    end
end)

table.insert(connections, workspace.DescendantAdded:Connect(function(obj)
    checkPartForModifiers(obj)
    if obj:IsA("Model") then
        task.delay(0.5, function()
            if obj and obj.Parent then checkNPC(obj) end
        end)
    elseif obj:IsA("Humanoid") and obj.Parent:IsA("Model") then
        checkNPC(obj.Parent)
    end
end))

task.spawn(function()
    while task.wait(10) do
        if not isScriptRunning then break end
        for i = #cachedNPCs, 1, -1 do
            local npc = cachedNPCs[i]
            if not npc or not npc.Parent then
                table.remove(cachedNPCs, i)
            end
        end
    end
end)

local function clearPathVisuals()
    for _, child in ipairs(pathVisualsFolder:GetChildren()) do
        child:Destroy()
    end
end

local function drawPath(waypoints, color, transparency)
    if not waypoints then return end
    color = color or Color3.fromRGB(0, 255, 150)
    transparency = transparency or 0.3
    
    for i = 1, #waypoints - 1 do
        local p1 = waypoints[i].Position
        local p2 = waypoints[i + 1].Position
        local distance = (p1 - p2).Magnitude

        local line = Instance.new("Part")
        line.Size = Vector3.new(0.05, 0.05, distance)
        line.CFrame = CFrame.lookAt(p1, p2) * CFrame.new(0, 0, -distance / 2)
        line.Anchored = true
        line.CanCollide = false
        line.Material = Enum.Material.Neon
        line.Color = color
        line.Transparency = transparency
        line.Parent = pathVisualsFolder
    end
end

local function getSafeRootPart(character)
    if not character then return nil end
    return character:FindFirstChild("HumanoidRootPart") or character.PrimaryPart or character:FindFirstChild("Torso") or character:FindFirstChild("UpperTorso")
end

local function getAvailableEntities()
    local list = {}
    if entityMode == "Jugadores" or entityMode == "Ambos" then
        for _, p in ipairs(Players:GetPlayers()) do
            if p ~= LocalPlayer and p.Character then
                table.insert(list, {name = p.DisplayName, accountName = p.Name, char = p.Character, isPlayer = true, player = p})
            end
        end
    end
    if entityMode == "NPCs" or entityMode == "Ambos" then
        for _, npc in ipairs(cachedNPCs) do
            if npc and npc.Parent then
                table.insert(list, {name = npc.Name, char = npc, isPlayer = false})
            end
        end
    end
    return list
end

local function getTargetsSortedByDistance()
    local targets = {}
    local myChar = LocalPlayer.Character
    local myRoot = getSafeRootPart(myChar)
    if not myRoot then return targets end 
    
    if manualTargetEntity then
        if manualTargetEntity.isPlayer then
            local p = Players:FindFirstChild(manualTargetEntity.accountName)
            if p then
                local pChar = p.Character
                if pChar then
                    local targetRoot = getSafeRootPart(pChar)
                    local hum = pChar:FindFirstChildOfClass("Humanoid")
                    local isAlive = hum and hum.Health > 0 and hum:GetState() ~= Enum.HumanoidStateType.Dead
                    if not ignoreDead or isAlive then
                        if targetRoot then
                            manualTargetEntity.char = pChar 
                            local dist = (myRoot.Position - targetRoot.Position).Magnitude
                            if dist <= trackingRadius then
                                table.insert(targets, {character = pChar, distance = dist})
                                return targets
                            end
                        end
                    end
                end
                return targets 
            else
                local npcChar = manualTargetEntity.char
                local isAlive = false
                
                if npcChar and npcChar.Parent then
                    local targetRoot = getSafeRootPart(npcChar)
                    local hum = npcChar:FindFirstChildOfClass("Humanoid")
                    
                    local aliveCheck = hum and hum.Health > 0 and hum:GetState() ~= Enum.HumanoidStateType.Dead
                    if not ignoreDead or aliveCheck then
                        if targetRoot then
                            isAlive = true
                            local dist = (myRoot.Position - targetRoot.Position).Magnitude
                            if dist <= trackingRadius then
                                table.insert(targets, {character = npcChar, distance = dist})
                                return targets
                            end
                        end
                    end
                end
                
                if not isAlive then
                    local foundNewNPC = nil
                    for _, npc in ipairs(cachedNPCs) do
                        if npc and npc.Parent and npc.Name == manualTargetEntity.name then
                            local root = getSafeRootPart(npc)
                            local hum = npc:FindFirstChildOfClass("Humanoid")
                            local aliveCheck = hum and hum.Health > 0 and hum:GetState() ~= Enum.HumanoidStateType.Dead
                            if root and (not ignoreDead or aliveCheck) then
                                foundNewNPC = npc
                                break
                            end
                        end
                    end
                    
                    if foundNewNPC then
                        manualTargetEntity.char = foundNewNPC
                        local targetRoot = getSafeRootPart(foundNewNPC)
                        local dist = (myRoot.Position - targetRoot.Position).Magnitude
                        if dist <= trackingRadius then
                            table.insert(targets, {character = foundNewNPC, distance = dist})
                            return targets
                        end
                    else
                        return targets
                    end
                end
            end
        end
    end

    local entities = getAvailableEntities()
    for _, ent in ipairs(entities) do
        local targetRoot = getSafeRootPart(ent.char)
        local hum = ent.char:FindFirstChildOfClass("Humanoid")
        local isAlive = hum and hum.Health > 0 and hum:GetState() ~= Enum.HumanoidStateType.Dead
        local canTarget = not ignoreDead or isAlive
        
        if targetRoot and canTarget then
            local isValidTarget = true
            
            if ent.isPlayer then
                local player = ent.player
                if targetMode == "Enemigos" then
                    if LocalPlayer.Team ~= nil and player.Team ~= nil then
                        if LocalPlayer.Team == player.Team then isValidTarget = false end
                    elseif not LocalPlayer.Neutral and not player.Neutral then
                        if LocalPlayer.TeamColor == player.TeamColor then isValidTarget = false end
                    end
                elseif targetMode == "Aliados" then
                    if LocalPlayer.Team ~= nil and player.Team ~= nil then
                        if LocalPlayer.Team ~= player.Team then isValidTarget = false end
                    elseif not LocalPlayer.Neutral and not player.Neutral then
                        if LocalPlayer.TeamColor ~= player.TeamColor then isValidTarget = false end
                    else
                        isValidTarget = false 
                    end
                end
            else
                if targetMode == "Aliados" then isValidTarget = false end
            end
            
            if isValidTarget then
                local distance = (myRoot.Position - targetRoot.Position).Magnitude
                if distance <= trackingRadius then
                    table.insert(targets, {character = ent.char, distance = distance})
                end
            end
        end
    end
    
    table.sort(targets, function(a, b) return a.distance < b.distance end)
    return targets
end

local function getFloorPosition(position)
    local raycastParams = RaycastParams.new()
    if LocalPlayer.Character then
        raycastParams.FilterDescendantsInstances = {LocalPlayer.Character, pathVisualsFolder}
    end
    raycastParams.FilterType = Enum.RaycastFilterType.Exclude
    
    local result = workspace:Raycast(position + Vector3.new(0, 3, 0), Vector3.new(0, -53, 0), raycastParams)
    if result then return result.Position end
    return position 
end

local function startRigCheck()
    rigCheckTask = task.spawn(function()
        while isTracking and isScriptRunning do
            local char = LocalPlayer.Character
            if char then
                local humanoid = char:FindFirstChildOfClass("Humanoid")
                local rootPart = getSafeRootPart(char)
                
                if humanoid and rootPart then
                    local rigType = "Personalizado"
                    if humanoid.RigType == Enum.HumanoidRigType.R6 and char:FindFirstChild("Torso") then
                        rigType = "R6"
                    elseif humanoid.RigType == Enum.HumanoidRigType.R15 and char:FindFirstChild("UpperTorso") then
                        rigType = "R15"
                    end
                    if not char:FindFirstChild("HumanoidRootPart") then
                        rigType = "Personalizado"
                    end
                    if rigType ~= lastRigType then
                        lastRigType = rigType
                    end
                end
            end
            task.wait(3)
        end
    end)
end

-- ==========================================
-- AIMBOT / SISTEMA DE ATAQUE A DISTANCIA GLOBAL
-- ==========================================
local function handleAutoAttack()
    if not autoAttack then return end
    local char = LocalPlayer.Character
    if not char then return end
    
    local rootPart = getSafeRootPart(char)
    if not rootPart then return end
    
    local sortedTargets = getTargetsSortedByDistance()
    if #sortedTargets == 0 then return end
    
    local bestTarget = sortedTargets[1]
    if bestTarget.distance > attackDistance then return end
    
    local targetRoot = getSafeRootPart(bestTarget.character)
    if not targetRoot then return end
    
    local lookAtPos = Vector3.new(targetRoot.Position.X, rootPart.Position.Y, targetRoot.Position.Z)
    rootPart.CFrame = CFrame.lookAt(rootPart.Position, lookAtPos)

    local cam = workspace.CurrentCamera
    cam.CFrame = CFrame.lookAt(cam.CFrame.Position, targetRoot.Position)

    local tool = char:FindFirstChildOfClass("Tool")
    if not tool then
        local backpack = LocalPlayer:FindFirstChild("Backpack")
        if backpack then
            tool = backpack:FindFirstChildOfClass("Tool")
            if tool then
                local hum = char:FindFirstChildOfClass("Humanoid")
                if hum then hum:EquipTool(tool) end
            end
        end
    end
    
    if tool then
        tool:Activate()
        if unequipAfterUse then
            local hum = char:FindFirstChildOfClass("Humanoid")
            if hum then
                task.delay(0.1, function()
                    hum:UnequipTools()
                end)
            end
        end
    end
end

local function isHitClimbable(hit)
    if not hit or not hit.Instance then return false end
    local pName = string.lower(hit.Instance.Name)
    return hit.Instance:IsA("TrussPart") or string.find(pName, "ladder") or string.find(pName, "escalera") or string.find(pName, "climb") or string.find(pName, "truss")
end

local function startTrackingLogic()
    startRigCheck()
    
    trackingTask = task.spawn(function()
        while isTracking and isScriptRunning do
            local char = LocalPlayer.Character
            if not char then 
                task.wait(0.5)
                continue 
            end
            
            local humanoid = char:FindFirstChildOfClass("Humanoid")
            local rootPart = getSafeRootPart(char)
            
            if not humanoid or not rootPart then
                task.wait(0.5)
                continue 
            end
            
            if humanoid.Health <= 0 then
                notify("Sistema", "Jugador eliminado. Pathfinder pausado (esperando reaparición)...")
                
                -- Pausar el bucle hasta que el jugador reaparezca y tenga un Humanoid con vida
                repeat
                    task.wait(0.5)
                    char = LocalPlayer.Character
                    humanoid = char and char:FindFirstChildOfClass("Humanoid")
                    rootPart = getSafeRootPart(char)
                until not isTracking or not isScriptRunning or (humanoid and humanoid.Health > 0 and rootPart)
                
                if not isTracking or not isScriptRunning then break end
                
                notify("Sistema", "¡Reaparecido! Reanudando pathfinder...")
                continue
            end
            
            if humanoid.Sit and allowJumping then humanoid.Jump = true end
            
            local canJumpHighEnough = true
            if humanoid.UseJumpPower then
                if humanoid.JumpPower < 50 then canJumpHighEnough = false end
            else
                if humanoid.JumpHeight < 7.2 then canJumpHighEnough = false end
            end
            
            humanoid.AutoJumpEnabled = canJumpHighEnough and allowJumping
            
            local bestTargetChar = nil
            local bestTargetRoot = nil
            local bestWaypoints = nil
            local isPartialPath = false
            local validTargetPos = nil
            
            clearPathVisuals()
            
            if movementMode == "ClickToMove" then
                if clickToMovePos then
                    validTargetPos = clickToMovePos
                    bestTargetRoot = {Position = clickToMovePos} 
                else
                    task.wait(0.2)
                    continue
                end
            elseif movementMode == "Merodear" then
                if not wanderTarget or (rootPart.Position - wanderTarget).Magnitude < 5 then
                    local angle = math.random() * math.pi * 2
                    local distance = math.random(25, 60)
                    local randomPos = rootPart.Position + Vector3.new(math.cos(angle) * distance, 0, math.sin(angle) * distance)
                    wanderTarget = getFloorPosition(randomPos)
                end
                validTargetPos = wanderTarget
                bestTargetRoot = {Position = wanderTarget} 
            else
                local sortedTargets = getTargetsSortedByDistance()
                for _, targetInfo in ipairs(sortedTargets) do
                    local targetChar = targetInfo.character
                    local targetRoot = getSafeRootPart(targetChar)
                    if not targetRoot then continue end
                    
                    local distanceToTarget = (rootPart.Position - targetRoot.Position).Magnitude
                    if movementMode == "Perseguir" and deadRadius > 0 and distanceToTarget <= deadRadius then
                        bestTargetChar = targetChar
                        bestTargetRoot = targetRoot
                        bestWaypoints = {} 
                        break
                    end
                    
                    if movementMode == "Huir" then
                        local runDirection = (rootPart.Position - targetRoot.Position).Unit
                        if runDirection.Magnitude ~= runDirection.Magnitude then runDirection = Vector3.new(1, 0, 0) end
                        local fleeDestination = rootPart.Position + (Vector3.new(runDirection.X, 0, runDirection.Z).Unit * 45)
                        validTargetPos = getFloorPosition(fleeDestination)
                    else
                        validTargetPos = getFloorPosition(targetRoot.Position)
                    end
                    
                    bestTargetChar = targetChar
                    bestTargetRoot = targetRoot
                    break
                end
            end
            
            if bestTargetRoot and validTargetPos then
                local agentRadius = 1.8
                local agentHeight = 5.0
                if rootPart and rootPart.Size.Y > 3 then
                    agentRadius = (math.max(rootPart.Size.X, rootPart.Size.Z) / 2) + 0.2
                    agentHeight = rootPart.Size.Y + 3 
                end
                
                local pathParams = {
                    AgentRadius = agentRadius,
                    AgentHeight = agentHeight,
                    AgentCanJump = canJumpHighEnough and allowJumping,
                    AgentCanDrop = true, 
                    AgentMaxDrop = maxDropDistance,
                    WaypointSpacing = math.max(1.5, agentRadius),
                    Costs = { Climbable = 1 }
                }
                
                local path = PathfindingService:CreatePath(pathParams)
                local success = pcall(function()
                    path:ComputeAsync(rootPart.Position, validTargetPos)
                end)
                
                if success then
                    local waypoints = path:GetWaypoints()
                    local pathStatus = path.Status
                    
                    if pathStatus == Enum.PathStatus.Success or pathStatus == Enum.PathStatus.ClosestNoPath then
                        for w = 1, #waypoints - 1 do
                            if (waypoints[w].Position.Y - waypoints[w+1].Position.Y) > maxDropDistance then
                                pathStatus = Enum.PathStatus.NoPath
                                break
                            end
                        end
                    end
                    
                    if autoJumpHazards and (pathStatus == Enum.PathStatus.Success or pathStatus == Enum.PathStatus.ClosestNoPath) then
                        local filtered = {}
                        local i = 1
                        local rp = RaycastParams.new()
                        if char then rp.FilterDescendantsInstances = {char, pathVisualsFolder} end
                        rp.FilterType = Enum.RaycastFilterType.Exclude

                        while i <= #waypoints do
                            table.insert(filtered, waypoints[i])
                            local hit = workspace:Raycast(waypoints[i].Position + Vector3.new(0, 2, 0), Vector3.new(0, -6, 0), rp)
                            
                            local isOnHazard = false
                            if hit and hit.Instance then
                                for _, child in ipairs(hit.Instance:GetChildren()) do
                                    if child:IsA("PathfindingModifier") and (child.Label == "Hazard" or child.Label == "SmallHazard") then
                                        isOnHazard = true; break
                                    end
                                end
                            end
                            
                            if isOnHazard then
                                local nextSafe = i + 1
                                for j = i + 1, #waypoints do
                                    local h2 = workspace:Raycast(waypoints[j].Position + Vector3.new(0, 2, 0), Vector3.new(0, -6, 0), rp)
                                    local isSafe = true
                                    if h2 and h2.Instance then
                                        for _, c in ipairs(h2.Instance:GetChildren()) do
                                            if c:IsA("PathfindingModifier") and (c.Label == "Hazard" or c.Label == "SmallHazard") then
                                                isSafe = false; break
                                            end
                                        end
                                    end
                                    if isSafe then nextSafe = j; break end
                                end
                                if nextSafe <= #waypoints then
                                    waypoints[nextSafe].Action = Enum.PathWaypointAction.Jump
                                    table.insert(filtered, waypoints[nextSafe])
                                    i = nextSafe + 1
                                else
                                    break
                                end
                            else
                                i = i + 1
                            end
                        end
                        waypoints = filtered
                    end
                    
                    if pathStatus == Enum.PathStatus.Success then
                        drawPath(waypoints, Color3.fromRGB(255, 255, 255), 0.7)
                        bestWaypoints = waypoints
                    elseif pathStatus == Enum.PathStatus.ClosestNoPath then
                        if #waypoints > 0 then
                            drawPath(waypoints, Color3.fromRGB(255, 255, 255), 0.85)
                            bestWaypoints = waypoints
                            isPartialPath = true
                        else
                            wanderTarget = nil 
                        end
                    else
                        wanderTarget = nil 
                    end
                end
                
                if bestWaypoints then
                    activeTargetRoot = bestTargetRoot
                    local initialTargetPos = bestTargetRoot.Position
                    local currentDist = (rootPart.Position - initialTargetPos).Magnitude
                    
                    handleAutoAttack()
                    
                    if movementMode == "Perseguir" and deadRadius > 0 and currentDist <= deadRadius then
                        clearPathVisuals()
                        humanoid:MoveTo(rootPart.Position)
                        currentLookTarget = bestTargetRoot.Position 
                        task.wait(0.1) 
                    else
                        local recalcThreshold = 2 * math.sqrt(currentDist)
                        recalcThreshold = math.max(recalcThreshold, 2)
                        
                        drawPath(bestWaypoints, Color3.fromRGB(0, 255, 150), 0.3)
                        
                        local lastJumpTime = 0
                        local function forzarSalto()
                            if not canJumpHighEnough or not allowJumping then return end 
                            if humanoid:GetState() == Enum.HumanoidStateType.Climbing then return end 
                            
                            if tick() - lastJumpTime > 0.4 then
                                if not ignoreSpecialBlocks then
                                    local checkCFrame = rootPart.CFrame * CFrame.new(0, 10, 0) 
                                    local checkSize = Vector3.new(3, 20, 3) 
                                    local overlapParams = OverlapParams.new()
                                    overlapParams.FilterDescendantsInstances = {char, pathVisualsFolder}
                                    overlapParams.FilterType = Enum.RaycastFilterType.Exclude
                                    
                                    local partsAbove = workspace:GetPartBoundsInBox(checkCFrame, checkSize, overlapParams)
                                    for _, part in ipairs(partsAbove) do
                                        local isHazard = false
                                        for _, child in ipairs(part:GetChildren()) do
                                            if child:IsA("PathfindingModifier") and child.Label == "Hazard" then
                                                isHazard = true
                                                break
                                            end
                                        end
                                        if isHazard then return end
                                    end
                                end

                                humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
                                humanoid.Jump = true
                                lastJumpTime = tick()
                            end
                        end
                        
                        local startIndex = 1
                        local skipDistance = math.clamp(humanoid.WalkSpeed * 0.12, 1.5, 6)
                        
                        for i = 1, #bestWaypoints do
                            local flatWp = Vector3.new(bestWaypoints[i].Position.X, 0, bestWaypoints[i].Position.Z)
                            local flatRoot = Vector3.new(rootPart.Position.X, 0, rootPart.Position.Z)
                            if (flatRoot - flatWp).Magnitude > skipDistance then
                                startIndex = i
                                break
                            end
                        end
                        if startIndex > #bestWaypoints then startIndex = #bestWaypoints end
                        
                        local shouldRecalculate = false
                        
                        for i = startIndex, #bestWaypoints do
                            local waypoint = bestWaypoints[i]
                            if not isTracking or not isScriptRunning or humanoid.Health <= 0 then break end
                            if shouldRecalculate then break end
                            if not LocalPlayer.Character or not getSafeRootPart(LocalPlayer.Character) then break end
                            
                            if movementMode ~= "ClickToMove" and movementMode ~= "Merodear" and bestTargetRoot then
                                local targetDeviance = (bestTargetRoot.Position - initialTargetPos).Magnitude
                                if targetDeviance > recalcThreshold then
                                    shouldRecalculate = true
                                    break
                                end
                            end
                            
                            if movementMode == "Perseguir" and deadRadius > 0 and (rootPart.Position - bestTargetRoot.Position).Magnitude <= deadRadius then
                                break
                            end
                            
                            local waypointPosition = waypoint.Position
                            currentLookTarget = waypointPosition
                            
                            if waypoint.Action == Enum.PathWaypointAction.Jump then
                                forzarSalto()
                            end

                            humanoid:MoveTo(waypointPosition)
                            
                            local waypointStartTime = tick()
                            local lastStuckPos = rootPart.Position
                            local stuckTimer = 0
                            local flatDistance = math.huge
                            
                            repeat 
                                local dt = task.wait()
                                if not isTracking or not isScriptRunning or humanoid.Health <= 0 or not LocalPlayer.Character or not getSafeRootPart(LocalPlayer.Character) then 
                                    break 
                                end

                                if isJumpingHazard then
                                    local currentState = humanoid:GetState()
                                    local isMidAir = (currentState == Enum.HumanoidStateType.Freefall or currentState == Enum.HumanoidStateType.Jumping)
                                    
                                    if tick() - globalHeartbeatJumpTime > 0.5 and not isMidAir then
                                        isJumpingHazard = false
                                        globalHeartbeatJumpTime = 0
                                        humanoid:MoveTo(waypointPosition)
                                    end
                                end                          
                                local currentRoot = getSafeRootPart(LocalPlayer.Character)
                                local flatWaypoint = Vector3.new(waypointPosition.X, 0, waypointPosition.Z)
                                local flatPlayer = Vector3.new(currentRoot.Position.X, 0, currentRoot.Position.Z)
                                flatDistance = (flatWaypoint - flatPlayer).Magnitude
                                
                                handleAutoAttack()
                                
                                if not isJumpingHazard then
                                    if movementMode ~= "ClickToMove" and movementMode ~= "Merodear" and bestTargetRoot then
                                        local targetDeviance = (bestTargetRoot.Position - initialTargetPos).Magnitude
                                        if targetDeviance > recalcThreshold then
                                            shouldRecalculate = true
                                            break
                                        end
                                    end
                                    
                                    if humanoid.Sit and allowJumping then
                                        humanoid.Jump = true
                                        shouldRecalculate = true 
                                        break
                                    end
                                    
                                    local rayParams = RaycastParams.new()
                                    rayParams.FilterDescendantsInstances = {char, pathVisualsFolder}
                                    rayParams.FilterType = Enum.RaycastFilterType.Exclude
                                    
                                    if waypointPosition.Y > (currentRoot.Position.Y + 1.2) and flatDistance <= 4.0 then
                                        forzarSalto()
                                    end
                                    
                                    local rawLookDir = humanoid.MoveDirection
                                    if rawLookDir.Magnitude < 0.01 then
                                        rawLookDir = currentRoot.CFrame.LookVector
                                    end
                                    local flatRaw = Vector3.new(rawLookDir.X, 0, rawLookDir.Z)
                                    local flatLookDir = (flatRaw.Magnitude > 0.01) and (flatRaw.Unit * 2.5) or (rawLookDir * 2.5)
                                    local dynamicSize = char:GetExtentsSize()
                                    
                                    local hitKnee = workspace:Raycast(currentRoot.Position - Vector3.new(0, (dynamicSize.Y / 2) * 0.5, 0), flatLookDir, rayParams)
                                    local hitWaist = workspace:Raycast(currentRoot.Position, flatLookDir, rayParams)
                                    
                                    if hitKnee or hitWaist then 
                                        if not (isHitClimbable(hitKnee) or isHitClimbable(hitWaist) or humanoid:GetState() == Enum.HumanoidStateType.Climbing) then
                                            forzarSalto() 
                                        end
                                    end
                                    
                                    local currentFlatPos = Vector3.new(currentRoot.Position.X, 0, currentRoot.Position.Z)
                                    local lastFlatPos = Vector3.new(lastStuckPos.X, 0, lastStuckPos.Z)
                                    local distMoved = (currentFlatPos - lastFlatPos).Magnitude
                                    
                                    if distMoved < 0.05 then 
                                        stuckTimer = stuckTimer + dt
                                        if stuckTimer > 0.6 then 
                                            forzarSalto()
                                            shouldRecalculate = true 
                                            break 
                                        end
                                    else
                                        stuckTimer = 0
                                        lastStuckPos = currentRoot.Position
                                    end
                                end
                                
                                if tick() - waypointStartTime > 1.5 then break end
                            until flatDistance <= 2.5 or not isTracking or shouldRecalculate
                            
                            if isTracking and not shouldRecalculate and not isJumpingHazard then
                                local fallStart = tick()
                                local currentState = humanoid:GetState()
                                
                                local targetAirPos = waypointPosition
                                if bestWaypoints and i < #bestWaypoints then
                                    targetAirPos = bestWaypoints[i + 1].Position
                                end
                                
                                while (currentState == Enum.HumanoidStateType.Freefall or currentState == Enum.HumanoidStateType.Jumping) and isTracking do
                                    if tick() - fallStart > 1.5 then break end 
                                    task.wait(0.05)
                                    currentState = humanoid:GetState()
                                    humanoid:MoveTo(targetAirPos)
                                end
                            end
                        end
                    end
                    
                    if isPartialPath and movementMode == "Perseguir" then
                        currentLookTarget = bestTargetRoot.Position
                        if bestTargetRoot.Position.Y > rootPart.Position.Y + 2 then forzarSalto() end
                        task.wait(0.2)
                    end
                end
            else
                activeTargetRoot = nil
                clearPathVisuals()
                humanoid:MoveTo(rootPart.Position)
                currentLookTarget = nil 
                task.wait(0.4)
            end
        end
    end)
end

-- ==========================================
-- SISTEMA DE SALTO INDEPENDIENTE DIAGONAL
-- ==========================================
table.insert(connections, RunService.Heartbeat:Connect(function()
    if not isScriptRunning or not isTracking or not autoJumpHazards then return end
    
    local char = LocalPlayer.Character
    if not char then return end
    
    local humanoid = char:FindFirstChildOfClass("Humanoid")
    local rootPart = getSafeRootPart(char)
    
    if humanoid and rootPart and humanoid.Health > 0 then
        local state = humanoid:GetState()
        
        local function getHazardJumpDirection()
            local jumpDir = Vector3.zero
            if humanoid.MoveDirection.Magnitude > 0.01 then
                jumpDir = Vector3.new(humanoid.MoveDirection.X, 0, humanoid.MoveDirection.Z).Unit
            elseif currentLookTarget then
                local routeDir = (currentLookTarget - rootPart.Position)
                if routeDir.Magnitude > 0.01 then
                    jumpDir = Vector3.new(routeDir.X, 0, routeDir.Z).Unit
                end
            end
            if jumpDir == Vector3.zero or jumpDir.Magnitude ~= jumpDir.Magnitude then
                local lookDir = rootPart.CFrame.LookVector
                jumpDir = Vector3.new(lookDir.X, 0, lookDir.Z).Unit
            end
            return jumpDir
        end
        
        if state == Enum.HumanoidStateType.Landed or state == Enum.HumanoidStateType.Running then
            if tick() - globalHeartbeatJumpTime > 0.5 then
                isJumpingHazard = false
            end
        end
        
        if isJumpingHazard then
            if tick() - globalHeartbeatJumpTime < 0.2 then
                humanoid.Jump = true
            end
        end

        if state ~= Enum.HumanoidStateType.Jumping and state ~= Enum.HumanoidStateType.Freefall and state ~= Enum.HumanoidStateType.Climbing then
            local overlapParams = OverlapParams.new()
            overlapParams.FilterDescendantsInstances = {char, pathVisualsFolder}
            overlapParams.FilterType = Enum.RaycastFilterType.Exclude
            
            local function checkModifiers(part)
                for _, child in ipairs(part:GetChildren()) do
                    if child:IsA("PathfindingModifier") and child.Label == "SmallHazard" then
                        return true
                    end
                end
                return false
            end
            
            local rayParams = RaycastParams.new()
            rayParams.FilterDescendantsInstances = {char, pathVisualsFolder}
            rayParams.FilterType = Enum.RaycastFilterType.Exclude

            local dir = humanoid.MoveDirection
            if dir.Magnitude < 0.01 then dir = rootPart.CFrame.LookVector end
            local flatDir = Vector3.new(dir.X, 0, dir.Z).Unit
            
            if flatDir.Magnitude > 0 then
                local predictPos = rootPart.Position + (flatDir * 2.5) 
                local predictRay = workspace:Raycast(predictPos, Vector3.new(0, -4, 0), rayParams)
                
                if predictRay and predictRay.Instance and checkModifiers(predictRay.Instance) then
                    humanoid.Jump = true
                    humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
                    isJumpingHazard = true
                    hazardJumpDirection = getHazardJumpDirection()
                    globalHeartbeatJumpTime = tick()
                    return 
                end
            end
            
            local checkSize = char:GetExtentsSize() + Vector3.new(0.5, 1, 0.5)
            local partsTouching = workspace:GetPartBoundsInBox(rootPart.CFrame, checkSize, overlapParams)
            
            for _, part in ipairs(partsTouching) do
                local floorName = string.lower(part.Name)
                local isHazard = part:IsA("Seat") or part:IsA("VehicleSeat") or
                                 string.find(floorName, "conveyor") or string.find(floorName, "belt") or 
                                 string.find(floorName, "cinta") or string.find(floorName, "asiento") or 
                                 string.find(floorName, "seat") or
                                 (part.Anchored and part.AssemblyLinearVelocity.Magnitude > 1)

                if not isHazard then
                    isHazard = checkModifiers(part)
                end

                if isHazard then
                    if humanoid.Sit then humanoid.Sit = false end
                    humanoid.Jump = true
                    humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
                    isJumpingHazard = true
                    hazardJumpDirection = getHazardJumpDirection()
                    globalHeartbeatJumpTime = tick()
                    break
                end
            end
        end
    end
end))

-- ==========================================
-- SISTEMA ESP VISUAL
-- ==========================================
RunService:BindToRenderStep("XenoESPVisuals", Enum.RenderPriority.Camera.Value + 1, function()
    if not isScriptRunning or not isESPEnabled then return end

    local validTargets = getTargetsSortedByDistance()
    local currentValid = {}

    for _, targetInfo in ipairs(validTargets) do
        local char = targetInfo.character
        local root = getSafeRootPart(char)
        if not root then continue end

        currentValid[char] = true

        if not espBoxes[char] then
            local proxy = Instance.new("Part")
            proxy.Size = Vector3.new(2.5, 2.5, 2.5)
            proxy.Transparency = 1
            proxy.Anchored = true
            proxy.CanCollide = false
            proxy.CFrame = CFrame.new(root.Position) 
            proxy.Parent = espVisualsFolder

            local adorn = Instance.new("BoxHandleAdornment")
            adorn.Name = "XenoESPAdornment"
            adorn.Adornee = proxy
            adorn.AlwaysOnTop = true
            adorn.ZIndex = 5
            adorn.Size = proxy.Size
            adorn.Transparency = 0.5
            adorn.Color3 = Color3.fromRGB(0, 255, 0)
            adorn.Parent = proxy

            espBoxes[char] = {proxyPart = proxy, adornment = adorn}
        else
            espBoxes[char].proxyPart.CFrame = CFrame.new(root.Position)
        end
    end

    for char, box in pairs(espBoxes) do
        if not currentValid[char] then
            if box.proxyPart then box.proxyPart:Destroy() end
            espBoxes[char] = nil
        end
    end
end)

-- ==========================================
-- FUERZA DE CÁMARA
-- ==========================================
RunService:BindToRenderStep("XenoCameraForce", Enum.RenderPriority.Camera.Value + 5, function(deltaTime)
    if not isScriptRunning then return end

    if isTracking and currentLookTarget then
        local char = LocalPlayer.Character
        if not char then return end
        
        local head = char:FindFirstChild("Head")
        local rootPart = getSafeRootPart(char)
        if not head and not rootPart then return end
        
        local charExtents = char:GetExtentsSize()
        local headPosition = head and head.Position or (rootPart.Position + Vector3.new(0, (charExtents.Y / 2) - 0.5, 0))
        
        local camera = workspace.CurrentCamera
        local camDist = (camera.CFrame.Position - headPosition).Magnitude
        
        local isInDeadZone = false
        if activeTargetRoot and deadRadius > 0 and movementMode == "Perseguir" then
            if (rootPart.Position - activeTargetRoot.Position).Magnitude <= deadRadius then
                isInDeadZone = true
            end
        end

        if isFreelock and (camDist <= 1.5 or isInDeadZone) then
            return 
        end
        
        if camDist <= 1.5 then
            local camPos = camera.CFrame.Position
            local lookAtTarget = Vector3.new(currentLookTarget.X, camPos.Y, currentLookTarget.Z)
            
            if (lookAtTarget - camPos).Magnitude > 0.1 then
                local targetCFrame = CFrame.lookAt(camPos, lookAtTarget)
                camera.CFrame = camera.CFrame:Lerp(targetCFrame, deltaTime * 12)
            end
        end
    end
end)

-- ==========================================
-- MANEJO DE ENTRADA (TECLAS Y RETENCIÓN F6)
-- ==========================================
local f6PressTime = 0
local f6TriggeredHold = false

table.insert(connections, UserInputService.InputBegan:Connect(function(input, gameProcessed)
    if not isScriptRunning then return end
    
    if input.KeyCode == Enum.KeyCode.F1 then
        if settingsFrame then settingsFrame.Visible = not settingsFrame.Visible end
    elseif input.KeyCode == Enum.KeyCode.F4 then
        isTracking = not isTracking
        if isTracking then
            lastRigType = nil 
            notify("IY Pathfinder", string.upper(movementMode) .. ": ACTIVADO")
            startTrackingLogic()
        else
            notify("IY Pathfinder", "Sistema: DESACTIVADO")
            activeTargetRoot = nil
            clearPathVisuals()
            currentLookTarget = nil 
            isJumpingHazard = false
            
            if trackingTask then task.cancel(trackingTask) trackingTask = nil end
            if rigCheckTask then task.cancel(rigCheckTask) rigCheckTask = nil end
            
            local char = LocalPlayer.Character
            if char then
                local humanoid = char:FindFirstChildOfClass("Humanoid")
                local rootPart = getSafeRootPart(char)
                if humanoid and rootPart then humanoid:MoveTo(rootPart.Position) end
            end
        end
    elseif input.KeyCode == Enum.KeyCode.F2 then
        if entityMode == "Jugadores" then
            entityMode = "NPCs"
            notify("Entidades", "Objetivos: SOLO NPC's")
        elseif entityMode == "NPCs" then
            entityMode = "Ambos"
            notify("Entidades", "Objetivos: JUGADORES Y NPC's")
        else
            entityMode = "Jugadores"
            notify("Entidades", "Objetivos: SOLO JUGADORES")
        end
        manualTargetEntity = nil
    elseif input.KeyCode == Enum.KeyCode.F5 then
        if targetMode == "Todos" then
            targetMode = "Enemigos"
            notify("Filtro", "Modo: SOLO ENEMIGOS")
        elseif targetMode == "Enemigos" then
            targetMode = "Aliados"
            notify("Filtro", "Modo: SOLO ALIADOS")
        else
            targetMode = "Todos"
            notify("Filtro", "Modo: TODOS LOS JUGADORES/NPCs")
        end
    elseif input.KeyCode == Enum.KeyCode.F6 then
        f6PressTime = tick()
        f6TriggeredHold = false
        
        task.delay(0.4, function()
            if UserInputService:IsKeyDown(Enum.KeyCode.F6) and not f6TriggeredHold then
                f6TriggeredHold = true
                manualTargetEntity = nil
                notify("Objetivo", "Modo: AUTO")
            end
        end)
    elseif input.KeyCode == Enum.KeyCode.F3 then
        if movementMode == "Perseguir" then
            movementMode = "Huir"
            notify("Comportamiento", "Modo: HUIR DEL OBJETIVO")
        elseif movementMode == "Huir" then
            movementMode = "Merodear"
            notify("Comportamiento", "Modo: MERODEAR ALEATORIAMENTE")
        elseif movementMode == "Merodear" then
            movementMode = "ClickToMove"
            notify("Comportamiento", "Modo: CLICK TO MOVE")
        else
            movementMode = "Perseguir"
            notify("Comportamiento", "Modo: PERSEGUIR AL OBJETIVO")
        end
    end
end))

table.insert(connections, UserInputService.InputEnded:Connect(function(input)
    if not isScriptRunning then return end
    
    if input.KeyCode == Enum.KeyCode.F6 then
        if not f6TriggeredHold and (tick() - f6PressTime < 0.4) then
            local entitiesList = getAvailableEntities()
            if #entitiesList == 0 then
                notify("Selección", "No hay entidades disponibles (" .. entityMode .. ").")
                return
            end
            
            table.sort(entitiesList, function(a, b) return string.lower(a.name) < string.lower(b.name) end)
            
            local currentIndex = 0
            if manualTargetEntity then
                for i, ent in ipairs(entitiesList) do
                    if ent.isPlayer and manualTargetEntity.isPlayer and ent.accountName == manualTargetEntity.accountName then
                        currentIndex = i
                        break
                    elseif not ent.isPlayer and not manualTargetEntity.isPlayer and ent.name == manualTargetEntity.name then
                        currentIndex = i
                        break
                    end
                end
            end
            
            currentIndex = currentIndex + 1
            if currentIndex > #entitiesList then
                manualTargetEntity = nil
                notify("Objetivo", "Modo: AUTO")
            else
                manualTargetEntity = entitiesList[currentIndex]
                notify("Objetivo", "Fijado en: " .. manualTargetEntity.name)
            end
        end
    end
end))

-- Cleanup global
globalEnv.XenoCleanup = function()
    isScriptRunning = false
    isTracking = false
    
    for _, conn in ipairs(connections) do
        if conn then conn:Disconnect() end
    end
    table.clear(connections)
    
    RunService:UnbindFromRenderStep("XenoCameraForce")
    RunService:UnbindFromRenderStep("XenoESPVisuals")
    
    if trackingTask then task.cancel(trackingTask) end
    if rigCheckTask then task.cancel(rigCheckTask) end
    
    if sg and sg.Parent then sg:Destroy() end
    if pathVisualsFolder and pathVisualsFolder.Parent then pathVisualsFolder:Destroy() end
end

Features & Information

An advanced pathfinder made just for fun.

Community Comments (0)

No comments yet for this script.

More Scripts for Universal Scripts