How to make NPC Line System?

I’m making a customer system where you are a cashier and npcs come to buy items. I have already made a very buggy and I think hacky way of creating an NPC line system, but I want to know what’s the best way to do it, because my method is very bad.

I currently have a table of the npcs, and once they pathfind to the last location, they get added to the table, and whatever position in the table they are, they move to that location in the line. This works partly, but I have made a max of 7 npcs allowed in a line, as there are only 7 parts. I made it where they stand still if the line is full. But they wont know the line is full until an npc gets to the line to make it full. When this happens, it makes weird bugs. I want the NPCS to whoever gets there first to be ahead in line, so they don’t wait for an npc that’s far away. Is there any other way to do this? Any help would be greatly appreciated. This has been bugging me for quite some time.

1 Like

I would try this, first do not use only 7 spots for the line.
Each spot should be behind each NPC. So when a NPC already reached the last line spot, the NPC becomes the new last line spot.

Watch this image:

Theres a starter spot for the cashout (a green part)
You would have that part as a reference where all NPC should have to try to reach when they are ready to use the cashout.
Once a NPC reached that spot, in script you change the reference of that spot, turn it into the yellow part that is behind each NPC, so that will be the next line spot ALL NPC will try to reach, and again, when another NPC reach the last line spot (the yellow part of the previous NPC) will become the next available spot in line. In that way all NPC will try to reach the spot behind the last NPC that reached the line.

In the picture, 2 NPC are trying to reach the spot, when one of them reach the last spot, it’s yellow spot will become the next available line spot, causing all other NPCs to walk into that new spot, they will become a straight line or curved if they get different orientations.

If you want to not let more than 7, just add statements to not let more NPC to walk to the line.

The event that should make them to walk again would be the player/cashier that finished up checking the items, trigger a function to make all NPC that are in “cashout line table” to walk to the green spot, and next ones to follow the last available spot which would be the yellow part behind each NPC

2 Likes

Would there be a better way to do this? Or is this the best way

One way to implement a customer line system in your cashier game could be to use a queue data structure. A queue is a data structure that follows the “first in, first out” principle, which means that the first element that is added to the queue is the first one to be removed.

Here’s how you could implement a customer line system using a queue:

Create an empty queue to represent the customer line.

local customerLine = {}

When a new customer arrives, add them to the end of the queue.

table.insert(customerLine, newCustomer)

When a customer finishes their transaction and leaves, remove them from the front of the queue.

table.remove(customerLine, 1)

To determine which position in the line the customer should stand in, you can use the index of the customer in the queue. For example, if the customer is at index 3 in the queue, they should stand at the 3rd position in the line.

local positionInLine = table.find(customerLine, customer)

Using a queue data structure can simplify your customer line system and avoid some of the bugs you were experiencing with your previous implementation. It also allows you to have an unlimited number of customers in line, as opposed to your previous limit of 7.

I hope this helps! Let me know if you have any further questions.

1 Like

This was my first implementation actually, where everytime the an npc got to the line, they would be inserted at the end, then removed when they leave and check # of items in the list so there wouldn’t be more than seven. My plan is to use this, but I might have implemented it incorrectly. I’ve implemented like you had said though. How would you know when the customer needs to move down the line? Since I want a max of around 7 npcs, I was thinking if the line was full, they would idle until #items in the list was enough to let them in the line, but what if there are multiple npcs idle, and there’s only one spot? They would all attempt to go to the line, but only one will be able to get there. What will happen to the other NPCs? Thanks for replying though, but these are some questions I really need answered. Thanks

To know when a customer needs to move down the line, you can keep track of the number of customers in front of them in the queue. For example, if a customer is at index 3 in the queue, there are 2 customers in front of them, so they need to move down 2 positions when the customer in front of them leaves.

To handle the situation when the line is full and there are multiple NPCs waiting to get in, you can use a simple check before allowing an NPC to join the line. If there is space available in the queue, the NPC can join the line. If there is no space available, the NPC can be made to wait until there is space available.

One way to do this is to use a separate queue for the idle NPCs. When an NPC arrives and the line is full, add them to the idle queue. When a customer leaves the line and there is space available, remove an NPC from the idle queue and add them to the customer line.

If there are multiple NPCs waiting in the idle queue when a space becomes available in the customer line, you can choose the NPC at the front of the idle queue to join the line. This way, the NPCs are added to the line in the order in which they arrived.

I hope this helps! Let me know if you have any further questions.

This adding another array is such a good idea, but to get the npcs to move, that’s easy, but how will I know when to move them. Also, the NPCs may die, so what then?

To know when to move the NPCs from the idle queue to the customer line, you can use the same logic as for the customers. Keep track of the number of customers in front of them in the customer line, and move the NPCs down the line accordingly when a customer leaves. For example, if an NPC is at index 2 in the idle queue and there are 3 customers in the customer line, when the customer at index 1 leaves the line, the NPC should move down to index 1 in the customer line.

As for NPCs dying, you can remove them from both the customer line and the idle queue when they die. One way to do this is to use a loop that checks the health status of each NPC in both queues, and removes any that have died. You can also add a check for this when an NPC is first added to the queue, to make sure they are still alive before adding them.

Here’s an example of how you could remove dead NPCs from the queues:

-- Loop through the customer line and remove any dead NPCs
for i = #customerLine, 1, -1 do
local customer = customerLine[i]
if customer == nil or customer.Parent == nil or customer.Health <= 0 then
table.remove(customerLine, i)
end
end

-- Loop through the idle queue and remove any dead NPCs
for i = #idleQueue, 1, -1 do
local npc = idleQueue[i]
if npc == nil or npc.Parent == nil or npc.Health <= 0 then
table.remove(idleQueue, i)
end
end

What I’m saying is that in the customer line, How will I know they have moved in the array? Is there like a function to see when the position of an item in an array has moved? I was thinking get the position of it currently, then if it’s different move to that position and then set that position to the current one, repeating this process until they get to the beginning. But I feel like this is a very tacky way of doing it

Metatables would be your best shot, I believe they do hold changed values and that but I’m not entirely sure.