Further enhance and add in lock-on.

```
-- LocalScript: Player Tracking and ESP Tool
-- Place this script in StarterPlayer > StarterPlayerScripts

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

-- Configuration Table
local CONFIG = {
    ROTATION = {
        Kp = 15,                 -- Proportional gain
        Ki = 5,                  -- Integral gain
        Kd = 3,                  -- Derivative gain
        MaxTorque = 50,          -- Maximum rotational force
        MinThreshold = 0.01      -- Minimum angle threshold to apply torque
    },
    ESP = {
        Text = "Targeted",
        Color = Color3.fromRGB(255, 0, 0),
        Size = UDim2.new(0, 100, 0, 50),
        Offset = Vector3.new(0, 2, 0)
    },
    TRACKING = {
        PredictionFactor = 0.3,  -- Seconds ahead to predict
        MaxDistance = 100,       -- Maximum distance to track a target
        RefreshInterval = 1      -- Seconds between target searches
    },
    DEBUG = {
        Enabled = true,
        Verbose = true
    }
}

-- Variables
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
local playerGui = player:WaitForChild("PlayerGui")

local trackedTarget = nil
local espIndicator = nil

-- PID Controller State
local pidState = {
    integral = 0,
    previousError = 0
}

-- External table to store Kalman data for each target
local kalmanData = {}

-- Debug Functions
local function debugLog(message, level)
    level = level or "INFO"
    if CONFIG.DEBUG.Enabled then
        if CONFIG.DEBUG.Verbose or level ~= "DEBUG" then
            print(string.format("[TrackerDebug][%s]: %s", level, message))
        end
    end
end

-- Helper Functions
local function hasHumanoid(model)
    return model and model:FindFirstChildOfClass("Humanoid") ~= nil
end

local function squaredDistance(pos1, pos2)
    local diff = pos1 - pos2
    return diff.X * diff.X + diff.Y * diff.Y + diff.Z * diff.Z
end

-- Advanced Prediction Function: Basic Kalman Filter Implementation
local function predictPosition(target)
    local hrp = target:FindFirstChild("HumanoidRootPart")
    local humanoid = target:FindFirstChildOfClass("Humanoid")
    
    if not hrp or not humanoid then
        debugLog("Target missing HumanoidRootPart or Humanoid.", "ERROR")
        return nil
    end

    -- Initialize Kalman data for the target if not already present
    if not kalmanData[target] then
        kalmanData[target] = {
            Position = hrp.Position,
            Velocity = Vector3.new(0, 0, 0),
            LastUpdate = tick()
        }
    end

    local data = kalmanData[target]
    local currentTick = tick()
    local timeElapsed = currentTick - data.LastUpdate

    if timeElapsed >= 1/60 then -- Update at ~60Hz
        local newVelocity = (hrp.Position - data.Position) / timeElapsed
        data.Velocity = newVelocity
        data.Position = hrp.Position
        data.LastUpdate = currentTick
    end

    -- Predict future position
    local predictedPos = hrp.Position + (data.Velocity * CONFIG.TRACKING.PredictionFactor)
    debugLog(string.format("Predicted Position for %s: %s", target.Parent.Name, tostring(predictedPos)), "DEBUG")
    return predictedPos
end

-- Target Finding Function with Refresh Interval
local function findClosestPlayer()
    local closestPlayer = nil
    local shortestDistanceSq = CONFIG.TRACKING.MaxDistance * CONFIG.TRACKING.MaxDistance

    for _, otherPlayer in ipairs(Players:GetPlayers()) do
        if otherPlayer ~= player and otherPlayer.Character and hasHumanoid(otherPlayer.Character) then
            local otherHRP = otherPlayer.Character:FindFirstChild("HumanoidRootPart")
            if otherHRP then
                local distanceSq = squaredDistance(otherHRP.Position, humanoidRootPart.Position)
                if distanceSq < shortestDistanceSq then
                    shortestDistanceSq = distanceSq
                    closestPlayer = otherPlayer
                end
            end
        end
    end

    if closestPlayer then
        debugLog("Closest player found: " .. closestPlayer.Name, "INFO")
    else
        debugLog("No players within tracking range.", "INFO")
    end

    return closestPlayer
end

-- ESP Management Functions
local function createESP(target)
    if not target or not target:FindFirstChild("Head") then
        debugLog("Cannot create ESP: Target does not have a Head.", "ERROR")
        return nil
    end

    -- Create BillboardGui
    local billboard = Instance.new("BillboardGui")
    billboard.Adornee = target.Head
    billboard.Size = CONFIG.ESP.Size
    billboard.StudsOffset = CONFIG.ESP.Offset
    billboard.AlwaysOnTop = true
    billboard.Name = "TargetESP"

    -- Create TextLabel
    local textLabel = Instance.new("TextLabel")
    textLabel.Parent = billboard
    textLabel.Size = UDim2.new(1, 0, 1, 0)
    textLabel.BackgroundTransparency = 1
    textLabel.Text = CONFIG.ESP.Text
    textLabel.TextColor3 = CONFIG.ESP.Color
    textLabel.Font = Enum.Font.SourceSansBold
    textLabel.TextScaled = true
    textLabel.TextStrokeTransparency = 0.8

    -- Parent to PlayerGui
    billboard.Parent = playerGui
    debugLog("ESP Indicator created for " .. target.Parent.Name, "DEBUG")

    return billboard
end

local function removeESP()
    if espIndicator then
        espIndicator:Destroy()
        espIndicator = nil
        debugLog("ESP Indicator removed.", "DEBUG")
    end
end

-- PID Controller Function
local function pidController(targetCFrame, deltaTime)
    -- Desired look vector
    local desiredLook = (targetCFrame.Position - humanoidRootPart.Position).Unit
    local currentLook = humanoidRootPart.CFrame.LookVector.Unit

    -- Calculate the angle between current and desired directions
    local dotProduct = math.clamp(currentLook:Dot(desiredLook), -1, 1) -- Ensure within acos range
    local angle = math.acos(dotProduct)

    -- Calculate the rotation direction
    local cross = currentLook:Cross(desiredLook)
    local rotationDirection = (cross.Y >= 0) and 1 or -1 -- Assuming Y-axis is up

    -- Error terms
    local error = angle
    pidState.integral = pidState.integral + error * deltaTime
    local derivative = (error - pidState.previousError) / deltaTime

    -- PID Output
    local output = (CONFIG.ROTATION.Kp * error) + (CONFIG.ROTATION.Ki * pidState.integral) + (CONFIG.ROTATION.Kd * derivative)
    output = math.clamp(output, 0, CONFIG.ROTATION.MaxTorque)

    -- Apply rotation if error is significant
    if error > CONFIG.ROTATION.MinThreshold then
        humanoidRootPart.CFrame = humanoidRootPart.CFrame * CFrame.Angles(0, rotationDirection * math.rad(output), 0)
        debugLog(string.format("Applying PID Output: %f", output), "DEBUG")
    end

    -- Update previous error
    pidState.previousError = error
end

-- Rotation and ESP Update Function
local function updateTracking(deltaTime)
    if not trackedTarget or not trackedTarget.Parent or not trackedTarget:FindFirstChild("HumanoidRootPart") then
        debugLog("Tracked target is invalid. Removing tracking.", "WARN")
        trackedTarget = nil
        removeESP()
        return
    end

    -- Predict target position
    local predictedPos = predictPosition(trackedTarget)
    if not predictedPos then
        debugLog("Failed to predict target position. Removing tracking.", "ERROR")
        trackedTarget = nil
        removeESP()
        return
    end

    -- Rotate towards predicted position using PID controller
    local targetCFrame = CFrame.new(humanoidRootPart.Position, predictedPos)
    pidController(targetCFrame, deltaTime)

    -- Update ESP
    if espIndicator and trackedTarget:FindFirstChild("Head") then
        espIndicator.Adornee = trackedTarget.Head
    else
        debugLog("Target lost Head. Removing ESP.", "WARN")
        removeESP()
        trackedTarget = nil
    end
end

-- Target Selection Toggle Function
local function toggleLockOn()
    if trackedTarget then
        -- Deselect current target
        debugLog("Deselecting target: " .. trackedTarget.Parent.Name, "INFO")
        trackedTarget = nil
        removeESP()
    else
        -- Find and select the closest target
        local closestPlayer = findClosestPlayer()
        if closestPlayer and closestPlayer.Character then
            trackedTarget = closestPlayer.Character
            espIndicator = createESP(trackedTarget)
            debugLog("Tracking target: " .. trackedTarget.Parent.Name, "INFO")
        else
            debugLog("No valid target found to track.", "INFO")
        end
    end
end

-- Event Connections
local inputConnection
local characterAddedConnection
local heartbeatConnection

-- Function to handle player removal
local function onPlayerRemoving(player)
    if player.Character and kalmanData[player.Character] then
        kalmanData[player.Character] = nil
        debugLog("Kalman data cleaned up for " .. player.Name, "DEBUG")
    end
end

-- Function to handle character removal
local function onCharacterRemoving(character)
    if kalmanData[character] then
        kalmanData[character] = nil
        debugLog("Kalman data cleaned up for character.", "DEBUG")
    end
end

-- Initialize Function
local function initialize()
    -- External table for kalman data is already initialized above

    -- Input Listener for E key
    inputConnection = UserInputService.InputBegan:Connect(function(input, gameProcessed)
        if gameProcessed then return end
        if input.KeyCode == Enum.KeyCode.E then
            toggleLockOn()
        end
    end)
    debugLog("Input connection established for toggleLockOn.", "DEBUG")

    -- Character Respawn Listener
    characterAddedConnection = player.CharacterAdded:Connect(function(newCharacter)
        character = newCharacter
        humanoidRootPart = character:WaitForChild("HumanoidRootPart")
        pidState = { integral = 0, previousError = 0 }
        trackedTarget = nil
        removeESP()
        debugLog("Character respawned. Resetting tracking.", "INFO")
    end)

    -- Heartbeat Listener for Smooth Updates
    heartbeatConnection = RunService.Heartbeat:Connect(function(deltaTime)
        if trackedTarget then
            updateTracking(deltaTime)
        end
    end)
    debugLog("Heartbeat connection established for tracking updates.", "DEBUG")

    -- Connect to PlayerRemoving
    Players.PlayerRemoving:Connect(onPlayerRemoving)

    -- Connect to existing players' character removal
    for _, p in ipairs(Players:GetPlayers()) do
        if p.Character then
            p.Character.AncestryChanged:Connect(function(_, parent)
                if not parent then
                    onCharacterRemoving(p.Character)
                end
            end)
        end
    end

    -- Connect to future players' character removal
    Players.PlayerAdded:Connect(function(p)
        p.CharacterAdded:Connect(function(c)
            c.AncestryChanged:Connect(function(_, parent)
                if not parent then
                    onCharacterRemoving(c)
                end
            end)
        end)
    end)
end

-- Cleanup Function
local function cleanup()
    if inputConnection then
        inputConnection:Disconnect()
        debugLog("Input connection disconnected.", "DEBUG")
    end
    if characterAddedConnection then
        characterAddedConnection:Disconnect()
        debugLog("CharacterAdded connection disconnected.", "DEBUG")
    end
    if heartbeatConnection then
        heartbeatConnection:Disconnect()
        debugLog("Heartbeat connection disconnected.", "DEBUG")
    end
    removeESP()
    -- Clear all Kalman data
    for k in pairs(kalmanData) do
        kalmanData[k] = nil
    end
    debugLog("Cleanup complete. All connections disconnected and resources freed.", "INFO")
end

-- Monitor Ancestry Changes for Cleanup
script.AncestryChanged:Connect(function(_, parent)
    if not parent then
        -- Script is being removed
        cleanup()
    end
end)

-- Initialize Script
initialize()
debugLog("Tracking script initialized successfully.", "INFO")
```

