
KeylessUniversal

-- 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)No comments yet for this script.



