The functions work in turn

I have NPCs that are all tagged with the “NPC” tag
as well as the module on which the server is running:

local npcmodule = {}
local PathfindingService = game:GetService('PathfindingService')

function npcmodule.Animation(npc, animationname, state)
	local animation = script:WaitForChild(animationname)
	local animationid = animation.AnimationId
	local humanoid = npc:WaitForChild("Humanoid")
	local animator = humanoid.Animator

	if state == "Play" then
		animator:LoadAnimation(animation):Play()
	elseif state == "Stop" then
		for _, animationtrack in pairs(animator:GetPlayingAnimationTracks()) do
			if animationtrack.Name == animationname then
				animationtrack:Stop()
			end
		end
	end
end

function npcmodule.MoveToPoint(npc, goal, goalnumber)
	local humanoid = npc:WaitForChild("Humanoid")
	local rootPart = npc:FindFirstChild("HumanoidRootPart")
	local path = PathfindingService:CreatePath({
		AgentRadius = 2,
		AgentHeight = 5,
		AgentCanJump = true,
		AgentJumpHeight = 10
	})
	path:ComputeAsync(rootPart.Position, goal)
	local waypoints = path:GetWaypoints()

	for _, waypoint in ipairs(waypoints) do
		humanoid:MoveTo(waypoint.Position)
		if waypoint.Action == Enum.PathWaypointAction.Jump then
			humanoid.Jump = true
		end
		humanoid.MoveToFinished:Wait()
	end
end

return npcmodule

Server:

local CollectionService = game:GetService("CollectionService")
local npcModule = require(script.NPCModule)
local treadMills = workspace.TreadMills:GetChildren()
local WeightRs = workspace.WeigtRacks:GetChildren()
local DressRoom = workspace.DressRooms:GetChildren()
local Reception = workspace.Reception
local Door = workspace.Door
local PC = Reception.PC

