Add in rotation for target tracking (that targets players that has humanoidrootpart and can target multiple players at once but in a smooth way) with a more accurate prediction algorithm

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

-- Local Player
local LocalPlayer = Players.LocalPlayer
local Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")

-- Configuration Settings
local Settings = {
    Autoparry = {
        Toggle = true,
        Range = 25,
        Delay = 0,
        Fov = 180,
        Facing = false,
        Dodgerange = 3,
        Aimhelper = false,
    },
    ESP = {
        Toggle = false,
        Config = {},
    },
    Tpaura = {
        Toggle = false,
    },
}

-- Animation Timings
local anims = {
    -- Saitama Animations
    ["rbxassetid://10469493270"] = {0, 0.30},
    ["rbxassetid://10469630950"] = {0, 0.30},
    ["rbxassetid://10469639222"] = {0, 0.30},
    ["rbxassetid://10469643643"] = {0, 0.30},
    -- Hunter Animations
    ["rbxassetid://13532562418"] = {0, 0.30},
    ["rbxassetid://13532600125"] = {0, 0.30},
    ["rbxassetid://13532604085"] = {0, 0.30},
    ["rbxassetid://13294471966"] = {0, 0.30},
    -- Cyborg Animations
    ["rbxassetid://13491635433"] = {0, 0.30},
    ["rbxassetid://13296577783"] = {0, 0.30},
    ["rbxassetid://13295919399"] = {0, 0.30},
    ["rbxassetid://13295936866"] = {0, 0.30},
    -- Ninja Animations
    ["rbxassetid://13370310513"] = {0, 0.30},
    ["rbxassetid://13390230973"] = {0, 0.30},
    ["rbxassetid://13378751717"] = {0, 0.30},
    ["rbxassetid://13378708199"] = {0, 0.30},
    abilities = {},
}

-- Dodge, Barrage, and Ability Timings
local dodges = {
    ["rbxassetid://10479335397"] = {0, 0.50},
    ["rbxassetid://13380255751"] = {0, 0.50},
}

local barrages = {
    ["rbxassetid://10466974800"] = {0.20, 1.80},
    ["rbxassetid://12534735382"] = {0.20, 1.80},
}

local abilities = {
    ["rbxassetid://10468665991"] = {0.15, 0.60},
    ["rbxassetid://13376869471"] = {0.05, 1},
    ["rbxassetid://13376962659"] = {0, 2},
    ["rbxassetid://12296882427"] = {0.05, 1},
    ["rbxassetid://13309500827"] = {0.05, 1},
    ["rbxassetid://13365849295"] = {0, 1},
    ["rbxassetid://13377153603"] = {0, 1},
    ["rbxassetid://12509505723"] = {0.09, 2},
}

-- Cooldown Management
local cooldown = false

-- Tracking Data Structures
local trackedPlayers = {}
local trackingInterval = 0.1 -- seconds between tracking updates

-- Prediction Settings
local predictionFactor = 0.5 -- seconds ahead to predict

-- Helper Functions

-- Find Closest Players within Range
local function getClosestPlayers()
    local closestPlayers = {}
    local localPos = HumanoidRootPart.Position

    for _, player in ipairs(Players:GetPlayers()) do
        if player ~= LocalPlayer and player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
            local pos = player.Character.HumanoidRootPart.Position
            local distance = (pos - localPos).Magnitude
            if distance < Settings.Autoparry.Range then
                table.insert(closestPlayers, {player = player, distance = distance, position = pos})
            end
        end
    end

    return closestPlayers
end

-- Check if Any Attack Animation is Playing
local function isAttacking(player)
    if not player.Character or not player.Character:FindFirstChildOfClass("Humanoid") then
        return false
    end

    local humanoid = player.Character.Humanoid
    for _, animTrack in ipairs(humanoid:GetPlayingAnimationTracks()) do
        if anims[animTrack.Animation.AnimationId] or dodges[animTrack.Animation.AnimationId] or abilities[animTrack.Animation.AnimationId] or barrages[animTrack.Animation.AnimationId] then
            return true
        end
    end

    return false
end

-- Check if Player is Facing Local Player
local function isFacing(player)
    if not Settings.Autoparry.Toggle or not Settings.Autoparry.Facing then
        return true
    end

    local playerHead = player.Character:FindFirstChild("Head")
    local localHead = Character:FindFirstChild("Head")

    if not playerHead or not localHead then
        return false
    end

    local playerDirection = playerHead.CFrame.LookVector
    local toLocal = (localHead.Position - playerHead.Position).Unit
    local dotProduct = playerDirection:Dot(toLocal)

    local angle = math.acos(dotProduct) * (180 / math.pi)
    return angle <= (Settings.Autoparry.Fov / 2)
