local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UIS = game:GetService("UserInputService")
local PathfindingService = game:GetService("PathfindingService")
local Workspace = game:GetService("Workspace")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local root = character:WaitForChild("HumanoidRootPart")
-- SETTINGS
local botActive = false
local attackRange = 30 -- you can change this if you want
local walkSpeed = 30
local strafeRadius = 5 -- now strafes exactly 5 studs away
local strafeSpeed = 0.5
local voidLevel = -10
local lockedTarget = nil
local orbitAngle = 0
local strafeDirection = 1
humanoid.WalkSpeed = walkSpeed
-- TOGGLE BOT
UIS.InputBegan:Connect(function(input, processed)
if processed then return end
if input.KeyCode == Enum.KeyCode.M then
botActive = not botActive
if not botActive then
lockedTarget = nil
end
end
end)
-- FIND NEAREST PLAYER
local function pickTarget()
local nearestDist = math.huge
local nearestChar = nil
for _,plr in pairs(Players:GetPlayers()) do
if plr ~= player then
local char = plr.Character
if char then
local hum = char:FindFirstChild("Humanoid")
local hrp = char:FindFirstChild("HumanoidRootPart")
if hum and hum.Health > 0 and hrp then
local dist = (hrp.Position - root.Position).Magnitude
if dist < nearestDist then
nearestDist = dist
nearestChar = char
end
end
end
end
end
lockedTarget = nearestChar
end
-- VOID RECOVERY
local function fixVoid()
if root.Position.Y < voidLevel then
local rayOrigin = root.Position + Vector3.new(0,100,0)
local rayDir = Vector3.new(0,-500,0)
local params = RaycastParams.new()
params.FilterDescendantsInstances = {character}
params.FilterType = Enum.RaycastFilterType.Blacklist
local result = Workspace:Raycast(rayOrigin, rayDir, params)
if result then
root.CFrame = CFrame.new(result.Position + Vector3.new(0,5,0))
else
root.CFrame = CFrame.new(0,10,0)
end
end
end
-- CHECK GROUND BELOW
local function groundBelow(pos)
local rayOrigin = pos + Vector3.new(0,2,0)
local rayDir = Vector3.new(0,-12,0)
local params = RaycastParams.new()
params.FilterDescendantsInstances = {character}
params.FilterType = Enum.RaycastFilterType.Blacklist
local result = Workspace:Raycast(rayOrigin, rayDir, params)
return result ~= nil
end
-- STRAFE AROUND PLAYER AT 5 STUDS
local function safeStrafe(targetPos)
orbitAngle += strafeSpeed * strafeDirection
local offset = Vector3.new(
math.cos(orbitAngle) * strafeRadius,
0,
math.sin(orbitAngle) * strafeRadius
)
local strafePos = targetPos + offset
local frontSafe = groundBelow(strafePos)
local leftPos = targetPos + Vector3.new(
math.cos(orbitAngle + math.pi/2) * strafeRadius,
0,
math.sin(orbitAngle + math.pi/2) * strafeRadius
)
local rightPos = targetPos + Vector3.new(
math.cos(orbitAngle - math.pi/2) * strafeRadius,
0,
math.sin(orbitAngle - math.pi/2) * strafeRadius
)
local leftSafe = groundBelow(leftPos)
local rightSafe = groundBelow(rightPos)
if not frontSafe then
strafeDirection *= -1
elseif not leftSafe and not rightSafe then
humanoid:MoveTo(Vector3.new(0, root.Position.Y, 0))
return
end
local moveDir = strafePos - root.Position
moveDir = Vector3.new(moveDir.X,0,moveDir.Z)
if moveDir.Magnitude > 0 then
humanoid:Move(moveDir.Unit,false)
end
-- always face the player
root.CFrame = CFrame.new(root.Position, Vector3.new(targetPos.X, root.Position.Y, targetPos.Z))
end
-- PATHFIND TO TARGET
local moving = false
local function moveToTarget(targetPos)
if moving then return end
moving = true
local path = PathfindingService:CreatePath()
path:ComputeAsync(root.Position,targetPos)
for _,wp in ipairs(path:GetWaypoints()) do
if not botActive then break end
if wp.Action == Enum.PathWaypointAction.Jump then
humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
humanoid:MoveTo(wp.Position)
humanoid.MoveToFinished:Wait()
end
moving = false
end
-- MAIN LOOP
RunService.RenderStepped:Connect(function()
if not botActive then return end
fixVoid()
pickTarget()
if lockedTarget and lockedTarget:FindFirstChild("HumanoidRootPart") then
local targetRoot = lockedTarget.HumanoidRootPart
local hum = lockedTarget:FindFirstChild("Humanoid")
if hum and hum.Health > 0 then
local dist = (targetRoot.Position - root.Position).Magnitude
if dist > strafeRadius then
moveToTarget(targetRoot.Position)
else
safeStrafe(targetRoot.Position)
end
if dist <= attackRange then
local sword = character:FindFirstChildOfClass("Tool")
if sword then
sword:Activate()
end
end
else
lockedTarget = nil
end
end
end)
Comments
No comments yet
Be the first to share your thoughts!