I Need Advice With My Code

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

any suggestions please

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

now what happened when I did that:

the continued spawning!!

but when one of the npc’s left the queue line all of them stopped

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.

I am unsure how to do it, can you give me a tip, please?

how can I store each state individually

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

do i need to change someting in those functions?

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

do I need to insert to the table the npc?

i already did that in the example i gave you, in the wander function, i set the npc to true in the table.

You have to edit all the functions where you set Wandering, to use npcWanderingStates[npc]

so that means that i need to put false here?

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

Yeah that means it stops the next npc from wandering, and moves it to the queue

note that you will probably have to call updateQueue in your module, or wherever you finish serving the last npc.

yes i have this here:

function QueueModule.NPCfinished()
	table.remove(queue, 1)  -- Only remove after the NPC has finished being served
	updateQueue()  -- Move other NPCs forward after removal
end

yeah it should work fine then, let me know if u have any issues

they not wandering for some reason

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

if not Wandering then break end

this is still in your wander function.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.