I’m trying to make a swordfighting NPC and I’m having a problem where if I use Humanoid:MoveToFinished()
the NPC waits until its current path is finished until updating the path path to the player and where if i don’t use Humanoid:MoveToFinished()
the NPC doesn’t follow the path at all.
Here’s my code:
local Players = game:GetService("Players")
local PathfindingService = game:GetService("PathfindingService")
local Debris = game:GetService("Debris")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local path = PathfindingService:CreatePath({
AgentRadius = 2,
AgentHeight = 4,
AgentCanJump = true,
Costs = {
NoPass = math.huge
}
})
local robot = script.Parent.Parent
local h = robot.Humanoid
local root = robot.HumanoidRootPart
local bodyColours = robot["Body Colors"]
local armJoint = robot.RightUpperArm.RightShoulder
local headJoint = robot.Head.Neck
local waypointFolder = workspace:FindFirstChild("WaypointMarkers")
local sword = robot.ClassicSword
local attackEvent = robot.Events.SwordSwing
local equipEvent = robot.Events.SwordEquip
local maxDistance = 100
local attackDist = 5
local attackDelay = 1
local cleanupTime = 3
local canAttack = true
local distance = math.huge
local attackThread:thread
local aimThread:thread
local canwalkBack = true
local defaultArmPos = CFrame.new(0.971603811, 0.597512901, 1.19686121e-07, 1, 0, 0, 0, 1, 0, 0, 0, 1)
local defaultNeckPos = CFrame.new(-5.79121036e-08, 0.849033773, 1.19686121e-07, 1, 0, 0, 0, 1, 0, 0, 0, 1 )
local target:Model
local origin = root.Position
local cancelPath = false
local walkingBack = false
if not waypointFolder then
waypointFolder = Instance.new("Folder", workspace)
waypointFolder.Name = "WaypointMarkers"
end
function compute(goal: Vector3)
local success, errorMessage = pcall(function()
path:ComputeAsync(root.Position, goal)
end)
if success and path.Status == Enum.PathStatus.Success then
local waypoints:{PathWaypoint} = path:GetWaypoints()
return true, waypoints
else
return false, nil
end
end
function draw(waypoints: {PathWaypoint})
end
function pathfind(waypoints, waitUntilFinished)
if RunService:IsStudio() then
waypointFolder:ClearAllChildren()
for i = 2, #waypoints do
local point = Instance.new("Part")
point.Shape = Enum.PartType.Ball
point.Size = Vector3.new(1,1,1)
point.TopSurface = Enum.SurfaceType.Smooth
point.BottomSurface = Enum.SurfaceType.Smooth
point.Color = Color3.new(1,1,1)
point.Material = Enum.Material.Neon
point.Position = waypoints[i].Position
point.Anchored = true
point.CanCollide = false
point.Name = "Waypoint"..i
point.Parent = workspace.WaypointMarkers
end
end
local distance
for i = 2, #waypoints do
if target then
distance = (root.Position - target.PrimaryPart.Position).Magnitude
if distance <= attackDist then
break
end
end
if cancelPath == true then
cancelPath = false
break
end
h:MoveTo(waypoints[i].Position)
if waypoints[i].Action == Enum.PathWaypointAction.Jump then
h.Jump = true
end
if waitUntilFinished then
h.MoveToFinished:Wait()
end
end
walkingBack = false
end
function generateColours()
local torsoColour = BrickColor.random()
local legsColour = BrickColor.random()
bodyColours.TorsoColor = torsoColour
bodyColours.LeftLegColor = legsColour
bodyColours.RightLegColor = legsColour
end
function attack()
while wait() do
if target and target:FindFirstChildOfClass("Humanoid") and distance <= attackDist and (h.Health > 0 and target.Humanoid.Health > 0) then
if canAttack == true then
canAttack = false
local choice = math.random(1,3)
if choice == 1 then
aim(target.PrimaryPart)
attackEvent:Fire()
task.wait(0.1)
aim(target.PrimaryPart)
attackEvent:Fire()
else
aim(target.PrimaryPart)
attackEvent:Fire()
end
wait(attackDelay)
canAttack = true
end
else
end
end
end
function getClosestPlayer()
local nearestPlayer, nearestDistance
for _, player in pairs(Players:GetPlayers()) do
local character = player.Character
local distance = player:DistanceFromCharacter(root.Position)
if not character or
distance > maxDistance or
(nearestDistance and distance >= nearestDistance)
then
continue
end
nearestDistance = distance
nearestPlayer = player
end
return nearestPlayer, nearestDistance
end
function walkBack()
local success, waypoints = compute(origin)
if success then
walkingBack = true
pathfind(waypoints, true)
end
end
function aim(part)
local unit = -(root.CFrame.Position - part.Position).unit
local tween = TweenService:Create(armJoint, TweenInfo.new(0.075, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {C0 = defaultArmPos * CFrame.new(Vector3.new(0, 0, 0), unit) * CFrame.Angles(0,0,math.rad(90))})
tween.Completed:Connect(function()
tween:Destroy()
end)
tween:Play()
end
function look(part)
local unit = -(root.CFrame.Position - part.Position).unit
local tween = TweenService:Create(headJoint, TweenInfo.new(0.075, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {C0 = defaultNeckPos * CFrame.new(Vector3.new(0, 0, 0), unit)})
tween.Completed:Connect(function()
tween:Destroy()
end)
tween:Play()
end
function reset()
local armTween = TweenService:Create(armJoint, TweenInfo.new(.1, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {C0 = defaultArmPos})
armTween.Completed:Connect(function()
armTween:Destroy()
end)
armTween:Play()
local neckTween = TweenService:Create(headJoint, TweenInfo.new(.1, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {C0 = defaultNeckPos})
neckTween.Completed:Connect(function()
neckTween:Destroy()
end)
neckTween:Play()
end
function initialize()
generateColours()
equipEvent:Fire()
attackThread = task.spawn(attack)
--aimThread = task.spawn(aim)
wait(1)
print("Ready!")
end
h.Died:Connect(function()
task.cancel(attackThread)
--task.cancel(aimThread)
local creator:ObjectValue = h:FindFirstChild("creator")
if creator then
local plr = creator.Value
if plr then
local vars = plr:FindFirstChild("PlayerVariables")
if vars then
local KOs = vars:FindFirstChild("KOs")
if KOs then
KOs.Value += 1
end
end
end
end
Debris:AddItem(robot, cleanupTime)
end)
initialize()
while wait() do
if h.Health > 0 then
local plr, dist = getClosestPlayer()
if plr and dist then
local char = plr.Character
distance = dist
if char then
local hum = char:FindFirstChildOfClass("Humanoid")
if hum and hum.Health > 0 then
target = char
look(char.PrimaryPart)
local success, waypoints = compute(char.PrimaryPart.Position)
if success then
if walkingBack == true then
cancelPath = true
walkingBack = false
end
pathfind(waypoints)
else
target = nil
reset()
walkBack()
end
else
target = nil
reset()
walkBack()
end
end
else
target = nil
reset()
walkBack()
end
end
end
Sorry for the code being a little messy