-- HRP PREDICTIVE LOCK-ON (RAW + SHIFTLOCK) -- StarterPlayer > StarterPlayerScripts -- Roblox Studio LocalScript local Players = game:GetService("Players") local RunService = game:GetService("RunService") local UserInputService = game:GetService("UserInputService") local LocalPlayer = Players.LocalPlayer local PlayerGui = LocalPlayer:WaitForChild("PlayerGui") local Settings = { Prediction = 0.22, MaxPrediction = 0.65, SearchRadius = 120, RequireLineOfSight = true, UsePrediction = true, -- set to false for pure raw HRP aim } local State = { Mode = "Idle", Selected = nil, Target = nil, Connection = nil, } -- SHIFTLOCK CONTROL local function shiftLockOn() UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter UserInputService.MouseIconEnabled = false end local function shiftLockOff() UserInputService.MouseBehavior = Enum.MouseBehavior.Default UserInputService.MouseIconEnabled = true end -- GUI local Gui = Instance.new("ScreenGui") Gui.Name = "HRPLockOn" Gui.ResetOnSpawn = false Gui.Parent = PlayerGui local Button = Instance.new("TextButton") Button.Name = "LockButton" Button.Size = UDim2.fromOffset(48, 48) Button.Position = UDim2.new(0.82, 0, 0.65, 0) Button.BackgroundColor3 = Color3.fromRGB(25, 25, 30) Button.Text = "🔓" Button.TextSize = 25 Button.Parent = Gui local Corner = Instance.new("UICorner") Corner.CornerRadius = UDim.new(1, 0) Corner.Parent = Button local Stroke = Instance.new("UIStroke") Stroke.Thickness = 2 Stroke.Color = Color3.fromRGB(100, 100, 110) Stroke.Parent = Button local Status = Instance.new("TextLabel") Status.Size = UDim2.fromOffset(190, 28) Status.Position = UDim2.new(0.5, -95, 0, -34) Status.BackgroundColor3 = Color3.fromRGB(20, 20, 25) Status.TextColor3 = Color3.new(1, 1, 1) Status.TextSize = 11 Status.Font = Enum.Font.GothamBold Status.Visible = false Status.Parent = Button local StatusCorner = Instance.new("UICorner") StatusCorner.CornerRadius = UDim.new(0, 7) StatusCorner.Parent = Status -- DRAGGING local dragging = false local dragStart local startPosition local dragInput Button.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = true dragStart = input.Position startPosition = Button.Position input.Changed:Connect(function() if input.UserInputState == Enum.UserInputState.End then dragging = false end end) end end) Button.InputChanged:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then dragInput = input end end) UserInputService.InputChanged:Connect(function(input) if dragging and input == dragInput then local delta = input.Position - dragStart Button.Position = UDim2.new( startPosition.X.Scale, startPosition.X.Offset + delta.X, startPosition.Y.Scale, startPosition.Y.Offset + delta.Y ) end end) -- CHARACTER HELPERS local function getCharacter(player) if not player then return end local character = player.Character if not character then return end local humanoid = character:FindFirstChildOfClass("Humanoid") local hrp = character:FindFirstChild("HumanoidRootPart") if not humanoid or not hrp or humanoid.Health <= 0 then return end return character, humanoid, hrp end -- TARGET VISIBILITY local function canSee(character, part) if not Settings.RequireLineOfSight then return true end local myCharacter = LocalPlayer.Character local camera = workspace.CurrentCamera if not camera then return false end local params = RaycastParams.new() params.FilterType = Enum.RaycastFilterType.Exclude params.FilterDescendantsInstances = { myCharacter, camera } local direction = part.Position - camera.CFrame.Position local result = workspace:Raycast( camera.CFrame.Position, direction, params ) return result ~= nil and result.Instance:IsDescendantOf(character) end -- TARGET SELECTION local function findTarget() local camera = workspace.CurrentCamera if not camera then return nil end local viewport = camera.ViewportSize local center = Vector2.new( viewport.X / 2, viewport.Y / 2 ) local bestTarget local bestDistance = Settings.SearchRadius for _, player in ipairs(Players:GetPlayers()) do if player ~= LocalPlayer then local character, humanoid, hrp = getCharacter(player) if character and hrp then local screen, visible = camera:WorldToViewportPoint(hrp.Position) if visible and screen.Z > 0 then local distance = ( Vector2.new(screen.X, screen.Y) - center ).Magnitude if distance < bestDistance and canSee(character, hrp) then bestDistance = distance bestTarget = player end end end end end return bestTarget end -- PREDICTION local StopThreshold = 0.5 -- studs/sec; below this the target counts as stopped local function predictPosition(hrp) local velocity = hrp.AssemblyLinearVelocity local speed = velocity.Magnitude -- Target fully stopped: no prediction, raw HRP aim. if speed < StopThreshold then return hrp.Position end local predictionTime = math.clamp( Settings.Prediction + speed / 150, 0, Settings.MaxPrediction ) return hrp.Position + velocity * predictionTime end -- UNLOCK local function unlock() if State.Connection then State.Connection:Disconnect() State.Connection = nil end State.Target = nil State.Selected = nil State.Mode = "Idle" shiftLockOff() Button.Text = "🔓" Button.BackgroundColor3 = Color3.fromRGB(25, 25, 30) Stroke.Color = Color3.fromRGB(100, 100, 110) Status.Visible = false end -- LOCK local function lock(player) local character, humanoid, hrp = getCharacter(player) if not character then unlock() return end local myCharacter = LocalPlayer.Character local myHumanoid = myCharacter and myCharacter:FindFirstChildOfClass("Humanoid") local myHRP = myCharacter and myCharacter:FindFirstChild("HumanoidRootPart") if not myHumanoid or not myHRP then unlock() return end State.Target = player State.Mode = "Locked" shiftLockOn() Button.Text = "🔒" Button.BackgroundColor3 = Color3.fromRGB(20, 115, 55) Stroke.Color = Color3.fromRGB(65, 255, 110) Status.Text = "HRP LOCKED: " .. player.DisplayName Status.Visible = true State.Connection = RunService.RenderStepped:Connect(function() local targetCharacter, targetHumanoid, targetHRP = getCharacter(State.Target) local currentCharacter = LocalPlayer.Character local currentHRP = currentCharacter and currentCharacter:FindFirstChild("HumanoidRootPart") local currentHumanoid = currentCharacter and currentCharacter:FindFirstChildOfClass("Humanoid") if not targetCharacter or not currentHRP or not currentHumanoid then unlock() return end -- Keep shiftlock held every frame (Roblox resets it on camera changes). shiftLockOn() -- Aim point: predicted position, or the raw HRP itself. local aimPosition = targetHRP.Position if Settings.UsePrediction then aimPosition = predictPosition(targetHRP) end -- RAW lock-on: face the aim point instantly, no smoothing/lerp. local origin = currentHRP.Position local flatTarget = Vector3.new( aimPosition.X, origin.Y, aimPosition.Z ) local difference = flatTarget - origin if difference.Magnitude > 0.01 then currentHRP.CFrame = CFrame.lookAt( origin, flatTarget ) end end) end -- BUTTON Button.Activated:Connect(function() if State.Mode == "Idle" then local target = findTarget() if target then State.Selected = target State.Mode = "Selected" Button.Text = "✅" Button.BackgroundColor3 = Color3.fromRGB(20, 130, 65) Stroke.Color = Color3.fromRGB(65, 255, 110) Status.Text = "SAVE TARGET: " .. target.DisplayName Status.Visible = true else Status.Text = "NO TARGET FOUND" Status.Visible = true task.delay(1.5, function() if State.Mode == "Idle" then Status.Visible = false end end) end elseif State.Mode == "Selected" then if State.Selected and getCharacter(State.Selected) then lock(State.Selected) else unlock() end elseif State.Mode == "Locked" then unlock() end end) -- TARGET LEAVING Players.PlayerRemoving:Connect(function(player) if player == State.Target or player == State.Selected then unlock() end end) -- RESPAWN LocalPlayer.CharacterAdded:Connect(function() unlock() end) print("[HRP Lock-On] Raw + ShiftLock loaded successfully.")