local Players = game:GetService("Players") local RunService = game:GetService("RunService") local Workspace = game:GetService("Workspace") local lp = Players.LocalPlayer local cfg = { active = true, visual = true, compFactor = 0.7, jitterW = 0.6, maxCompMs = 350, maxOfs = 18, smooth = 7, blendUp = 2.5, blendDn = 4.0, dirUp = 2.0, dirDn = 3.5, velMin = 1.5, velAlpha = 17.0, tpDist = 50, rttA = 0.08, jitA = 0.06, yDamp = 0.1, spdClamp = 1.15, boundsCheck = true, maxOfsRate = 0.8, pingFadeLo = 0.03, pingFadeHi = 0.07, minDt = 1 / 300, maxDt = 1 / 15, owThresh = 0.05, accelAlpha = 3.5, accelScale = 0.3, staleRate = 1.5, staleFade = 0.6, groundUp = 10, groundDown = 80, adaptSmoothMin = 3, adaptSmoothMax = 12, adaptJitScale = 120, } local net = { rtt = 0, jit = 0.01 } local ents = {} local conns = {} local running = false local rcP = RaycastParams.new() rcP.FilterType = Enum.RaycastFilterType.Exclude local filterTable = {} local function expAlpha(rate, dt) return 1 - math.exp(-rate * dt) end local function pingFade(rtt) local hi = math.max(cfg.pingFadeHi, net.jit * 2.5) if rtt <= cfg.pingFadeLo then return 0 end if rtt >= hi then return 1 end return (rtt - cfg.pingFadeLo) / (hi - cfg.pingFadeLo) end local function compT() local raw = net.rtt * 0.5 * cfg.compFactor + net.jit * cfg.jitterW local v = math.min(raw * pingFade(net.rtt), cfg.maxCompMs / 1000) if v ~= v or v < 0 then return 0 end return v end local function updateNet() local r = lp:GetNetworkPing() * 2 if r ~= r or r < 0 then r = 0 end net.rtt = net.rtt == 0 and r or net.rtt + cfg.rttA * (r - net.rtt) net.jit = net.jit + cfg.jitA * (math.abs(r - net.rtt) - net.jit) end local function newE() return { engPos = nil, readCF = CFrame.identity, lastPP = nil, vel = Vector3.zero, sVel = Vector3.zero, dir = Vector3.zero, dcon = 0, bld = 0, ofs = Vector3.zero, pred = CFrame.identity, char = nil, root = nil, hum = nil, alive = false, ok = false, accel = Vector3.zero, prevVel = nil, airborne = false, stale = 0, conf = 0, } end local function rstE(e) e.vel = Vector3.zero e.sVel = Vector3.zero e.dir = Vector3.zero e.dcon = 0 e.bld = 0 e.ofs = Vector3.zero e.ok = false e.engPos = nil e.lastPP = nil e.accel = Vector3.zero e.prevVel = nil e.airborne = false e.stale = 0 e.conf = 0 end local function getWS(e) return (e.hum and e.hum.WalkSpeed) or 16 end local function validatePos(origin, target) if not cfg.boundsCheck then return target end local disp = target - origin local dist = disp.Magnitude if dist < 0.1 then return target end local wh = Workspace:Raycast(origin, disp, rcP) if wh then return origin + disp.Unit * math.max(wh.Distance - 0.5, 0) end local gh = Workspace:Raycast(target + Vector3.new(0, cfg.groundUp, 0), Vector3.new(0, -(cfg.groundUp + cfg.groundDown), 0), rcP) if not gh then return origin end return target end local function updE(e, dt) local root = e.root local cf = root.CFrame local p = cf.Position local rv = root.AssemblyLinearVelocity local rvm = rv.Magnitude if rvm ~= rvm or rvm > 5000 then rv = Vector3.zero end e.readCF = cf local freshData = false local engP if cfg.visual and e.lastPP and e.engPos then if (p - e.lastPP).Magnitude > cfg.owThresh then engP = p freshData = true else engP = e.engPos + rv * dt end else engP = p freshData = true end if e.engPos and (engP - e.engPos).Magnitude > cfg.tpDist then rstE(e) engP = p freshData = true end e.engPos = engP local va = expAlpha(cfg.velAlpha, dt) e.sVel = e.sVel:Lerp(rv, va) local ws = getWS(e) local maxSpd = ws * cfg.spdClamp local hRaw = Vector3.new(e.sVel.X, 0, e.sVel.Z) local hMag = hRaw.Magnitude if hMag > maxSpd then local s = maxSpd / hMag e.vel = Vector3.new(e.sVel.X * s, e.sVel.Y, e.sVel.Z * s) else e.vel = e.sVel end if e.prevVel then local rawAccel = (e.vel - e.prevVel) / dt local ram = rawAccel.Magnitude if ram ~= ram or ram > 5000 then rawAccel = Vector3.zero end e.accel = e.accel:Lerp(rawAccel, expAlpha(cfg.accelAlpha, dt)) end e.prevVel = e.vel e.airborne = e.hum and e.hum.FloorMaterial == Enum.Material.Air local hv = Vector3.new(e.vel.X, 0, e.vel.Z) local hspd = hv.Magnitude if hspd > cfg.velMin then local nv = hv.Unit if e.dir.Magnitude < 0.1 then e.dir = nv e.dcon = 0.2 else local dot = math.clamp(nv:Dot(e.dir), 0, 1) e.dcon = e.dcon + cfg.dirUp * dt * (dot - e.dcon) local nd = e.dir:Lerp(nv, math.clamp(5 * dt, 0, 1)) e.dir = nd.Magnitude > 0.001 and nd.Unit or nv end e.bld = math.min(e.bld + cfg.blendUp * dt, 1) else e.dcon = math.max(e.dcon - cfg.dirDn * dt, 0) e.bld = math.max(e.bld - cfg.blendDn * dt, 0) if e.bld < 0.01 then e.dir = Vector3.zero end end if freshData then e.stale = 0 else e.stale = e.stale + dt * cfg.staleRate end local staleMul = math.max(1 - e.stale * cfg.staleFade, 0) local sc = e.bld * e.dcon * staleMul local ct = compT() local adaptSmooth = math.clamp(cfg.smooth - net.jit * cfg.adaptJitScale, cfg.adaptSmoothMin, cfg.adaptSmoothMax) local tgt if sc > 0.01 then local t = ct * sc local pv if e.airborne then local grav = Workspace.Gravity pv = e.vel * t + Vector3.new(0, -grav * 0.5 * t * t, 0) + Vector3.new(e.accel.X, 0, e.accel.Z) * (cfg.accelScale * 0.5 * t * t) else local dampedVel = Vector3.new(e.vel.X, e.vel.Y * cfg.yDamp, e.vel.Z) pv = dampedVel * t + Vector3.new(e.accel.X, 0, e.accel.Z) * (cfg.accelScale * 0.5 * t * t) end tgt = pv local m = tgt.Magnitude local dynMax = math.min(cfg.maxOfs, ws * ct * cfg.spdClamp) if m > dynMax then tgt = tgt * (dynMax / m) end else tgt = Vector3.zero end local a = expAlpha(adaptSmooth, dt) local desired = e.ofs:Lerp(tgt, a) local delta = desired - e.ofs local deltaMag = delta.Magnitude local maxDelta = maxSpd * dt * cfg.maxOfsRate if deltaMag > maxDelta and deltaMag > 0.001 then desired = e.ofs + delta * (maxDelta / deltaMag) end e.ofs = desired local ofsMag = e.ofs.Magnitude if ofsMag ~= ofsMag then e.ofs = Vector3.zero ofsMag = 0 elseif ofsMag < 0.01 then e.ofs = Vector3.zero ofsMag = 0 end if ofsMag > 0.01 and sc > 0.05 then e.conf = math.min(e.conf + 2.0 * dt, 1) else e.conf = math.max(e.conf - 3.0 * dt, 0) end local predPos = validatePos(engP, engP + e.ofs) e.pred = (cf - p) + predPos e.ok = true end local M = {} function M.start() if running then return end running = true conns.leave = Players.PlayerRemoving:Connect(function(pl) ents[pl] = nil end) conns.hb = RunService.Heartbeat:Connect(function(rawDt) if not cfg.active then return end local dt = math.clamp(rawDt, cfg.minDt, cfg.maxDt) updateNet() local pls = Players:GetPlayers() table.clear(filterTable) local fi = 0 for i = 1, #pls do local ch = pls[i].Character if ch then fi = fi + 1; filterTable[fi] = ch end end rcP.FilterDescendantsInstances = filterTable for i = 1, #pls do local pl = pls[i] if pl ~= lp then local ch = pl.Character if ch then local root = ch:FindFirstChild("HumanoidRootPart") local hum = ch:FindFirstChild("Humanoid") if root and hum and hum.Health > 0 then local e = ents[pl] if not e then e = newE(); ents[pl] = e end if e.char ~= ch then rstE(e) e.char = ch end e.root = root e.hum = hum e.alive = true updE(e, dt) if cfg.visual and root.Parent then root.CFrame = e.pred e.lastPP = e.pred.Position else e.lastPP = nil end else local e = ents[pl] if e and e.alive then e.alive = false if cfg.visual and e.ok and e.root and e.root.Parent and e.engPos then e.root.CFrame = (e.readCF - e.readCF.Position) + e.engPos end end end else local e = ents[pl] if e then e.alive = false end end end end end) end function M.stop() running = false for k, c in pairs(conns) do c:Disconnect(); conns[k] = nil end for _, e in pairs(ents) do if cfg.visual and e.ok and e.root and e.root.Parent and e.engPos then e.root.CFrame = (e.readCF - e.readCF.Position) + e.engPos end end table.clear(ents) table.clear(filterTable) rcP.FilterDescendantsInstances = filterTable end function M.predicted(pl) local e = ents[pl] return e and e.ok and e.pred.Position or nil end function M.predictedCF(pl) local e = ents[pl] return e and e.ok and e.pred or nil end function M.partPos(pl, name) local e = ents[pl] if not e or not e.ok or not e.char or not e.engPos then return nil end local pt = e.char:FindFirstChild(name) if not pt then return nil end return e.pred.Position + (pt.Position - e.readCF.Position) end function M.headPos(pl) return M.partPos(pl, "Head") end function M.leadPoint(pl, projSpd) local e = ents[pl] if not e or not e.ok then return nil end if not projSpd or projSpd <= 0 then return e.pred.Position end local mc = lp.Character local mr = mc and mc:FindFirstChild("HumanoidRootPart") if not mr then return e.pred.Position end local d = (e.pred.Position - mr.Position).Magnitude local t = d / projSpd + net.rtt * 0.5 return e.pred.Position + e.vel * t + e.accel * (cfg.accelScale * 0.5 * t * t) end function M.nearest(fov, rng, los) local cam = Workspace.CurrentCamera if not cam then return nil end fov = fov or 15 rng = rng or 500 local o = cam.CFrame.Position local l = cam.CFrame.LookVector local best, bs = nil, math.huge for pl, e in pairs(ents) do if e.ok and e.alive then local dv = e.pred.Position - o local dm = dv.Magnitude if dm > 0.1 and dm < rng then local ang = math.deg(math.acos(math.clamp(l:Dot(dv / dm), -1, 1))) if ang < fov then if los then local hit = Workspace:Raycast(o, dv, rcP) if hit then continue end end local sc = ang + dm * 0.01 if sc < bs then best, bs = pl, sc end end end end end return best end function M.velocity(pl) local e = ents[pl] return e and e.vel or nil end function M.moving(pl, t) local e = ents[pl] return e ~= nil and e.vel.Magnitude > (t or cfg.velMin) end function M.offset(pl) local e = ents[pl] return e and e.ofs or nil end function M.confidence(pl) local e = ents[pl] return e and e.conf or 0 end function M.stats() return { rtt = net.rtt, rttMs = net.rtt * 1000, jitter = net.jit, jitterMs = net.jit * 1000, compMs = compT() * 1000, oneWayMs = net.rtt * 500, } end function M.allPreds() local r = {} for pl, e in pairs(ents) do if e.ok and e.alive then r[pl] = { position = e.pred.Position, cframe = e.pred, velocity = e.vel, offset = e.ofs, acceleration = e.accel, confidence = e.conf, airborne = e.airborne, } end end return r end function M.setVisual(on) if not on and cfg.visual then for _, e in pairs(ents) do if e.ok and e.root and e.root.Parent and e.engPos then e.root.CFrame = (e.readCF - e.readCF.Position) + e.engPos end e.ofs = Vector3.zero e.lastPP = nil e.stale = 0 e.conf = 0 end end cfg.visual = on end function M.setActive(on) cfg.active = on if not on then M.setVisual(false) end end function M.config() return cfg end M.start() return M