I need Help With This Ai NPC System

Hello, So i have this script :

-- Variables

local WayPoints = game.Workspace.Waypoints:GetChildren()

local DMG = 10

local Pathfinding = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local Enemy = script.Parent
local Humanoid = Enemy:WaitForChild("Humanoid")


Enemy.PrimaryPart:SetNetworkOwner(nil)

local RunTrack = Humanoid:LoadAnimation(script.Run.Run)

local WalkTrack = Humanoid:LoadAnimation(script.Walk.Walk)


local RunService = game:GetService("RunService")

local NextWayPoints
local ReachedConnection
local BlockedConnection

local Walkspeed = Enemy:GetAttribute("WalkSpeed")
local SprintSpeed = Enemy:GetAttribute("SprintSpeed")
local Damage = Enemy:GetAttribute("Damage")

local canDMG = false

local punchAnimation = game:GetService("ReplicatedStorage").CombatAssets.Animations.Punch1
local PunchLoaded = Humanoid:LoadAnimation(punchAnimation)

local punchAnimation1 = game:GetService("ReplicatedStorage").CombatAssets.Animations.Punch2
local PunchLoaded1 = Humanoid:LoadAnimation(punchAnimation1)

local punchAnimation2 = game:GetService("ReplicatedStorage").CombatAssets.Animations.Punch3
local PunchLoaded2 = Humanoid:LoadAnimation(punchAnimation2)


--- Functions --

local HitAnimation1 = script.Hit
local HitAnimation2 = script.Hit2
local StunnedAnimation = script.Stunned

local HitboxFolder = workspace.NPCHitbox

local alreadydone = false


