
KeylessUniversal

local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local function getCharacter()
local character = player.Character
if not character then return end
local humanoid = character:FindFirstChildOfClass("Humanoid")
local rootPart = character:FindFirstChild("HumanoidRootPart")
if not humanoid or not rootPart then
return
end
return character, humanoid, rootPart
end
local stuckState = 0
local lastJumpTime = 0
local JUMP_COOLDOWN = 0.8
local lastDirection = Vector3.new(1, 0, 0)
local NavConfig = {
Active = true,
Radius = 200,
WaypointVisuals = true,
StoppingDistance = 4,
MaxStuckTime = 1.2
}
local PLAYER_JUMP_HEIGHT = 7
local PLAYER_WIDTH = 4
local camera = workspace.CurrentCamera
local activeLines = {}
local function clearAllMarkers()
for _, l in pairs(activeLines) do
if l then l:Destroy() end
end
activeLines = {}
end
local function removeLine(i)
if activeLines[i] then
activeLines[i]:Destroy()
activeLines[i] = nil
end
end
local function drawFullVisualPath(points)
clearAllMarkers()
if not NavConfig.WaypointVisuals then return end
for i = 1, #points - 1 do
local a = points[i].Position
local b = points[i + 1].Position
local dist = (b - a).Magnitude
local part = Instance.new("Part")
part.Anchored = true
part.CanCollide = false
part.Material = Enum.Material.Neon
part.Color = Color3.fromRGB(255, 255, 0)
part.Size = Vector3.new(0.2, 0.2, dist)
part.CFrame = CFrame.lookAt(a, b) * CFrame.new(0, 0, -dist / 2)
part.Parent = workspace
table.insert(activeLines, part)
end
end
local function lookAtCrumb(targetPos, speed)
local _, _, rootPart = getCharacter()
if not rootPart then return end
speed = speed or 25
local camPos = camera.CFrame.Position
local dir = targetPos - camPos
dir = Vector3.new(dir.X, 0, dir.Z)
if dir.Magnitude < 0.001 then return end
dir = dir.Unit
local targetCF = CFrame.lookAt(camPos, camPos + dir)
camera.CFrame = camera.CFrame:Lerp(targetCF, 1 / speed)
end
local function forceJump(humanoid)
local now = os.clock()
if now - lastJumpTime < JUMP_COOLDOWN then return end
humanoid.Jump = true
lastJumpTime = now
end
local function generateCrumbs(waypoints)
local crumbs = {}
for i = 1, #waypoints - 1 do
table.insert(crumbs, {Position = waypoints[i].Position})
table.insert(crumbs, {Position = waypoints[i + 1].Position})
end
table.insert(crumbs, {Position = waypoints[#waypoints].Position})
return crumbs
end
local function hasTouchDamage(part)
local name = part.Name:lower()
if name:find("kill") then return true end
if name:find("lava") then return true end
if name:find("damage") then return true end
if part:FindFirstChild("Damage") then return true end
return false
end
local function isPositionDanger(pos)
local boxSize = Vector3.new(6, 6, 6)
local parts = workspace:GetPartBoundsInBox(CFrame.new(pos), boxSize)
for _, p in ipairs(parts) do
if p:GetAttribute("Hazard") == true then
return true
end
if hasTouchDamage(p) then
return true
end
end
return false
end
local function buildDestination(mode, baseDir, rootPart)
if mode == 0 then
return rootPart.Position + Vector3.new(
math.random(-NavConfig.Radius, NavConfig.Radius),
0,
math.random(-NavConfig.Radius, NavConfig.Radius)
)
elseif mode == 1 then
local offset = baseDir.Unit * math.random(40, 120)
return rootPart.Position + offset + Vector3.new(math.random(-20, 20), 0, math.random(-20, 20))
else
return rootPart.Position + Vector3.new(
math.random(-NavConfig.Radius, NavConfig.Radius),
0,
math.random(-NavConfig.Radius, NavConfig.Radius)
)
end
end
local function followCrumbs(crumbs)
local index = 1
local stuckTime = 0
while index <= #crumbs do
if not NavConfig.Active then return false end
local character, humanoid, rootPart = getCharacter()
if not character or not humanoid or not rootPart then
task.wait(0.1)
return false
end
local crumb = crumbs[index]
local nextLook = crumbs[math.min(index, #crumbs)]
lookAtCrumb(nextLook.Position, 5)
local target = crumb.Position
local pos = rootPart.Position
local delta = target - pos
local planar = Vector3.new(delta.X, 0, delta.Z)
if planar.Magnitude < NavConfig.StoppingDistance then
local nextCrumb = crumbs[index + 1]
if nextCrumb then
local deltaY = nextCrumb.Position.Y - pos.Y
if deltaY > 2 then
forceJump(humanoid)
end
end
removeLine(index)
index += 1
stuckTime = 0
continue
end
local dir = planar.Magnitude > 0 and planar.Unit or Vector3.zero
humanoid:MoveTo(pos + dir * 8)
if (pos - rootPart.Position).Magnitude > 0.15 then
stuckTime = 0
else
stuckTime += 0.05
end
if stuckTime > NavConfig.MaxStuckTime then
return false
end
task.wait()
end
return true
end
player.CharacterAdded:Connect(function()
clearAllMarkers()
stuckState = 0
lastDirection = Vector3.new(1, 0, 0)
end)
task.spawn(function()
print("NavBot SAFE VERSION")
while true do
if not NavConfig.Active then task.wait(1) continue end
local character, humanoid, rootPart = getCharacter()
if not character or not humanoid or not rootPart then
task.wait(0.2)
continue
end
local mode = stuckState % 3
local destination = buildDestination(mode, lastDirection, rootPart)
local path = PathfindingService:CreatePath({
AgentRadius = 3,
AgentHeight = 5,
AgentCanJump = true,
WaypointSpacing = 6
})
local success = pcall(function()
path:ComputeAsync(rootPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints()
local crumbs = generateCrumbs(waypoints)
drawFullVisualPath(crumbs)
local ok = followCrumbs(crumbs)
if not ok then
stuckState += 1
lastDirection = (destination - rootPart.Position)
clearAllMarkers()
task.wait(0.1)
else
stuckState = 0
clearAllMarkers()
task.wait(0.2)
end
else
stuckState += 1
clearAllMarkers()
task.wait(0.3)
end
end
end)



In the next version, could you add a menu that allows control of certain functions? Like, for example, objectives????