Add in shiftlock support as well as a more smoother predictive algorithm.

```
--[[
    Enhanced Lock-On and ESP Script with Track Layering and Close Handler
    - Always targets the closest torso (UpperTorso for R15, Torso for R6).
    - Implements an advanced prediction algorithm using velocity averaging.
    - Includes hitbox detection to ensure ESP accuracy.
    - Track layering to prioritize the closest target.
    - Implements a close handler that triggers when any player is within a specified close range.
    - Removes the Target Selection GUI for streamlined functionality.
    - Maintains comprehensive debugging for easier troubleshooting.
--]]

-- Services
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local GuiService = game:GetService("GuiService")

-- Configuration
local DEBUG = true  -- Toggle debug logs
local ROTATION_SPEED = 25       -- Smooth rotation speed multiplier
local ESP_TEXT_PREFIX = "Targeted:"      -- Prefix Text displayed in ESP
local ESP_COLOR = Color3.fromRGB(255, 0, 0)  -- Color of the ESP text
local PREDICTION_TIME_BASE = 0.5 -- Base time in seconds to predict target movement
local PREDICTION_TIME_ADJUSTMENT_FACTOR = 0.05 -- Factor to adjust prediction time based on distance
local VELOCITY_SAMPLES = 5 -- Number of samples to average for velocity
local LOCK_ON_KEY = Enum.KeyCode.E -- Key to toggle lock-on
local CLOSE_DISTANCE = 10 -- Distance in studs to trigger close handler (adjust as needed)

-- Debug Function
local function debugLog(message)
    if DEBUG then
        print("[LockOnScript]: " .. message)
    end
end

-- Variables
local player = Players.LocalPlayer
if not player then
    error("LocalPlayer not found!")
    return
end

local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
local trackedTarget = nil          -- Currently tracked target (another player)
local espIndicator = nil           -- BillboardGui for ESP
local instantRotation = false      -- Instant rotation toggle

-- Determine Rig Type and set the torso part name
local isR15 = humanoid.RigType == Enum.HumanoidRigType.R15
local torsoPartName = isR15 and "UpperTorso" or "Torso"
debugLog("Rig type determined: " .. (isR15 and "R15" or "R6"))
debugLog("Torso part set to: " .. torsoPartName)

-- Velocity Averaging Variables
local velocityHistory = {} -- Table to store velocity samples

-- Helper Function: Check if a model has a Humanoid
local function hasHumanoid(model)
    return model and model:FindFirstChildOfClass("Humanoid") ~= nil
end

-- Helper Function: Find the closest player to the local player
local function findClosestPlayer()
    local closestPlayer = nil
    local shortestDistance = math.huge

    for _, otherPlayer in ipairs(Players:GetPlayers()) do
        if otherPlayer ~= player and otherPlayer.Character and otherPlayer.Character:FindFirstChild(torsoPartName) then
            local otherTorso = otherPlayer.Character:FindFirstChild(torsoPartName)
            if otherTorso and otherTorso:IsA("BasePart") then
                local distance = (otherTorso.Position - humanoidRootPart.Position).Magnitude
                if distance < shortestDistance then
                    shortestDistance = distance
                    closestPlayer = otherPlayer
                end
            end
        end
    end

    if closestPlayer then
        debugLog("Closest player found: " .. closestPlayer.Name .. " with distance " .. string.format("%.2f", shortestDistance))
    else
        debugLog("No closest player found.")
    end

    return closestPlayer
end

-- Function: Toggle Lock-On to the Closest Player when E is pressed
local function toggleLockOn()
    if trackedTarget then
        -- Deselect the current target
        debugLog("Deselecting current target: " .. (trackedTarget.Name or "Unknown"))
        trackedTarget = nil
        if espIndicator then
            espIndicator:Destroy()
            espIndicator = nil
            debugLog("ESP indicator destroyed.")
        end
    else
        -- Find and select the closest player
        local closestPlayer = findClosestPlayer()
        if closestPlayer and closestPlayer.Character then
            trackedTarget = closestPlayer.Character
            debugLog("Tracking new target: " .. closestPlayer.Name)
            -- Create ESP indicator
            local targetTorso = trackedTarget:FindFirstChild(torsoPartName)
            if targetTorso then
                -- Ensure previous ESP is removed
                if espIndicator then
                    espIndicator:Destroy()
                    espIndicator = nil
                    debugLog("Previous ESP indicator destroyed.")
                end

                -- Create BillboardGui for ESP
                espIndicator = Instance.new("BillboardGui")
                espIndicator.Adornee = targetTorso
                espIndicator.Size = UDim2.new(0, 100, 0, 50)
                espIndicator.StudsOffset = Vector3.new(0, 2, 0)
                espIndicator.AlwaysOnTop = true
                espIndicator.Name = "TargetESP"

                -- Create TextLabel for ESP
                local textLabel = Instance.new("TextLabel")
                textLabel.Parent = espIndicator
                textLabel.Size = UDim2.new(1, 0, 1, 0)
                textLabel.BackgroundTransparency = 1
                textLabel.Text = ESP_TEXT_PREFIX .. " " .. torsoPartName
                textLabel.TextColor3 = ESP_COLOR
                textLabel.Font = Enum.Font.SourceSansBold
                textLabel.TextScaled = true
                textLabel.TextStrokeTransparency = 0.8

                -- Parent the ESP to the player's PlayerGui
                local playerGui = player:WaitForChild("PlayerGui")
                espIndicator.Parent = playerGui
                debugLog("ESP indicator created for " .. closestPlayer.Name)
            else
                debugLog("Torso part '" .. torsoPartName .. "' not found on " .. closestPlayer.Name)
                trackedTarget = nil
            end
        else
            debugLog("No valid closest player to track.")
        end
    end
end

-- Function: Predict Future Position Based on Target's Velocity Averaging
local function getPredictedPosition(targetCharacter)
    local targetTorso = targetCharacter:FindFirstChild(torsoPartName)
    if not targetTorso then
        debugLog("Target does not have " .. torsoPartName .. ".")
        return nil
    end

    -- Get current velocity
    local currentVelocity = targetTorso.Velocity

    -- Store velocity in history
    table.insert(velocityHistory, currentVelocity)
    if #velocityHistory > VELOCITY_SAMPLES then
        table.remove(velocityHistory, 1)
    end

    -- Calculate average velocity
    local avgVelocity = Vector3.new(0, 0, 0)
    for _, vel in ipairs(velocityHistory) do
        avgVelocity = avgVelocity + vel
    end
    avgVelocity = avgVelocity / #velocityHistory

    -- Calculate dynamic prediction time based on distance
    local distance = (targetTorso.Position - humanoidRootPart.Position).Magnitude
    local predictionTime = PREDICTION_TIME_BASE + (distance * PREDICTION_TIME_ADJUSTMENT_FACTOR)
    predictionTime = math.clamp(predictionTime, 0.3, 1.0) -- Clamp prediction time between 0.3 and 1.0 seconds

    -- Calculate predicted position
    local futurePosition = targetTorso.Position + (avgVelocity * predictionTime)
    debugLog(string.format("Predicted position: (%.2f, %.2f, %.2f); Prediction Time: %.2f", 
        futurePosition.X, futurePosition.Y, futurePosition.Z, predictionTime))
    
    return futurePosition
end

-- Function: Instantly rotate to face the predicted target position
local function instantRotateToPosition(targetPosition)
    if not targetPosition then return end

    local desiredCFrame = CFrame.new(humanoidRootPart.Position, targetPosition)
    humanoidRootPart.CFrame = desiredCFrame
    debugLog("Instantly rotated to face predicted position.")
end

-- Function: Smoothly rotate to face the predicted target position
local function smoothRotateToPosition(targetPosition, deltaTime)
    if not targetPosition then return end

    local direction = (Vector3.new(targetPosition.X, humanoidRootPart.Position.Y, targetPosition.Z) - humanoidRootPart.Position).Unit
    local desiredCFrame = CFrame.new(humanoidRootPart.Position, humanoidRootPart.Position + direction)

    -- Smoothly interpolate the CFrame
    humanoidRootPart.CFrame = humanoidRootPart.CFrame:Lerp(desiredCFrame, ROTATION_SPEED * deltaTime)
    debugLog("Smoothly rotated to face predicted position.")
end

-- Function: Rotate to Target (Instant or Smooth based on toggle)
local function rotateToTarget(deltaTime)
    if not trackedTarget then return end

    local targetTorso = trackedTarget:FindFirstChild(torsoPartName)
    if targetTorso and targetTorso:IsA("BasePart") then
        local predictedPosition = getPredictedPosition(trackedTarget)
        if predictedPosition then
            if instantRotation then
                instantRotateToPosition(predictedPosition)
            else
                smoothRotateToPosition(predictedPosition, deltaTime)
            end

            -- Hitbox Detection: Ensure predicted position is within torso bounds
            local torsoSize = targetTorso.Size
            local torsoPosition = targetTorso.Position
            local deltaPosition = predictedPosition - torsoPosition

            local withinX = math.abs(deltaPosition.X) <= (torsoSize.X / 2)
            local withinY = math.abs(deltaPosition.Y) <= (torsoSize.Y / 2)
            local withinZ = math.abs(deltaPosition.Z) <= (torsoSize.Z / 2)

            if withinX and withinY and withinZ then
                debugLog("Predicted position is within the torso hitbox.")
            else
                debugLog("Predicted position is outside the torso hitbox.")
            end
        else
            debugLog("Failed to get predicted position.")
        end
    else
        debugLog("Torso part '" .. torsoPartName .. "' is invalid or missing.")
    end
end

-- Function: Toggle Instant Rotation via Keybind (e.g., R)
local function setupInstantRotationToggle()
    local INSTANT_ROTATION_TOGGLE_KEY = Enum.KeyCode.R -- Choose your preferred key

    UserInputService.InputBegan:Connect(function(input, gameProcessed)
        if gameProcessed then return end

        if input.KeyCode == INSTANT_ROTATION_TOGGLE_KEY then
            instantRotation = not instantRotation
            debugLog("Instant Rotation set to: " .. tostring(instantRotation))
        end
    end)
end

-- Function: Clean up ESP when the tracked target dies or leaves
local function onTrackedTargetRemoved()
    if not trackedTarget then return end
    debugLog("Tracked target removed or died: " .. (trackedTarget.Name or "Unknown"))
    trackedTarget = nil
    if espIndicator then
        espIndicator:Destroy()
        espIndicator = nil
        debugLog("ESP indicator destroyed due to target removal.")
    end
    velocityHistory = {} -- Reset velocity history
end

-- Function: Monitor Tracked Target for Removal or Death
local function monitorTrackedTarget(targetCharacter)
    if not targetCharacter then return end

    local humanoid = targetCharacter:FindFirstChildOfClass("Humanoid")
    if humanoid then
        humanoid.Died:Connect(function()
            debugLog("Tracked target " .. (targetCharacter.Name or "Unknown") .. " has died.")
            onTrackedTargetRemoved()
        end)
    end

    targetCharacter.AncestryChanged:Connect(function()
        if not targetCharacter:IsDescendantOf(game) then
            debugLog("Tracked target " .. (targetCharacter.Name or "Unknown") .. " has left the game.")
            onTrackedTargetRemoved()
        end
    end)
end

-- Modify toggleLockOn to monitor the tracked target
local originalToggleLockOn = toggleLockOn
toggleLockOn = function()
    originalToggleLockOn()
    if trackedTarget then
        monitorTrackedTarget(trackedTarget)
    end
end

-- Function: Handle Character Respawn
player.CharacterAdded:Connect(function(newCharacter)
    debugLog("Character respawned.")
    character = newCharacter
    humanoid = character:WaitForChild("Humanoid")
    humanoidRootPart = character:WaitForChild("HumanoidRootPart")
    
    -- Determine rig type using RigType property
    isR15 = humanoid.RigType == Enum.HumanoidRigType.R15
    torsoPartName = isR15 and "UpperTorso" or "Torso"
    debugLog("New rig type determined: " .. (isR15 and "R15" or "R6"))
    
    -- Reset tracking and ESP on respawn
    onTrackedTargetRemoved()
end)

-- Function: Handle Close Proximity Events
local function handleCloseProximity()
    for _, otherPlayer in ipairs(Players:GetPlayers()) do
        if otherPlayer ~= player and otherPlayer.Character and otherPlayer.Character:FindFirstChild(torsoPartName) then
            local otherTorso = otherPlayer.Character:FindFirstChild(torsoPartName)
            if otherTorso and otherTorso:IsA("BasePart") then
                local distance = (otherTorso.Position - humanoidRootPart.Position).Magnitude
                if distance <= CLOSE_DISTANCE then
                    debugLog("Player " .. otherPlayer.Name .. " is within close proximity (" .. string.format("%.2f", distance) .. " studs).")
                    -- Trigger close handler actions here
                    -- Example Actions:
                    -- 1. Automatically unlock lock-on
                    if trackedTarget and trackedTarget == otherPlayer.Character then
                        debugLog("Closing lock-on due to close proximity to the target.")
                        toggleLockOn()
                    end
                    -- 2. Notify the player
                    print("Warning: " .. otherPlayer.Name .. " is very close to you!")
                end
            end
        end
    end
end

-- Setup Instant Rotation Toggle
setupInstantRotationToggle()

-- Event Listeners

-- Toggle Lock-On based on key presses
UserInputService.InputBegan:Connect(function(input, gameProcessed)
    if gameProcessed then return end

    if input.KeyCode == LOCK_ON_KEY then
        toggleLockOn()
    end
end)

-- Render Step: Continuously update rotation if a target is tracked
RunService.RenderStepped:Connect(function(deltaTime)
    if trackedTarget then
        pcall(function()
            rotateToTarget(deltaTime)
        end)
    end

    -- Handle Close Proximity Checks
    handleCloseProximity()
end)