local function hitbox()

	local KnockBackModule = require(game.ServerScriptService.CombatSystem.CombatHitBox.LowStageHit)

	--HITBOX
	local hitbox = Instance.new("Part")
	hitbox.Size = Vector3.new(3,3,3)
	hitbox.CanCollide = false
	hitbox.Parent = HitboxFolder
	hitbox.CFrame = Enemy.HumanoidRootPart.CFrame
	hitbox.Massless = true
	hitbox.Transparency = 1
	hitbox.Anchored = false

	--WELD
	local weld = Instance.new("Weld")
	weld.Part0 = Enemy.HumanoidRootPart
	weld.Part1 = hitbox
	weld.C0 = CFrame.new(0,0,-2)
	weld.Parent = weld.Part0


	local canDMG = false

	local HitFx = game:GetService("ReplicatedStorage").CombatAssets.Hit.Attachment:Clone()

	local HitFx2 = game:GetService("ReplicatedStorage").CombatAssets.Hit.A:Clone()

	local StunFx = game:GetService("ReplicatedStorage").CombatAssets.Stun.Attachment:Clone()



	hitbox.Touched:Connect(function(hit)
		-- Cambia il genitore con l'oggetto desiderato, in modo da decidere dove l'audio deve essere riprodotto



		if not canDMG then

			if hit.Parent == Enemy then return end
			if not hit and not hit.Parent then return end
			local enemyCharacter = hit.Parent
			local human = hit.Parent:FindFirstChild("Humanoid")
			local Humanoid = Enemy:WaitForChild("Humanoid")
			if human and human.Health > 0 then



				local PunchSound = script:WaitForChild("Punch"):Clone()
				PunchSound.Parent = Humanoid


				local Stunned = Humanoid:LoadAnimation(StunnedAnimation)

				local EnemyPlayer = game.Players:GetPlayerFromCharacter(enemyCharacter)

				local aToPlay = math.random(1,2)

				local anim1 = human:LoadAnimation(HitAnimation1)
				local anim2 = human:LoadAnimation(HitAnimation2)

				local Hitting = Instance.new("BoolValue")
				Hitting.Name = "Stun"
				Hitting.Value = true
				Hitting.Parent = enemyCharacter





				if human:FindFirstChild("Blocked") and human:FindFirstChild("Blocked").Value == false and human:FindFirstChild("Execution") and human:FindFirstChild("Execution").Value == false then


					DMG = 10
					
					if enemyCharacter:FindFirstChild("Stun") ~= nil then
						human.UseJumpPower = true
						Humanoid.UseJumpPower = true
						Humanoid.JumpPower = 0
						Humanoid.WalkSpeed = 2
						human.WalkSpeed = 0
						human.JumpPower = 0
					end



					HitFx2.Parent = human.Parent:WaitForChild("Torso")
					HitFx2.Slice:Emit(12)

					HitFx.Parent = human.Parent:WaitForChild("Torso")
					HitFx.Lines:Emit(15)


					human:TakeDamage(DMG)

					KnockBackModule.Effects(enemyCharacter, Enemy)


					if aToPlay == 1 then
						anim1:Play()
					elseif aToPlay == 2 then
						anim2:Play()
					end


					print("Hit")




				elseif human:FindFirstChild("Blocked").Value == true then



					Hitting:Destroy()

					local audioId = 4516507682

					local Audioo = Instance.new("Sound")
					Audioo.SoundId = "rbxassetid://" .. audioId

					-- Opzionalmente, puoi impostare altre proprietĂ  dell'audio
					Audioo.Volume = 1
					Audioo.Parent = human -- Cambia il genitore con l'oggetto desiderato, in modo da decidere dove l'audio deve essere riprodotto


					Audioo:Play()

					StunFx.Parent = Humanoid.Parent:WaitForChild("Torso")
					StunFx.Lines:Emit(1)

					Humanoid.AutoRotate = false
					Humanoid.Parent:WaitForChild("Torso").Anchored = true
					Humanoid:FindFirstChild("AnimBlocked").Value = true

					Humanoid:FindFirstChild("Stunned").Value = true

					DMG = 0
					print("parried brot")
					Stunned:Play()
					wait(1.4)

					Humanoid.AutoRotate = true
					Humanoid.Parent:WaitForChild("Torso").Anchored = false
					Humanoid:FindFirstChild("AnimBlocked").Value = false
					Stunned:Stop()
					Humanoid:FindFirstChild("Stunned").Value = false
					Audioo:Destroy()


				end



				canDMG = true


				wait(.4)

				PunchSound:Destroy()


				wait(.1)


				Hitting:Destroy()
				
				
				if enemyCharacter:FindFirstChild("Stun") == nil and human.Health >= 10 then


					human.WalkSpeed = 19

					human.JumpPower = 50

					Humanoid.JumpPower = 50

				elseif human.Health <= 10 then

					human.JumpPower = 0

				end


			end

		end

	end)


	wait(0.6)

	hitbox:Destroy()
	HitFx:Destroy()
	HitFx2:Destroy()


	StunFx:Destroy()
end



local function GetPath(Destination)
	local Path = Pathfinding:CreatePath({
		AgentHeight = 6;
		AgentRadius = 3;
		AgentCanJump = true;
		AgentCanClimb = false;

		Costs = {
			Water = 100;
			DangerZone = math.huge
		}
	})

	Path:ComputeAsync(Enemy.HumanoidRootPart.Position, Destination.Position)

	return Path
end

local function FindTarget()
	local NearestTarget
	local MaxDistance = 50

	for Index, Player in pairs(Players:GetPlayers()) do
		if Player.Character then
			local Target = Player.Character
			local Distance = (Enemy.HumanoidRootPart.Position - Target.HumanoidRootPart.Position).Magnitude

			if Distance < MaxDistance then
				NearestTarget = Target
				MaxDistance = Distance
			end
		end
	end

	return NearestTarget
end

