server position predictor OPEN SOURCE
Key RequiredUniversal

server position predictor OPEN SOURCE

Universal ScriptsimkaHUBsimkaHUB 790 views 268 executesUpdated Nov 28, 2025
2.5/ 5(6 votes)
3350% Positive
Lua Script•196 lines (6889 chars)
local Configuration = {
    Enabled = true,
    Parts = {
        'HumanoidRootPart', 'Head', 'Left Arm', 'Right Arm', 'Left Leg', 'Right Leg',
        'LeftUpperArm', 'RightUpperArm', 'LeftLowerArm', 'RightLowerArm',
        'LeftHand', 'RightHand', 'LeftUpperLeg', 'RightUpperLeg',
        'LeftLowerLeg', 'RightLowerLeg', 'LeftFoot', 'RightFoot'
    },
    Timing = {
        MinDelay = 0.02,
        MaxDelay = 0.12,
        MaxDistance = 6,
        PingSmoothing = 0.12,
        DefaultPing = 120
    }
}

getgenv().ghostrgb = true

local RunService = game:GetService('RunService')
local Players = game:GetService('Players')
local Stats = game:GetService('Stats')

local LocalPlayer = Players.LocalPlayer
LocalPlayer.Archivable = true

local GhostManager = {
    Parts = {},
    FrameHistory = {},
    Character = nil
}

function GhostManager:InitializeGhostPart(originalPart)
    local ghostPart = Instance.new('Part')
    ghostPart.Name = originalPart.Name .. '_Ghost'
    ghostPart.Size = originalPart.Size
    ghostPart.Anchored = true
    ghostPart.CanCollide = false
    ghostPart.Transparency = 1
    ghostPart.CFrame = originalPart.CFrame
    ghostPart.Parent = workspace

    local selectionBox = Instance.new('SelectionBox')
    selectionBox.Adornee = ghostPart
    selectionBox.LineThickness = 0.04
    selectionBox.Parent = ghostPart

    return {
        Original = originalPart,
        Ghost = ghostPart,
        Box = selectionBox
    }
end

function GhostManager:CalculateCurrentPing()
    local networkStats = Stats.Network
    if not networkStats then return Configuration.Timing.DefaultPing end
    
    local pingStat = networkStats.ServerStatsItem['Data Ping'] or networkStats.ServerStatsItem['Data Ping (ms)']
    if not pingStat then return Configuration.Timing.DefaultPing end
    
    return tonumber(pingStat:GetValue()) or Configuration.Timing.DefaultPing
end

function GhostManager:ApplyColorEffect(selectionBox)
    if getgenv().ghostrgb then
        selectionBox.Color3 = Color3.fromHSV((tick() % 5) / 5, 1, 1)
    else
        selectionBox.Color3 = Color3.new(1, 1, 1)
    end
end

function GhostManager:InitializeCharacter()
    self.Character = LocalPlayer.Character
    if not self.Character then return end

    self:CleanupExistingGhosts()

    local rootPart = self.Character:FindFirstChild('HumanoidRootPart')
    if not rootPart then return end

    self.Parts = {}
    for _, partName in ipairs(Configuration.Parts) do
        local characterPart = self.Character:FindFirstChild(partName)
        if characterPart and characterPart:IsA('BasePart') then
            self.Parts[partName] = self:InitializeGhostPart(characterPart)
        end
    end
end

function GhostManager:CleanupExistingGhosts()
    for _, child in ipairs(workspace:GetChildren()) do
        if child:IsA('Part') and child.Name:match('_Ghost$') then
            child:Destroy()
        end
    end
end

