I am making a npc system with a queue line. now my goal is to spawn the NPCS and then it will check if there is a free queue position if yes he will forward to that position if there is no free position I want the npc wander in a random position. my problem is that I stuck in the loop and can’t leave him until a free space opens up. i want to spawn more npcs without waiting for a free position,
local function moveToQueuePosition(npc, position)
local path = PathFindingService:CreatePath()
path:ComputeAsync(npc.HumanoidRootPart.Position, position)
if path.Status == Enum.PathStatus.Success then
for _, waypoint in ipairs(path:GetWaypoints()) do
npc.Humanoid:MoveTo(waypoint.Position)
npc.Humanoid.MoveToFinished:Wait()
end
if queue[1] == npc then
QueueModule.serveNPC() -- Call serveNPC if this NPC is first in line
end
else
warn("Pathfinding failed for " .. npc.Name .. " to position " .. tostring(position))
end
end
local function wander(npc)
while Wandering do
local randomPosition = Vector3.new(
math.random(wanderingArea.min.X, wanderingArea.max.X),
npc.HumanoidRootPart.Position.Y,
math.random(wanderingArea.min.Z, wanderingArea.max.Z)
)
local WanderingPath = PathFindingService:CreatePath()
WanderingPath:ComputeAsync(npc.HumanoidRootPart.Position, randomPosition)
if WanderingPath.Status == Enum.PathStatus.Success then
for _, waypoint in ipairs(WanderingPath:GetWaypoints()) do
if Wandering == false then print("interrupted") break end
npc.Humanoid:MoveTo(waypoint.Position)
npc.Humanoid.MoveToFinished:Wait()
end
end
task.wait(math.random(1, 5)) -- Replace wait() with task.wait()
end
end
function QueueModule.addToQueue(npc)
table.insert(queue, npc)
local positionIndex = #queue
if positionIndex <= #queuePositions then
moveToQueuePosition(npc, queuePositions[positionIndex])
else
Wandering = true
end
end
when npc spawns from the spawn script it immediately sends him to the module script to “addToQueue” function
Your issue can probably fixed with using coroutines, or task.spawn to create a new thread for every npc instead of the while loop blocking the main thread.
local Wandering = true
--[[
the rest of ur code
]]
function QueueModule.addToQueue(npc)
table.insert(queue, npc)
local positionIndex = #queue
if positionIndex <= #queuePositions then
moveToQueuePosition(npc, queuePositions[positionIndex])
else
task.spawn(wander, npc)
end
end
I’m not entirely sure what your serveNPC function does, but you will most likely have to store each npcs state individually, instead of having just one variable handling all their wandering.
local npcWanderingStates = {}
local function moveToQueuePosition(npc, position)
-- rest of ur code
if queue[1] == npc then
npcWanderingStates[npc] = false
QueueModule.serveNPC()
end
end
local function wander(npc)
npcWanderingStates[npc] = true
while npcWanderingStates[npc] do
-- rest of ur code
if not npcWanderingStates[npc] then
print("interrupted")
return
end
-- rest of ur code
end
end
and after being served, in your serveNPC function, you will most likely have to remove him from the queue, and then direct the next npc towards the queue
do I need to insert to the table the npc? to use “npcWanderingStates[npc]”
thats my whole code:
local QueueModule = {}
local PathFindingService = game:GetService("PathfindingService")
local queuePositions = {
game.Workspace.Queue1.Position,
game.Workspace.Queue2.Position,
game.Workspace.Queue3.Position,
game.Workspace.Queue4.Position
}
local npcWanderingStates = {}
local wanderingArea = {
min = Vector3.new(-30, 0, -30),
max = Vector3.new(30, 0, 30)
}
local queue = {}
local Wandering = false
-- Function to move NPCs to queue positions
local function moveToQueuePosition(npc, position)
local path = PathFindingService:CreatePath()
path:ComputeAsync(npc.HumanoidRootPart.Position, position)
if path.Status == Enum.PathStatus.Success then
for _, waypoint in ipairs(path:GetWaypoints()) do
npc.Humanoid:MoveTo(waypoint.Position)
npc.Humanoid.MoveToFinished:Wait()
end
if queue[1] == npc then
npcWanderingStates[npc] = false
QueueModule.serveNPC() -- Call serveNPC if this NPC is first in line
end
else
warn("Pathfinding failed for " .. npc.Name .. " to position " .. tostring(position))
end
end
local function wander(npc)
npcWanderingStates[npc] = true
while npcWanderingStates[npc] do
if not npcWanderingStates[npc] then
print("interrupted")
return
end
local randomPosition = Vector3.new(
math.random(wanderingArea.min.X, wanderingArea.max.X),
npc.HumanoidRootPart.Position.Y,
math.random(wanderingArea.min.Z, wanderingArea.max.Z)
)
local WanderingPath = PathFindingService:CreatePath()
WanderingPath:ComputeAsync(npc.HumanoidRootPart.Position, randomPosition)
if WanderingPath.Status == Enum.PathStatus.Success then
for _, waypoint in ipairs(WanderingPath:GetWaypoints()) do
if not Wandering then break end
npc.Humanoid:MoveTo(waypoint.Position)
npc.Humanoid.MoveToFinished:Wait()
end
end
task.wait(math.random(1, 5))
end
end
function QueueModule.addToQueue(npc)
table.insert(queue, npc)
local positionIndex = #queue
if positionIndex <= #queuePositions then
moveToQueuePosition(npc, queuePositions[positionIndex])
else
Wandering = true
task.spawn(wander, npc) -- Use task.spawn to run wander in a coroutine
end
end
local function updateQueue()
for i, npc in ipairs(queue) do
if i <= #queuePositions then
Wandering = false
moveToQueuePosition(npc, queuePositions[i])
else
print(npc.Name .. " is still waiting for a queue position.")
end
end
end
function QueueModule.NPCfinished()
table.remove(queue, 1) -- Only remove after the NPC has finished being served
updateQueue() -- Move other NPCs forward after removal
end
function QueueModule.serveNPC()
if #queue > 0 then
local servedNpc = queue[1]
local mainModule = servedNpc:FindFirstChild("MainModule")
if mainModule then
require(mainModule).handleItemScanning(servedNpc) -- Call the function if it exists
end
end
end
return QueueModule
function QueueModule.addToQueue(npc)
table.insert(queue, npc)
local positionIndex = #queue
if positionIndex <= #queuePositions then
moveToQueuePosition(npc, queuePositions[positionIndex])
else
Wandering = true
task.spawn(wander, npc) -- Use task.spawn to run wander in a coroutine
end
end
local function updateQueue()
for i, npc in ipairs(queue) do
if i <= #queuePositions then
Wandering = false
moveToQueuePosition(npc, queuePositions[i])
else
print(npc.Name .. " is still waiting for a queue position.")
end
end
end
local function updateQueue()
for i, npc in ipairs(queue) do
if i <= #queuePositions then
npcWanderingStates[npc] = false
moveToQueuePosition(npc, queuePositions[i])
else
print(npc.Name .. " is still waiting for a queue position.")
end
end
end
function QueueModule.NPCfinished()
table.remove(queue, 1) -- Only remove after the NPC has finished being served
updateQueue() -- Move other NPCs forward after removal
end
local QueueModule = {}
local PathFindingService = game:GetService("PathfindingService")
local queuePositions = {
game.Workspace.Queue1.Position,
game.Workspace.Queue2.Position,
game.Workspace.Queue3.Position,
game.Workspace.Queue4.Position
}
local npcWanderingStates = {}
local wanderingArea = {
min = Vector3.new(-30, 0, -30),
max = Vector3.new(30, 0, 30)
}
local queue = {}
-- Function to move NPCs to queue positions
local function moveToQueuePosition(npc, position)
local path = PathFindingService:CreatePath()
path:ComputeAsync(npc.HumanoidRootPart.Position, position)
if path.Status == Enum.PathStatus.Success then
for _, waypoint in ipairs(path:GetWaypoints()) do
npc.Humanoid:MoveTo(waypoint.Position)
npc.Humanoid.MoveToFinished:Wait()
end
if queue[1] == npc then
npcWanderingStates[npc] = false
QueueModule.serveNPC() -- Call serveNPC if this NPC is first in line
end
else
--warn("Pathfinding failed for " .. npc.Name .. " to position " .. tostring(position))
end
end
local function wander(npc)
npcWanderingStates[npc] = true
while npcWanderingStates[npc] do
print("before")
if not npcWanderingStates[npc] then
print("interrupted")
return
end
print("after")
local randomPosition = Vector3.new(
math.random(wanderingArea.min.X, wanderingArea.max.X),
npc.HumanoidRootPart.Position.Y,
math.random(wanderingArea.min.Z, wanderingArea.max.Z)
)
local WanderingPath = PathFindingService:CreatePath()
WanderingPath:ComputeAsync(npc.HumanoidRootPart.Position, randomPosition)
if WanderingPath.Status == Enum.PathStatus.Success then
for _, waypoint in ipairs(WanderingPath:GetWaypoints()) do
if not Wandering then break end
npc.Humanoid:MoveTo(waypoint.Position)
npc.Humanoid.MoveToFinished:Wait()
end
end
task.wait(math.random(1, 5))
end
end
function QueueModule.addToQueue(npc)
table.insert(queue, npc)
local positionIndex = #queue
if positionIndex <= #queuePositions then
moveToQueuePosition(npc, queuePositions[positionIndex])
else
task.spawn(wander, npc) -- Use task.spawn to run wander in a coroutine
end
end
local function updateQueue()
for i, npc in ipairs(queue) do
if i <= #queuePositions then
npcWanderingStates[npc] = false
moveToQueuePosition(npc, queuePositions[i])
else
print(npc.Name .. " is still waiting for a queue position.")
end
end
end
function QueueModule.NPCfinished()
table.remove(queue, 1) -- Only remove after the NPC has finished being served
updateQueue() -- Move other NPCs forward after removal
end
function QueueModule.serveNPC()
if #queue > 0 then
local servedNpc = queue[1]
local mainModule = servedNpc:FindFirstChild("MainModule")
if mainModule then
require(mainModule).handleItemScanning(servedNpc) -- Call the function if it exists
end
end
end
return QueueModule