game.Players.PlayerAdded:Connect(function(plr)
	
	local function WaitForBuy()
		repeat wait(1) until game.Workspace.BuyPart.ProximityPrompt.Triggered:Wait()
	end
	
	local function ThreadMill()
		if #treadMills > 0 then
			
			local randomIndex = math.random(1, #treadMills)
			local randomTreadMill = treadMills[randomIndex]
			
			for i, npc in pairs(CollectionService:GetTagged("NPC")) do
				for i:number, goal in pairs(randomTreadMill.Goals:GetChildren()) do
						
					npcModule.MoveToPoint(npc, goal.Position, i)
					if i == 1 then		
						task.wait(1)
					elseif i == 2 then
							npcModule.Animation(npc, "Run", "Play")
						task.wait(10)
						npcModule.Animation(npc, "Run", "Stop")
					elseif i == 3 then
						task.wait(0.75)
					end
				end
			end
		end
	end

	local function WeightRacks()
		if #WeightRs > 0 then
			local randomIndex = math.random(1, #WeightRs)
			local randomWeightRack = WeightRs[randomIndex]

			for i, npc in pairs(CollectionService:GetTagged("NPC")) do
				for i:number, goal in pairs(randomWeightRack.Goals:GetChildren()) do
					npcModule.MoveToPoint(npc, goal.Position, i)
					if i == 1 then
						task.wait(1)
					elseif i == 2 then
						npcModule.Animation(npc, "Weight", "Play")
						local wei = math.random(1,6)
						local weix = npc["Wei" .. wei*5]

						for i, Child in pairs(weix:GetChildren()) do
							Child.Transparency = 0
						end

						task.wait(10)
						npcModule.Animation(npc, "Weight", "Stop")
						task.wait(1)
						for i, Child in pairs(weix:GetChildren()) do
							Child.Transparency = 1
							task.wait(0.1)
						end
					elseif i == 3 then
						task.wait(1)
					end
				end
			end
		end
	end

	local function Dress()
		if #DressRoom > 0 then

			local randomIndex = math.random(1, #DressRoom)
			local randomTreadMill = DressRoom[randomIndex]

			for i, npc in pairs(CollectionService:GetTagged("NPC")) do
				for i:number, goal in pairs(randomTreadMill.Goals:GetChildren()) do
					npcModule.MoveToPoint(npc, goal.Position, i)
					if i == 1 then
						task.wait(1)
					elseif i == 2 then
						task.wait(5)
					elseif i == 3 then
						task.wait(0.75)
					end
				end
			end
		end
	end

	local function recept()
		for i, npc in pairs(CollectionService:GetTagged("NPC")) do
			if npc:GetAttribute("Recepted") ~= true then
				for i, goal in pairs(Reception.Goals:GetChildren()) do
					npcModule.MoveToPoint(npc, goal.Position, i)
					if i == 1 then
						local triggered = false
						local prompt = PC.ProximityPrompt

						local function onTriggered()
							triggered = true
							prompt.Triggered:Disconnect(onTriggered)
						end

						prompt.Triggered:Connect(onTriggered)

						repeat
							task.wait(1)
						until triggered

					end
				end
				npc:SetAttribute("Recepted", true)
				task.wait(0.1)
				local randomClass = math.random(1,3)
				if randomClass == 1 then
					npc:SetAttribute("Class", 1)
					plr:FindFirstChild("leaderstats").Cash.Value += 500
				elseif randomClass == 2 then
					npc:SetAttribute("Class", 2)
					plr:FindFirstChild("leaderstats").Cash.Value += 750
				else
					npc:SetAttribute("Class", 3)
					plr:FindFirstChild("leaderstats").Cash.Value += 1000
				end
				PC.ProximityPrompt.Enabled = false
			end
		end
	end

	local function GoGym()
		for i, npc in pairs(CollectionService:GetTagged("NPC")) do
			for i, goal in pairs(Door.GoalsIn:GetChildren()) do
				npcModule.MoveToPoint(npc, goal.Position, i)
				if i == 1 then
					task.wait(2)
				elseif i == 2 then
					task.wait(0.5)
				end
			end
		end
	end

	local function OutGym()
		for i, npc in pairs(CollectionService:GetTagged("NPC")) do
			for i:number, goal in pairs(Door.GoalsOut:GetChildren()) do
				npcModule.MoveToPoint(npc, goal.Position, i)
				if i == 1 then
					task.wait(2)
				elseif i == 2  then
					task.wait(3)
					if npc:GetAttribute("Class", 1) then
						plr:FindFirstChild("leaderstats").Cash.Value += 125
					elseif npc:GetAttribute("Class", 2) then
						plr:FindFirstChild("leaderstats").Cash.Value += 175
					else
						plr:FindFirstChild("leaderstats").Cash.Value += 250
					end
				end
			end
		end
	end


	recept()


end)

the problem is that 2 NPC waiting for the moment when 1 finishes executing the function, the same with 3 and so on. I tried to use courotine and spawn function, but although the NPCs were running at the same time thanks to this, the same thing happened to the functions, and I didn’t need it.

1 Like

EDIT: I forgot about the Door loop. I have adjusted the code.

You probably want to wrap only the movement part in the coroutine.

task.spawn(function()
	for i, goal in pairs(Door.GoalsIn:GetChildren()) do
		npcModule.MoveToPoint(npc, goal.Position, i)
		if i == 1 then
			task.wait(2)
		elseif i == 2 then
			task.wait(0.5)
		end
	end
end)

If I understand the problem correctly though, you will still run into issues, as you have no system in place to yield for all NPC to finish their walk.

I would go for bindable event and a simple counter.

local TotalAmountOfNPCs = #CollectionService:GetTagged("NPC")
local finishedCounter = 0
local FinishedWalking = Instance.new("BindableEvent")
FinishedWalking.Event:Connect(function()
	finishedCounter += 1
end)
for i, npc in pairs(CollectionService:GetTagged("NPC")) do
	task.spawn(function()
		for i, goal in pairs(Door.GoalsIn:GetChildren()) do
			npcModule.MoveToPoint(npc, goal.Position, i)
			if i == 1 then
				task.wait(2)
			elseif i == 2 then
				task.wait(0.5)
			end
		end
		FinishedWalking:Fire()
	end)
end
while finishedCounter ~= TotalAmountOfNPCs do
	FinishedWalking.Event:Wait()
	task.wait() --make sure event is handled
end
1 Like

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