end

-- Check if Parry Action is Allowed
local function canParry(player)
    return not Character:FindFirstChild("M1ing") and not isAttacking(player) and isFacing(player)
end

-- Perform Parry Action
local function performParry(action)
    if cooldown then return end

    cooldown = true
    task.delay(Settings.Autoparry.Delay, function()
        print("Parry Attempt | Action:", action)
        Character.Communicate:FireServer({
            Goal = "KeyPress",
            Key = Enum.KeyCode.F
        })
        task.delay(durations[action], function()
            Character.Communicate:FireServer({
                Goal = "KeyRelease",
                Key = Enum.KeyCode.F
            })
            cooldown = false
        end)
    end)
end

-- Look Towards Enemy
local function lookAt(enemyPosition)
    if Settings.Autoparry.Aimhelper then
        HumanoidRootPart.CFrame = CFrame.lookAt(HumanoidRootPart.Position, enemyPosition)
    end
end

-- Prediction Algorithm using Linear Extrapolation
local function predictPosition(playerData)
    local currentTime = tick()
    local history = playerData.history

    if #history < 2 then
        return playerData.position
    end

    local deltaTime = history[#history].time - history[#history - 1].time
    if deltaTime == 0 then return playerData.position end

    local velocity = (history[#history].position - history[#history - 1].position) / deltaTime
    local predictedPosition = playerData.position + velocity * predictionFactor
    return predictedPosition
end

-- Update Tracked Players' Data
local function updateTracking()
    local closestPlayers = getClosestPlayers()
    local currentTime = tick()

    for _, data in ipairs(closestPlayers) do
        local player = data.player
        if not trackedPlayers[player] then
            trackedPlayers[player] = {
                history = {},
                lastPosition = data.position,
                velocity = Vector3.new(0, 0, 0),
            }
        end

        local playerData = trackedPlayers[player]
        table.insert(playerData.history, {time = currentTime, position = data.position})

        -- Keep only the last few data points
        if #playerData.history > 10 then
            table.remove(playerData.history, 1)
        end

        -- Calculate Velocity
        if #playerData.history >= 2 then
            local first = playerData.history[1]
            local last = playerData.history[#playerData.history]
            local dt = last.time - first.time
            if dt > 0 then
                playerData.velocity = (last.position - first.position) / dt
            end
        end

        playerData.lastPosition = data.position
    end

    -- Remove players that are no longer in range
    for player, _ in pairs(trackedPlayers) do
        if not Players:GetPlayers():Find(function(p) return p == player end) or (player.Character and (player.Character.HumanoidRootPart.Position - HumanoidRootPart.Position).Magnitude > Settings.Autoparry.Range) then
            trackedPlayers[player] = nil
        end
    end
end

-- Parry Logic with Prediction
local function parry()
    for player, data in pairs(trackedPlayers) do
        if player.Character and player.Character:FindFirstChildOfClass("Humanoid") then
            local predictedPos = predictPosition(data)
            if canParry(player) then
                local humanoid = player.Character.Humanoid

                for _, animTrack in ipairs(humanoid:GetPlayingAnimationTracks()) do
                    local animId = animTrack.Animation.AnimationId
                    local actionType
                    if anims[animId] and animTrack.TimePosition >= anims[animId][1] and animTrack.TimePosition <= anims[animId][2] then
                        actionType = "anim"
                    elseif dodges[animId] and animTrack.TimePosition > dodges[animId][1] and animTrack.TimePosition < dodges[animId][2] then
                        actionType = "dodge"
                    elseif barrages[animId] and animTrack.TimePosition > barrages[animId][1] and animTrack.TimePosition < barrages[animId][2] then
                        actionType = "barrage"
                    elseif abilities[animId] and animTrack.TimePosition > abilities[animId][1] and animTrack.TimePosition < abilities[animId][2] then
                        actionType = "ability"
                    end

                    if actionType then
                        lookAt(predictedPos)
                        performParry(actionType)
                        break -- Only perform one parry per player per frame
                    end
                end
            end
        end
    end
end

-- Parry Action Duration Mapping
local durations = {
    ["anim"] = 0.3,
    ["dodge"] = 0.9,
    ["barrage"] = 0.9,
    ["ability"] = 0.6,
}

-- Initialize Tracking Loop
RunService.RenderStepped:Connect(function()
    if Settings.Autoparry.Toggle then
        parry()
    end
end)

-- Initialize Tracking Update Loop
RunService.Heartbeat:Connect(function()
    updateTracking()
end)

warn("Enhanced Autoparry Script Executed")