local function Capture(Target)
	local Distance = (Enemy.HumanoidRootPart.Position - Target.HumanoidRootPart.Position).Magnitude

	if Distance > 3 then
		
		if not RunTrack.IsPlaying then
			RunTrack:Play()
		end
		
		if WalkTrack.IsPlaying then
			WalkTrack:Stop()
		end

		Humanoid:MoveTo(Target.HumanoidRootPart.Position)
		
	elseif Humanoid.MoveDirection.Magnitude == 0 then
		if RunTrack.IsPlaying then
			RunTrack:Stop()
		end
		
		if WalkTrack.IsPlaying then
			WalkTrack:Stop()
		end
	end
	
	if Distance < 3 and Enemy:FindFirstChild("Stun") == nil then
		
		local aToPlay = math.random(1,3)

		if aToPlay == 1 then
			PunchLoaded:Play()
		elseif aToPlay == 2 then
			PunchLoaded1:Play()

		elseif aToPlay == 3 then
			PunchLoaded2:Play()
		end

		hitbox()


		wait(.2)
	end
	
end

local function WalkTo(Destination)
	local Path = GetPath(Destination)

	if Path.Status == Enum.PathStatus.Success then
		
		
		for Index, WayPoint in pairs(Path:GetWaypoints()) do
			local Target = FindTarget()

			if Target and Humanoid.Health < 100 and not Target:FindFirstChild("NPC") then
				Capture(Target)
				Enemy.Humanoid.WalkSpeed = SprintSpeed
				break
			else
				if RunTrack.IsPlaying then
					RunTrack:Stop()
				end
				
				if not WalkTrack.IsPlaying then
					WalkTrack:Play()
				end
				
				Enemy.Humanoid.WalkSpeed = Walkspeed
				Humanoid:MoveTo(WayPoint.Position)
				Humanoid.MoveToFinished:Wait()
			end
		end
	else
		Humanoid:MoveTo(Destination.Position - (Enemy.HumanoidRootPart.CFrame.LookVector * 10))
	end
	
end

local function Patrol()
	
	local RandomWaypoint = math.random(1, #WayPoints)
	
	WalkTo(WayPoints[RandomWaypoint])
end

-- Main Program --
while wait(0.001) do
	Patrol()
end

The problem is i would like to stop the NPC When it reach a waypoint. The waypoints are in “local WayPoints = game.Workspace.Waypoints:GetChildren()” But i dont really know how i should do it. I tried to insert a “wait” under “Humanoid.MoveToFinished:Wait()” like that :

local function WalkTo(Destination)
	local Path = GetPath(Destination)

	if Path.Status == Enum.PathStatus.Success then
		
		
		for Index, WayPoint in pairs(Path:GetWaypoints()) do
			local Target = FindTarget()

			if Target and Humanoid.Health < 100 and not Target:FindFirstChild("NPC") then
				Capture(Target)
				Enemy.Humanoid.WalkSpeed = SprintSpeed
				break
			else
				if RunTrack.IsPlaying then
					RunTrack:Stop()
				end
				
				if not WalkTrack.IsPlaying then
					WalkTrack:Play()
				end
				
				Enemy.Humanoid.WalkSpeed = Walkspeed
				Humanoid:MoveTo(WayPoint.Position)
				Humanoid.MoveToFinished:Wait()
				
				
				wait(5)
			end
		end
	else
		Humanoid:MoveTo(Destination.Position - (Enemy.HumanoidRootPart.CFrame.LookVector * 10))
	end
	
end

but the NPC move very slow and dont reach the waypoints, i just wanna do when it reach a waypoint the NPC Have to wait like 5 seconds and move to another waypoint, but when i try to do that it appear like that :

Please help me with that issue i dont know how to fix that or make that.

3 Likes

MoveTo is broken, it “gives up” after 5 or 10 seconds or smht, can’t remember how long exactly. I don’t remember what happens to WaitForMoveToFinished when it gives up.

You could write your own MoveTo function to work around this, it wouldn’t be especially difficult. Ask away if you’d like some pointers for how to do it.

2 Likes

Looking at the video, it looks like it does exactly what you’re asking. It moves to a waypoint and waits a bit, then goes to the next one. Can you clarify what’s wrong in the video?

1 Like

the waypoints are this, i want them to stop like 5 seconds when they reach a waypoint

1 Like

yea i really need help with that im trying to do everything, but nothing works

1 Like