Before you help me try and figure this out just know I am using SimplePath for my NPC. SimplePath - Pathfinding Module
I want my NPC to be able to move continusly without having to wait also to switch between chase and patrol states with ease. In chase mode the NPC will wait until it finishes going to the goal rather then continusioly making the player its goal. Ive tried multiple forums and youtube tutorials but still havent found a solution.
This is the code please let me know if you find any flaws or any reason as to why my NPC wont do what I want it to…
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local simplePath = require(ReplicatedStorage:WaitForChild("SimplePath"))
local NoiseEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("PlayerNoiseEvent")
local NPC = workspace:WaitForChild("BlindMonster2")
local Humanoid = NPC:FindFirstChildOfClass("Humanoid")
local NPC_Root = NPC.PrimaryPart or NPC:FindFirstChild("HumanoidRootPart")
local PatrolPoints = workspace:WaitForChild("PatrolPoints"):GetChildren()
local playerDetected = false
local patrolling = false
local activePath = nil
local patrolResetTask = nil
local maxDetectionRange = 50
local attackRange = 5
local damage = 10
local attackCooldown = 2
local lastAttackTime = 0
local pathRegen = 0.05
local patrolWaitTimeMin = 2
local patrolWaitTimeMax = 6
local resumePatrolDelay = 1
local function StopCurrentPath()
print("stop")
if activePath and activePath._status == "Active" then
activePath:Stop()
end
activePath = nil
end
local function Patrol()
print("patrol")
if playerDetected then return end -- If chasing, don't patrol
StopCurrentPath() -- Clears any existing path before starting patrol
patrolling = true
local randomPoint = PatrolPoints[math.random(1, #PatrolPoints)]
local patrolPosition = randomPoint.Position
activePath = simplePath.new(NPC)
activePath.Visualize = true
local success = activePath:Run(patrolPosition)
print("path")
if not success then
print("no")
patrolling = false
task.wait(1)
Patrol()
return
end
task.spawn(function()
while activePath and activePath._status == "Active" do
task.wait(pathRegen)
end
if activePath and activePath._status == "Idle" and not playerDetected then
task.wait(math.random(patrolWaitTimeMin, patrolWaitTimeMax))
patrolling = false
Patrol()
end
end)
end
local function ResetPatrolAfterDelay()
print("reset patrol")
if patrolResetTask then
task.cancel(patrolResetTask) -- Cancels any previous reset
end
patrolResetTask = task.delay(resumePatrolDelay, function()
if not playerDetected and not patrolling then
print("Resuming patrol after losing player.")
Patrol()
end
end)
end
local function MoveToSound(soundType, position)
print("sound")
if not NPC_Root then return end
local distance = (NPC_Root.Position - position).Magnitude
if distance > maxDetectionRange then
playerDetected = false
return
end
StopCurrentPath() -- Ensures old paths are stopped before moving to sound
playerDetected = true
patrolling = false
activePath = simplePath.new(NPC)
activePath.Visualize = true
activePath:Run(position)
print("path")
if Humanoid then
Humanoid.WalkSpeed = 22
end
task.spawn(function()
while activePath and activePath._status == "Active" do
task.wait(pathRegen)
end
if activePath and activePath._status == "Idle" then
playerDetected = false
ResetPatrolAfterDelay()
end
end)
end
local function AttackPlayer(player)
print("attacked")
if tick() - lastAttackTime < attackCooldown then return end
lastAttackTime = tick()
local humanoid = player:FindFirstChildOfClass("Humanoid")
if humanoid then
humanoid:TakeDamage(damage)
end
end
NoiseEvent.OnServerEvent:Connect(function(player, soundType, position)
print("noise")
if playerDetected then return end -- Ignore if already chasing
local distance = (NPC_Root.Position - position).Magnitude
if distance > maxDetectionRange then return end
StopCurrentPath() -- Stops patrolling if chasing starts
MoveToSound(soundType, position)
end)
task.spawn(function()
while true do
task.wait(3)
if not playerDetected and not patrolling then
Patrol()
end
end
end)