function GhostManager:CaptureFrameData()
    if not self.Character then return end
    
    local rootPart = self.Character:FindFirstChild('HumanoidRootPart')
    if not rootPart then return end

    local relativeTransforms = {}
    for partName, ghostData in pairs(self.Parts) do
        if ghostData.Original and ghostData.Original.Parent then
            relativeTransforms[partName] = rootPart.CFrame:ToObjectSpace(ghostData.Original.CFrame)
        end
    end

    local currentTime = tick()
    table.insert(self.FrameHistory, {
        Timestamp = currentTime,
        Transform = rootPart.CFrame,
        Position = rootPart.Position,
        Velocity = rootPart.Velocity,
        RelativeTransforms = relativeTransforms
    })

    if #self.FrameHistory > 300 then
        for _ = 1, 80 do table.remove(self.FrameHistory, 1) end
    end
end

function GhostManager:UpdateGhostParts(deltaTime)
    if not self.Character then return end
    
    local rootPart = self.Character:FindFirstChild('HumanoidRootPart')
    if not rootPart then return end

    local currentPing = self:CalculateCurrentPing()
    Configuration.Timing.DefaultPing = currentPing * Configuration.Timing.PingSmoothing + 
                                      Configuration.Timing.DefaultPing * (1 - Configuration.Timing.PingSmoothing)

    local targetDelay = math.clamp(Configuration.Timing.DefaultPing / 2000, 
                                 Configuration.Timing.MinDelay, 
                                 Configuration.Timing.MaxDelay)

    local targetFrame = self:FindTargetFrame(tick() - targetDelay)
    if not targetFrame then return end

    local timeDifference = math.clamp(tick() - targetFrame.Timestamp, 0, 0.06)
    local predictedPosition = targetFrame.Position + targetFrame.Velocity * timeDifference * 0.9
    local predictedTransform = CFrame.new(predictedPosition) * (targetFrame.Transform - targetFrame.Transform.Position)

    local stabilityFactor = math.clamp(1 - math.abs(currentPing - Configuration.Timing.DefaultPing) / 300, 0.25, 1)

    for partName, ghostData in pairs(self.Parts) do
        self:UpdateSingleGhostPart(ghostData, targetFrame, predictedTransform, deltaTime, stabilityFactor)
    end
end

function GhostManager:FindTargetFrame(targetTime)
    for index = #self.FrameHistory, 1, -1 do
        if self.FrameHistory[index].Timestamp <= targetTime then
            return self.FrameHistory[index]
        end
    end
    return self.FrameHistory[1]
end

function GhostManager:UpdateSingleGhostPart(ghostData, targetFrame, predictedTransform, deltaTime, stability)
    local ghostPart = ghostData.Ghost
    local selectionBox = ghostData.Box
    if not ghostPart then return end

    local relativeTransform = targetFrame.RelativeTransforms[ghostData.Original.Name]
    local targetCFrame = relativeTransform and predictedTransform * relativeTransform or 
                        (ghostData.Original and ghostData.Original.CFrame or ghostPart.CFrame)

    local positionOffset = (targetCFrame.Position - predictedTransform.Position).Magnitude
    if positionOffset > Configuration.Timing.MaxDistance then
        local direction = (targetCFrame.Position - predictedTransform.Position).Unit
        local rotationX, rotationY, rotationZ = targetCFrame:ToEulerAnglesXYZ()
        targetCFrame = CFrame.new(predictedTransform.Position + direction * Configuration.Timing.MaxDistance) * 
                      CFrame.Angles(rotationX, rotationY, rotationZ)
    end

    local interpolationWeight = math.clamp(deltaTime * 18 * stability, 0, 1)
    ghostPart.CFrame = ghostPart.CFrame:Lerp(targetCFrame, interpolationWeight)
    
    self:ApplyColorEffect(selectionBox)
end

GhostManager:InitializeCharacter()

RunService.Heartbeat:Connect(function(deltaTime)
    GhostManager:CaptureFrameData()
    GhostManager:UpdateGhostParts(deltaTime)
end)

LocalPlayer.CharacterAdded:Connect(function()
    task.wait(0.2)
    GhostManager:InitializeCharacter()
end)

Features & Information

Please like, I got sick the other day...
#SERVER#script

Community Comments (0)

No comments yet for this script.

More Scripts for Universal Scripts