Further enhance, remove the offset, and add in another new algorithm that'll calculate the movements before it'll lock-on effectively with a complex heartbeat method and a firstchild targeting method. And remove the maintain lock-on.

```
--[[
    Optimized Lock-On and ESP Script with Enhanced Consistency
    - Removed ShiftLock support
    - Continuous and consistent lock-on functionality
    - Advanced Kalman Filter for robust movement prediction
    - Improved target selection and persistence mechanisms
    - Comprehensive debug logging for troubleshooting
--]]

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

-- Configuration
local DEBUG = true  -- Toggle debug logs
local ROTATION_SPEED = 25        -- Smooth rotation speed multiplier for smoother effect
local ESP_TEXT_PREFIX = "Targeted: " -- Prefix Text displayed in ESP
local ESP_COLOR = Color3.fromRGB(0, 255, 0)  -- Color of the ESP text
local LOCK_ON_KEY = Enum.KeyCode.E -- Key to toggle lock-on
local BACK_OFFSET = 5 -- Studs behind the target's torso to aim (adjustable)
local MAX_FOV_ANGLE = 60 -- Maximum angle (in degrees) for FOV-based target selection
local TARGET_PERSISTENCE_TIME = 0.5 -- Time in seconds to maintain lock-on after target leaves FOV

local GUI_CONFIG = {
    ScreenGuiName = "EnhancedLockOnESPGUI",
    FrameSize = UDim2.new(0, 220, 0, 350),
    FramePosition = UDim2.new(0, 10, 0.5, -175),
    ButtonSize = UDim2.new(1, -20, 0, 35),
    BodyParts = {
        "Left Arm",
        "Left Leg",
        "Torso",
        "Torso (Back)",
        "Head",
        "Right Leg",
        "Right Arm"
    },
    SelectedColor = Color3.fromRGB(70, 130, 180), -- Steel Blue
    UnselectedColor = Color3.fromRGB(50, 50, 50),
    HoverColor = Color3.fromRGB(100, 100, 100),
    TextColor = Color3.fromRGB(255, 255, 255),
    BackgroundColor = Color3.fromRGB(30, 30, 30),
    StrokeColor = Color3.fromRGB(255, 255, 255)
}

-- Debug Function
local function debugLog(message)
    if DEBUG then
        print("[EnhancedLockOnScript]: " .. 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 lockOnMode = false           -- Lock-On mode toggle
local selectedBodyPart = "Torso (Back)" -- Default selected body part
local targetLostTime = 0           -- Timer to handle target persistence

-- 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)

-- Mapping for R6 and R15 body parts
local bodyPartMappings = {
    ["Left Arm"] = isR15 and "LeftUpperArm" or "Left Arm",
    ["Left Leg"] = isR15 and "LeftUpperLeg" or "Left Leg",
    ["Torso"] = torsoPartName,
    ["Torso (Back)"] = torsoPartName, -- Special handling
    ["Head"] = "Head",
    ["Right Leg"] = isR15 and "RightUpperLeg" or "Right Leg",
    ["Right Arm"] = isR15 and "RightUpperArm" or "Right Arm"
}

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

-- Helper Function: Calculate angle between two vectors
local function calculateAngle(direction)
    local viewVector = CurrentCamera.CFrame.LookVector
    local directionUnit = direction.Unit
    local dotProduct = viewVector:Dot(directionUnit)
    local angle = math.acos(math.clamp(dotProduct, -1, 1)) * (180 / math.pi) -- Clamp to avoid NaNs
    return angle
end

-- Advanced Kalman Filter Implementation for Enhanced Prediction
local KalmanFilter = {}
KalmanFilter.__index = KalmanFilter

function KalmanFilter.new(dt)
    local self = setmetatable({}, KalmanFilter)
    -- State vector components
    self.position = Vector3.new(0, 0, 0)
    self.velocity = Vector3.new(0, 0, 0)
    
    -- Covariance matrix represented as separate components for simplicity
    self.P = Vector3.new(1, 1, 1) -- Initial uncertainty per axis
    self.dt = dt or (1/60) -- Time step
    
    -- Process and measurement noise
    self.processNoise = 0.1
    self.measurementNoise = 1.0
    return self
end

function KalmanFilter:update(measurement)
    -- Predict Step
    self.position = self.position + self.velocity * self.dt
    self.P = self.P + Vector3.new(self.processNoise, self.processNoise, self.processNoise)
    
    -- Calculate Kalman Gain
    local K = Vector3.new(
        self.P.X / (self.P.X + self.measurementNoise),
        self.P.Y / (self.P.Y + self.measurementNoise),
        self.P.Z / (self.P.Z + self.measurementNoise)
    )
    
    -- Update Step
    local y = measurement - self.position
    self.position = self.position + Vector3.new(
        K.X * y.X,
        K.Y * y.Y,
        K.Z * y.Z
    )
    self.P = Vector3.new(
        (1 - K.X) * self.P.X,
        (1 - K.Y) * self.P.Y,
        (1 - K.Z) * self.P.Z
    )
    
    -- Estimate velocity
    -- Assuming acceleration is negligible for simplicity
    self.velocity = (self.position - (self.position - self.velocity * self.dt)) / self.dt
end

-- Create a table to hold Kalman Filters for each target
local kalmanFilters = {}

-- Helper Function: Find or create a Kalman Filter for a target
local function getKalmanFilter(target)
    if not kalmanFilters[target] then
        kalmanFilters[target] = KalmanFilter.new()
        -- Initialize with target's current position
        local targetPartName = bodyPartMappings[selectedBodyPart]
        local targetPart = target.Character and target.Character:FindFirstChild(targetPartName)
        if targetPart then
            kalmanFilters[target].position = targetPart.Position
            kalmanFilters[target].velocity = Vector3.new(0, 0, 0)
            debugLog("Kalman Filter initialized for " .. target.Name)
        else
            debugLog("Cannot initialize Kalman Filter: " .. target.Name .. " lacks the part " .. (targetPartName or "nil"))
        end
    end
    return kalmanFilters[target]
end

-- Helper Function: Find the best target based on FOV and distance
local function findBestTarget()
    local bestTarget = nil
    local shortestDistance = math.huge
    local bestAngle = MAX_FOV_ANGLE

    for _, otherPlayer in ipairs(Players:GetPlayers()) do
        if otherPlayer ~= player and otherPlayer.Character and hasHumanoid(otherPlayer.Character) then
            local targetPartName = bodyPartMappings[selectedBodyPart]
            local otherTargetPart = otherPlayer.Character:FindFirstChild(targetPartName)
            if otherTargetPart and otherTargetPart:IsA("BasePart") then
                local direction = otherTargetPart.Position - humanoidRootPart.Position
                local distance = direction.Magnitude
                local angle = calculateAngle(direction)
                
                if angle <= MAX_FOV_ANGLE and distance < shortestDistance then
                    shortestDistance = distance
                    bestTarget = otherPlayer
                    bestAngle = angle
                end
            end
        end
    end

    if bestTarget then
        debugLog(string.format("Best target found: %s | Distance: %.2f | Angle: %.2f", bestTarget.Name, shortestDistance, bestAngle))
    else
        debugLog("No suitable target found within FOV.")
    end

    return bestTarget
end

-- Function: Toggle Lock-On to the Best Target based on layered selection
local function toggleLockOn()
    if lockOnMode then
        -- Deselect the current target
        debugLog("Deselecting current target: " .. (trackedTarget and trackedTarget.Name or "None"))
        trackedTarget = nil
        lockOnMode = false
        targetLostTime = 0
        if espIndicator then
            espIndicator:Destroy()
            espIndicator = nil
            debugLog("ESP indicator destroyed.")
        end
    else
        -- Find and select the best target
        local bestPlayer = findBestTarget()
        if bestPlayer and bestPlayer.Character then
            trackedTarget = bestPlayer.Character
            lockOnMode = true
            debugLog("Tracking new target: " .. bestPlayer.Name)
            -- Create ESP indicator
            local targetPartName = bodyPartMappings[selectedBodyPart]
            local targetPart = trackedTarget:FindFirstChild(targetPartName)
            if targetPart 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 = targetPart
                espIndicator.Size = UDim2.new(0, 150, 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 .. trackedTarget.Name .. " (" .. selectedBodyPart .. ")"
                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 " .. bestPlayer.Name .. " targeting " .. selectedBodyPart)
            else
                debugLog("Selected body part '" .. targetPartName .. "' not found on " .. bestPlayer.Name)
                trackedTarget = nil
            end
        else
            debugLog("No valid target to track.")
        end
    end
end

-- Function: Predict Future Position Based on Target's Velocity using Enhanced Kalman Filter
local function getPredictedPosition(targetCharacter, deltaTime)
    local targetPartName = bodyPartMappings[selectedBodyPart]
    local targetPart = targetCharacter:FindFirstChild(targetPartName)
    if not targetPart then
        debugLog("Target does not have the part: " .. targetPartName)
        return nil
    end

    -- Get current position
    local currentPosition = targetPart.Position

    -- Update Kalman Filter with the current position
    local kalFilter = getKalmanFilter(player)
    if not kalFilter then
        debugLog("Kalman Filter not available for " .. targetCharacter.Name)
        return nil
    end
    kalFilter:update(currentPosition)

    -- Get predicted position
    local predictedPosition = kalFilter.position + kalFilter.velocity * deltaTime

    -- Enhanced Handling for "Torso (Back)"
    if selectedBodyPart == "Torso (Back)" then
        local targetHumanoid = targetCharacter:FindFirstChildOfClass("Humanoid")
        if targetHumanoid then
            local rootPart = targetHumanoid.RootPart or targetCharacter:FindFirstChild("HumanoidRootPart") or targetCharacter:FindFirstChild("UpperTorso")
            if rootPart then
                -- Calculate dynamic back offset based on target's velocity and orientation
                local dynamicBackOffset = BACK_OFFSET + math.clamp(kalFilter.velocity.Magnitude * 0.2, 0, 5)
                predictedPosition = predictedPosition - (rootPart.CFrame.LookVector * dynamicBackOffset)
                debugLog("Calculated back position using dynamic LookVector offset for " .. targetCharacter.Name)
            else
                debugLog("Root part not found for back position calculation on " .. targetCharacter.Name)
            end
        else
            debugLog("Humanoid not found on " .. targetCharacter.Name)
        end
    end

    debugLog(string.format("Final predicted target position: (%.2f, %.2f, %.2f)", predictedPosition.X, predictedPosition.Y, predictedPosition.Z))
    return predictedPosition
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 target position.")
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 target position.")
end

-- Function: Rotate to Target (Currently Only Smooth Rotation Implemented)
local function rotateToTarget(deltaTime)
    if not trackedTarget then return end

    local targetPartName = bodyPartMappings[selectedBodyPart]
    local targetPart = trackedTarget:FindFirstChild(targetPartName)
    if targetPart and targetPart:IsA("BasePart") then
        local predictedPosition = getPredictedPosition(trackedTarget, deltaTime)
        if predictedPosition then
            -- Currently using smooth rotation
            smoothRotateToPosition(predictedPosition, deltaTime)

            -- Hitbox Detection: Ensure predicted position is within part bounds
            local partSize = targetPart.Size
            local partPosition = targetPart.Position
            local deltaPosition = predictedPosition - partPosition

            local withinX = math.abs(deltaPosition.X) <= (partSize.X / 2 + (selectedBodyPart == "Torso (Back)" and BACK_OFFSET or 0))
            local withinY = math.abs(deltaPosition.Y) <= (partSize.Y / 2)
            local withinZ = math.abs(deltaPosition.Z) <= (partSize.Z / 2 + (selectedBodyPart == "Torso (Back)" and BACK_OFFSET or 0))

            if withinX and withinY and withinZ then
                debugLog("Predicted position is within the part's hitbox.")
            else
                debugLog("Predicted position is outside the part's hitbox.")
            end
        else
            debugLog("Failed to get predicted target position.")
        end
    else
        debugLog("Target part '" .. targetPartName .. "' is invalid or missing.")
    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
    lockOnMode = false
    targetLostTime = 0
    if espIndicator then
        espIndicator:Destroy()
        espIndicator = nil
        debugLog("ESP indicator destroyed due to target removal.")
    end
    -- Reset Kalman Filter for the target
    kalmanFilters[trackedTarget] = nil
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: Update Camera (No ShiftLock, so this might be omitted or used differently)
local function updateCamera(deltaTime)
    -- Since ShiftLock is removed, we might only update ESP or other visuals here
    -- Alternatively, keep this function for any future camera updates
end

-- Function: Create and Setup the Body Part Selection GUI with Enhanced Aesthetics
local function createBodyPartSelectionGUI()
    -- Check if the GUI already exists to prevent duplication
    if player.PlayerGui:FindFirstChild(GUI_CONFIG.ScreenGuiName) then
        debugLog("GUI already exists. Skipping creation.")
        return
    end

    -- Create ScreenGui
    local screenGui = Instance.new("ScreenGui")
    screenGui.Name = GUI_CONFIG.ScreenGuiName
    screenGui.Parent = player.PlayerGui
    screenGui.ResetOnSpawn = false

    -- Create Background Frame
    local frame = Instance.new("Frame")
    frame.Size = GUI_CONFIG.FrameSize
    frame.Position = GUI_CONFIG.FramePosition
    frame.BackgroundColor3 = GUI_CONFIG.BackgroundColor
    frame.BackgroundTransparency = 0.8
    frame.BorderSizePixel = 0
    frame.Parent = screenGui

    -- Add UIStroke for Frame
    local frameStroke = Instance.new("UIStroke")
    frameStroke.Color = GUI_CONFIG.StrokeColor
    frameStroke.Thickness = 2
    frameStroke.Parent = frame

    -- Create Title
    local title = Instance.new("TextLabel")
    title.Size = UDim2.new(1, 0, 0, 40)
    title.Position = UDim2.new(0, 0, 0, 0)
    title.BackgroundTransparency = 1
    title.Text = "Lock-On ESP"
    title.Font = Enum.Font.GothamBold
    title.TextSize = 24
    title.TextColor3 = GUI_CONFIG.TextColor
    title.TextStrokeTransparency = 0.5
    title.TextXAlignment = Enum.TextXAlignment.Center
    title.Parent = frame

    -- Create UIListLayout for organized buttons
    local uiListLayout = Instance.new("UIListLayout")
    uiListLayout.Parent = frame
    uiListLayout.FillDirection = Enum.FillDirection.Vertical
    uiListLayout.SortOrder = Enum.SortOrder.LayoutOrder
    uiListLayout.Padding = UDim.new(0, 10)
    uiListLayout.VerticalAlignment = Enum.VerticalAlignment.Top

    -- Create UIListLayoutPadding to position buttons below the title
    local layoutPadding = Instance.new("UIPadding")
    layoutPadding.PaddingTop = UDim.new(0, 50)
    layoutPadding.Parent = frame

    -- Function to handle body part selection
    local function selectBodyPart(bodyPart, button)
        selectedBodyPart = bodyPart
        debugLog("Selected body part: " .. bodyPart)
        toggleLockOn() -- Deselect current target

        -- Update ESP text if a target is already locked on
        if lockOnMode and espIndicator then
            espIndicator:Destroy()
            espIndicator = nil
            debugLog("ESP indicator destroyed due to body part change.")
            toggleLockOn() -- Re-select target with new body part
        end

        -- Update button colors to indicate selection
        for _, btn in ipairs(frame:GetChildren()) do
            if btn:IsA("TextButton") then
                btn.BackgroundColor3 = GUI_CONFIG.UnselectedColor
            end
        end
        button.BackgroundColor3 = GUI_CONFIG.SelectedColor
    end

    -- Create Buttons for each Body Part with Enhanced Aesthetics
    for _, bodyPart in ipairs(GUI_CONFIG.BodyParts) do
        local button = Instance.new("TextButton")
        button.Size = GUI_CONFIG.ButtonSize
        button.Text = bodyPart
        button.Font = Enum.Font.Gotham
        button.TextSize = 18
        button.TextColor3 = GUI_CONFIG.TextColor
        button.BackgroundColor3 = (bodyPart == selectedBodyPart) and GUI_CONFIG.SelectedColor or GUI_CONFIG.UnselectedColor
        button.AutoButtonColor = false
        button.BorderSizePixel = 0
        button.Parent = frame

        -- Add UIStroke for Buttons
        local buttonStroke = Instance.new("UIStroke")
        buttonStroke.Color = GUI_CONFIG.StrokeColor
        buttonStroke.Thickness = 1
        buttonStroke.Parent = button

        -- Hover Effects
        button.MouseEnter:Connect(function()
            if bodyPart ~= selectedBodyPart then
                button.BackgroundColor3 = GUI_CONFIG.HoverColor
            end
        end)

        button.MouseLeave:Connect(function()
            if bodyPart ~= selectedBodyPart then
                button.BackgroundColor3 = GUI_CONFIG.UnselectedColor
            end
        end)

        button.MouseButton1Click:Connect(function()
            selectBodyPart(bodyPart, button)
        end)
    end

    debugLog("Enhanced Body Part Selection GUI created.")
end

-- Call the function to create the GUI
createBodyPartSelectionGUI()

-- Function: Setup Lock-On Toggle
local function setupLockOnToggle()
    UserInputService.InputBegan:Connect(function(input, gameProcessed)
        if gameProcessed then return end

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

-- Function: Handle Target Persistence
local function handleTargetPersistence(deltaTime)
    if not lockOnMode and trackedTarget then
        local targetPartName = bodyPartMappings[selectedBodyPart]
        local targetPart = trackedTarget:FindFirstChild(targetPartName)
        if targetPart and targetPart:IsA("BasePart") then
            local direction = targetPart.Position - humanoidRootPart.Position
            local angle = calculateAngle(direction)
            if angle <= MAX_FOV_ANGLE then
                targetLostTime = 0
            else
                targetLostTime = targetLostTime + deltaTime
                debugLog("Target out of FOV. Incrementing lost time: " .. targetLostTime)
                if targetLostTime >= TARGET_PERSISTENCE_TIME then
                    debugLog("Target persistence time exceeded. Removing lock-on.")
                    onTrackedTargetRemoved()
                end
            end
        else
            targetLostTime = targetLostTime + deltaTime
            debugLog("Target part missing. Incrementing lost time: " .. targetLostTime)
            if targetLostTime >= TARGET_PERSISTENCE_TIME then
                debugLog("Target persistence time exceeded. Removing lock-on due to missing part.")
                onTrackedTargetRemoved()
            end
        end
    end
end

-- Function: Maintain Lock-On
local function maintainLockOn()
    if not lockOnMode then return end

    if not trackedTarget then
        debugLog("No tracked target to maintain lock-on.")
        return
    end

    local targetPartName = bodyPartMappings[selectedBodyPart]
    local targetPart = trackedTarget:FindFirstChild(targetPartName)
    if not targetPart or not targetPart:IsA("BasePart") then
        debugLog("Tracked target's part is invalid or missing.")
        onTrackedTargetRemoved()
        return
    end

    local direction = targetPart.Position - humanoidRootPart.Position
    local angle = calculateAngle(direction)

    if angle > MAX_FOV_ANGLE then
        targetLostTime = targetLostTime + 0.016 -- Approximate deltaTime for 60fps
        if targetLostTime >= TARGET_PERSISTENCE_TIME then
            debugLog("Tracked target moved out of FOV. Removing lock-on.")
            onTrackedTargetRemoved()
        end
    else
        targetLostTime = 0
    end
end

-- Consolidated RenderStepped Connection
RunService.RenderStepped:Connect(function(deltaTime)
    pcall(function()
        if lockOnMode and trackedTarget then
            rotateToTarget(deltaTime)
            -- updateCamera(deltaTime) -- Removed since ShiftLock is no longer supported
        end
        handleTargetPersistence(deltaTime)
    end)
end)

-- Event Listeners

-- Setup Lock-On Toggle
setupLockOnToggle()

-- Function: Smoothly switch to a new target if current target is lost but within persistence time
local function autoReacquireTarget()
    if not lockOnMode and not trackedTarget then
        local bestPlayer = findBestTarget()
        if bestPlayer and bestPlayer.Character then
            trackedTarget = bestPlayer.Character
            lockOnMode = true
            debugLog("Auto-reacquired target: " .. bestPlayer.Name)
            -- Create ESP indicator
            local targetPartName = bodyPartMappings[selectedBodyPart]
            local targetPart = trackedTarget:FindFirstChild(targetPartName)
            if targetPart 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 = targetPart
                espIndicator.Size = UDim2.new(0, 150, 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 .. trackedTarget.Name .. " (" .. selectedBodyPart .. ")"
                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 " .. bestPlayer.Name .. " targeting " .. selectedBodyPart)
            else
                debugLog("Selected body part '" .. targetPartName .. "' not found on " .. bestPlayer.Name)
                trackedTarget = nil
            end
        end
    end
end

-- Optionally, include autoReacquireTarget in RenderStepped if necessary
-- RunService.RenderStepped:Connect(function(deltaTime)
--     pcall(function()
--         autoReacquireTarget()
--     end)
-- end)