-- Ultra-Smart Hybrid Follower (With "NUH UH" Ground Recovery Command) local Players = game:GetService("Players") local PathfindingService = game:GetService("PathfindingService") local RunService = game:GetService("RunService") local localPlayer = Players.LocalPlayer local targetPlayer = nil local followConnection = nil local bodyVelocity = nil local bodyGyro = nil -- Configuration local STUCK_TIME_LIMIT = 0.4 local AIR_THRESHOLD = 5 local path = PathfindingService:CreatePath({ AgentRadius = 1.5, AgentHeight = 4.5, AgentCanJump = false, AgentSlope = 45 }) local function removeFlightForces() if bodyVelocity then bodyVelocity:Destroy(); bodyVelocity = nil end if bodyGyro then bodyGyro:Destroy(); bodyGyro = nil end end -- Safely finds the closest solid ground surface underneath the character local function teleportToNearestGround(rootPart) local raycastParams = RaycastParams.new() raycastParams.FilterType = Enum.RaycastFilterType.Exclude raycastParams.FilterDescendantsInstances = {rootPart.Parent} -- Cast a long ray straight down (up to 500 studs) to find a floor local raycastResult = workspace:Raycast(rootPart.Position, Vector3.new(0, -500, 0), raycastParams) if raycastResult then -- Snap to the intersection position + a minor upward offset so your feet don't clip into the floor rootPart.CFrame = CFrame.new(raycastResult.Position + Vector3.new(0, 3, 0)) end end local function stopFollowing(forceGroundSnap) if followConnection then followConnection:Disconnect(); followConnection = nil end removeFlightForces() targetPlayer = nil local myChar = localPlayer.Character if myChar then local myHumanoid = myChar:FindFirstChildOfClass("Humanoid") local myRoot = myChar:FindFirstChild("HumanoidRootPart") if myHumanoid and myRoot then myHumanoid:MoveTo(myRoot.Position) myHumanoid.WalkSpeed = 16 -- If triggered by "NUH UH" while mid-air, snap safely to the solid ground below if forceGroundSnap then teleportToNearestGround(myRoot) end end end end local function hasLineOfSight(startPos, endPos, character) local raycastParams = RaycastParams.new() raycastParams.FilterType = Enum.RaycastFilterType.Exclude raycastParams.FilterDescendantsInstances = {character, targetPlayer.Character} local rayDirection = (endPos - startPos) return workspace:Raycast(startPos + Vector3.new(0,1,0), rayDirection, raycastParams) == nil end local function isFlying(rootPart) local raycastParams = RaycastParams.new() raycastParams.FilterType = Enum.RaycastFilterType.Exclude raycastParams.FilterDescendantsInstances = {rootPart.Parent} local result = workspace:Raycast(rootPart.Position, Vector3.new(0, -AIR_THRESHOLD, 0), raycastParams) return result == nil end local function startFollowing(playerToFollow) targetPlayer = playerToFollow if followConnection then followConnection:Disconnect() end local myChar = localPlayer.Character local targetChar = targetPlayer.Character if myChar and targetChar then local myRoot = myChar:FindFirstChild("HumanoidRootPart") local targetRoot = targetChar:FindFirstChild("HumanoidRootPart") if myRoot and targetRoot then myRoot.CFrame = targetRoot.CFrame * CFrame.new(0, 0, 2) end end local lastPos = Vector3.new() local stuckTimer = 0 followConnection = RunService.Heartbeat:Connect(function() local myChar = localPlayer.Character local targetChar = targetPlayer.Character if myChar and targetChar then local myHumanoid = myChar:FindFirstChildOfClass("Humanoid") local targetHumanoid = targetChar:FindFirstChildOfClass("Humanoid") local myRoot = myChar:FindFirstChild("HumanoidRootPart") local targetRoot = targetChar:FindFirstChild("HumanoidRootPart") if myHumanoid and targetHumanoid and myRoot and targetRoot then myHumanoid.Jump = false local targetSpeed = targetHumanoid.WalkSpeed myHumanoid.WalkSpeed = targetSpeed local standTargetCFrame = targetRoot.CFrame * CFrame.new(0, 0, 2) local standTargetPos = standTargetCFrame.Position local myPos = myRoot.Position -- AIR FLIGHT MODE if isFlying(targetRoot) then if not bodyVelocity then bodyVelocity = Instance.new("BodyVelocity") bodyVelocity.MaxForce = Vector3.new(4e5, 4e5, 4e5) bodyVelocity.Velocity = Vector3.new(0,0,0) bodyVelocity.Parent = myRoot end if not bodyGyro then bodyGyro = Instance.new("BodyGyro") bodyGyro.MaxTorque = Vector3.new(4e5, 4e5, 4e5) bodyGyro.CFrame = targetRoot.CFrame bodyGyro.Parent = myRoot end local direction = (standTargetPos - myPos) local distance = direction.Magnitude if distance > 0.5 then bodyVelocity.Velocity = direction.Unit * math.clamp(distance * 5, targetSpeed, targetSpeed * 2) else bodyVelocity.Velocity = Vector3.new(0,0,0) end bodyGyro.CFrame = targetRoot.CFrame -- GROUND PATHFINDING MODE else removeFlightForces() if (myPos - lastPos).Magnitude < 0.2 then stuckTimer = stuckTimer + RunService.Heartbeat:Wait() if stuckTimer > STUCK_TIME_LIMIT then myHumanoid:MoveTo(standTargetPos + Vector3.new(math.random(-1,1), 0, math.random(-1,1))) stuckTimer = 0 end else stuckTimer = 0 end lastPos = myPos if hasLineOfSight(myPos, standTargetPos, myChar) then myHumanoid:MoveTo(standTargetPos) else local success, _ = pcall(function() path:ComputeAsync(myPos, standTargetPos) end) if success and path.Status == Enum.PathStatus.Success then local waypoints = path:GetWaypoints() if #waypoints >= 2 then myHumanoid:MoveTo(waypoints.Position) else myHumanoid:MoveTo(standTargetPos) end else myHumanoid:MoveTo(standTargetPos) end end end end else stopFollowing(false) end end) end -- Universal Chat Interpreter local function onPlayerChatted(player, message) local cleanMessage = message:lower():gsub("[%[%]]", ""):gsub("%s+", " "):match("^%s*(.-)%s*$") -- SELF COMMAND CHECK: Triggers only if YOU say it if player == localPlayer then if cleanMessage == "nuh uh" then -- Stops tracking and forces a down-ray ground drop check stopFollowing(true) end return end -- TARGET COMMANDS: Triggers if other players say them if cleanMessage == ":follow" then startFollowing(player) elseif cleanMessage == ":stop" then stopFollowing(false) end end for _, player in ipairs(Players:GetPlayers()) do player.Chatted:Connect(function(message) onPlayerChatted(player, message) end) end Players.PlayerAdded:Connect(function(player) player.Chatted:Connect(function(message) onPlayerChatted(player, message) end) end)