Reference Script (REFERENCE ONLY):

```
-- LocalScript: Player Tracking and ESP Tool
-- Place this script in StarterPlayer > StarterPlayerScripts

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

-- Configuration Table
local CONFIG = {
    ROTATION = {
        Kp = 15,                 -- Proportional gain
        Ki = 5,                  -- Integral gain
        Kd = 3,                  -- Derivative gain
        MaxTorque = 50,          -- Maximum rotational force
        MinThreshold = 0.01      -- Minimum angle threshold to apply torque
    },
    ESP = {
        Text = "Targeted",
        Color = Color3.fromRGB(255, 0, 0),
        Size = UDim2.new(0, 100, 0, 50),
        Offset = Vector3.new(0, 2, 0)
    },
    TRACKING = {
        PredictionFactor = 0.3,  -- Seconds ahead to predict
        MaxDistance = 100,       -- Maximum distance to track a target
        RefreshInterval = 1      -- Seconds between target searches
    },
    DEBUG = {
        Enabled = true,
        Verbose = true
    }
}

-- Variables
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
local playerGui = player:WaitForChild("PlayerGui")

local trackedTarget = nil
local espIndicator = nil

-- PID Controller State
local pidState = {
    integral = 0,
    previousError = 0
}

-- External table to store Kalman data for each target
local kalmanData = {}

-- Debug Functions
local function debugLog(message, level)
    level = level or "INFO"
    if CONFIG.DEBUG.Enabled then
        if CONFIG.DEBUG.Verbose or level ~= "DEBUG" then
            print(string.format("[TrackerDebug][%s]: %s", level, message))
        end
    end
end

-- Helper Functions
local function hasHumanoid(model)
    return model and model:FindFirstChildOfClass("Humanoid") ~= nil
end

local function squaredDistance(pos1, pos2)
    local diff = pos1 - pos2
    return diff.X * diff.X + diff.Y * diff.Y + diff.Z * diff.Z
end

-- Advanced Prediction Function: Basic Kalman Filter Implementation
local function predictPosition(target)
    local hrp = target:FindFirstChild("HumanoidRootPart")
    local humanoid = target:FindFirstChildOfClass("Humanoid")
    
    if not hrp or not humanoid then
        debugLog("Target missing HumanoidRootPart or Humanoid.", "ERROR")
        return nil
    end

    -- Initialize Kalman data for the target if not already present
    if not kalmanData[target] then
        kalmanData[target] = {
            Position = hrp.Position,
            Velocity = Vector3.new(0, 0, 0),
            LastUpdate = tick()
        }
    end

    local data = kalmanData[target]
    local currentTick = tick()
    local timeElapsed = currentTick - data.LastUpdate

    if timeElapsed >= 1/60 then -- Update at ~60Hz
        local newVelocity = (hrp.Position - data.Position) / timeElapsed
        data.Velocity = newVelocity
        data.Position = hrp.Position
        data.LastUpdate = currentTick
    end

    -- Predict future position
    local predictedPos = hrp.Position + (data.Velocity * CONFIG.TRACKING.PredictionFactor)
    debugLog(string.format("Predicted Position for %s: %s", target.Parent.Name, tostring(predictedPos)), "DEBUG")
    return predictedPos
end

-- Target Finding Function with Refresh Interval
local function findClosestPlayer()
    local closestPlayer = nil
    local shortestDistanceSq = CONFIG.TRACKING.MaxDistance * CONFIG.TRACKING.MaxDistance

    for _, otherPlayer in ipairs(Players:GetPlayers()) do
        if otherPlayer ~= player and otherPlayer.Character and hasHumanoid(otherPlayer.Character) then
            local otherHRP = otherPlayer.Character:FindFirstChild("HumanoidRootPart")
            if otherHRP then
                local distanceSq = squaredDistance(otherHRP.Position, humanoidRootPart.Position)
                if distanceSq < shortestDistanceSq then
                    shortestDistanceSq = distanceSq
                    closestPlayer = otherPlayer
                end
            end
        end
    end

    if closestPlayer then
        debugLog("Closest player found: " .. closestPlayer.Name, "INFO")
    else
        debugLog("No players within tracking range.", "INFO")
    end

    return closestPlayer
end

-- ESP Management Functions
local function createESP(target)
    if not target or not target:FindFirstChild("Head") then
        debugLog("Cannot create ESP: Target does not have a Head.", "ERROR")
        return nil
    end

    -- Create BillboardGui
    local billboard = Instance.new("BillboardGui")
    billboard.Adornee = target.Head
    billboard.Size = CONFIG.ESP.Size
    billboard.StudsOffset = CONFIG.ESP.Offset
    billboard.AlwaysOnTop = true
    billboard.Name = "TargetESP"

    -- Create TextLabel
    local textLabel = Instance.new("TextLabel")
    textLabel.Parent = billboard
    textLabel.Size = UDim2.new(1, 0, 1, 0)
    textLabel.BackgroundTransparency = 1
    textLabel.Text = CONFIG.ESP.Text
    textLabel.TextColor3 = CONFIG.ESP.Color
    textLabel.Font = Enum.Font.SourceSansBold
    textLabel.TextScaled = true
    textLabel.TextStrokeTransparency = 0.8

    -- Parent to PlayerGui
    billboard.Parent = playerGui
    debugLog("ESP Indicator created for " .. target.Parent.Name, "DEBUG")

    return billboard
end

local function removeESP()
    if espIndicator then
        espIndicator:Destroy()
        espIndicator = nil
        debugLog("ESP Indicator removed.", "DEBUG")
    end
end

-- PID Controller Function
local function pidController(targetCFrame, deltaTime)
    -- Desired look vector
    local desiredLook = (targetCFrame.Position - humanoidRootPart.Position).Unit
    local currentLook = humanoidRootPart.CFrame.LookVector.Unit

    -- Calculate the angle between current and desired directions
    local dotProduct = math.clamp(currentLook:Dot(desiredLook), -1, 1) -- Ensure within acos range
    local angle = math.acos(dotProduct)

    -- Calculate the rotation direction
    local cross = currentLook:Cross(desiredLook)
    local rotationDirection = (cross.Y >= 0) and 1 or -1 -- Assuming Y-axis is up

    -- Error terms
    local error = angle
    pidState.integral = pidState.integral + error * deltaTime
    local derivative = (error - pidState.previousError) / deltaTime

    -- PID Output
    local output = (CONFIG.ROTATION.Kp * error) + (CONFIG.ROTATION.Ki * pidState.integral) + (CONFIG.ROTATION.Kd * derivative)
    output = math.clamp(output, 0, CONFIG.ROTATION.MaxTorque)

    -- Apply rotation if error is significant
    if error > CONFIG.ROTATION.MinThreshold then
        humanoidRootPart.CFrame = humanoidRootPart.CFrame * CFrame.Angles(0, rotationDirection * math.rad(output), 0)
        debugLog(string.format("Applying PID Output: %f", output), "DEBUG")
    end

    -- Update previous error
    pidState.previousError = error
end

-- Rotation and ESP Update Function
local function updateTracking(deltaTime)
    if not trackedTarget or not trackedTarget.Parent or not trackedTarget:FindFirstChild("HumanoidRootPart") then
        debugLog("Tracked target is invalid. Removing tracking.", "WARN")
        trackedTarget = nil
        removeESP()
        return
    end

    -- Predict target position
    local predictedPos = predictPosition(trackedTarget)
    if not predictedPos then
        debugLog("Failed to predict target position. Removing tracking.", "ERROR")
        trackedTarget = nil
        removeESP()
        return
    end

    -- Rotate towards predicted position using PID controller
    local targetCFrame = CFrame.new(humanoidRootPart.Position, predictedPos)
    pidController(targetCFrame, deltaTime)

    -- Update ESP
    if espIndicator and trackedTarget:FindFirstChild("Head") then
        espIndicator.Adornee = trackedTarget.Head
    else
        debugLog("Target lost Head. Removing ESP.", "WARN")
        removeESP()
        trackedTarget = nil
    end
end

-- Target Selection Toggle Function
local function toggleLockOn()
    if trackedTarget then
        -- Deselect current target
        debugLog("Deselecting target: " .. trackedTarget.Parent.Name, "INFO")
        trackedTarget = nil
        removeESP()
    else
        -- Find and select the closest target
        local closestPlayer = findClosestPlayer()
        if closestPlayer and closestPlayer.Character then
            trackedTarget = closestPlayer.Character
            espIndicator = createESP(trackedTarget)
            debugLog("Tracking target: " .. trackedTarget.Parent.Name, "INFO")
        else
            debugLog("No valid target found to track.", "INFO")
        end
    end
end

-- Event Connections
local inputConnection
local characterAddedConnection
local heartbeatConnection

-- Function to handle player removal
local function onPlayerRemoving(player)
    if player.Character and kalmanData[player.Character] then
        kalmanData[player.Character] = nil
        debugLog("Kalman data cleaned up for " .. player.Name, "DEBUG")
    end
end

-- Function to handle character removal
local function onCharacterRemoving(character)
    if kalmanData[character] then
        kalmanData[character] = nil
        debugLog("Kalman data cleaned up for character.", "DEBUG")
    end
end

-- Initialize Function
local function initialize()
    -- External table for kalman data is already initialized above

    -- Input Listener for E key
    inputConnection = UserInputService.InputBegan:Connect(function(input, gameProcessed)
        if gameProcessed then return end
        if input.KeyCode == Enum.KeyCode.E then
            toggleLockOn()
        end
    end)
    debugLog("Input connection established for toggleLockOn.", "DEBUG")

    -- Character Respawn Listener
    characterAddedConnection = player.CharacterAdded:Connect(function(newCharacter)
        character = newCharacter
        humanoidRootPart = character:WaitForChild("HumanoidRootPart")
        pidState = { integral = 0, previousError = 0 }
        trackedTarget = nil
        removeESP()
        debugLog("Character respawned. Resetting tracking.", "INFO")
    end)

    -- Heartbeat Listener for Smooth Updates
    heartbeatConnection = RunService.Heartbeat:Connect(function(deltaTime)
        if trackedTarget then
            updateTracking(deltaTime)
        end
    end)
    debugLog("Heartbeat connection established for tracking updates.", "DEBUG")

    -- Connect to PlayerRemoving
    Players.PlayerRemoving:Connect(onPlayerRemoving)

    -- Connect to existing players' character removal
    for _, p in ipairs(Players:GetPlayers()) do
        if p.Character then
            p.Character.AncestryChanged:Connect(function(_, parent)
                if not parent then
                    onCharacterRemoving(p.Character)
                end
            end)
        end
    end

    -- Connect to future players' character removal
    Players.PlayerAdded:Connect(function(p)
        p.CharacterAdded:Connect(function(c)
            c.AncestryChanged:Connect(function(_, parent)
                if not parent then
                    onCharacterRemoving(c)
                end
            end)
        end)
    end)
end

-- Cleanup Function
local function cleanup()
    if inputConnection then
        inputConnection:Disconnect()
        debugLog("Input connection disconnected.", "DEBUG")
    end
    if characterAddedConnection then
        characterAddedConnection:Disconnect()
        debugLog("CharacterAdded connection disconnected.", "DEBUG")
    end
    if heartbeatConnection then
        heartbeatConnection:Disconnect()
        debugLog("Heartbeat connection disconnected.", "DEBUG")
    end
    removeESP()
    -- Clear all Kalman data
    for k in pairs(kalmanData) do
        kalmanData[k] = nil
    end
    debugLog("Cleanup complete. All connections disconnected and resources freed.", "INFO")
end

-- Monitor Ancestry Changes for Cleanup
script.AncestryChanged:Connect(function(_, parent)
    if not parent then
        -- Script is being removed
        cleanup()
    end
end)

-- Initialize Script
initialize()
debugLog("Tracking script initialized successfully.", "INFO")