Infinite yield possible on 'Players.Captain_Snek:WaitForChild("Quests")

It may look like another infinite yield, but this problem sometimes happens and sometimes doesn’t. I can’t figure out why its warning this:

Local Script:

local openBtn = script.Parent.Parent.ButtonsGui.Buttons.OpenButtonQUEST
local frame = script.Parent:WaitForChild("QuestsFrame")
frame.Visible = false

local tweenDebounce = false

local ogSize = openBtn.Size

openBtn.MouseButton1Down:Connect(function()
	openBtn:TweenSize(ogSize - UDim2.new(0, 2, 0, 2), "In", "Quint", 0.2, true)
end)

openBtn.MouseButton1Click:Connect(function()
	openBtn:TweenSize(ogSize, "In", "Quint", 0.2, true)

	if tweenDebounce then return end
	tweenDebounce = true

	if frame.Visible then
		frame:TweenPosition(UDim2.new(0.5, 0, 0.53, 0), "In", "Quint", 0.2, true)
		task.wait(0.2)
		frame.Visible = false
		tweenDebounce = false

	elseif not frame.Visible then
		frame.Position = UDim2.new(0.5, 0, 0.53, 0)
		frame.Visible = true
		frame:TweenPosition(UDim2.new(0.5, 0, 0.5, 0), "Out", "Quint", 0.2, true)
		task.wait(0.2)
		tweenDebounce = false
	end
end)


local questsFolder = game.Players.LocalPlayer:WaitForChild("Quests")

local lastRefresh = questsFolder:WaitForChild("LastRefresh").Value
local nextRefresh = lastRefresh + (24*60*60)
task.spawn(function()
	while task.wait(1) do
		local now = os.time()

		local timeDiff = nextRefresh - now

		if timeDiff < 0 then break end

		local hours = math.floor(timeDiff / 60 / 60)
		hours = string.format("%02i", hours)
		local mins = math.floor((timeDiff / 60) - (hours * 60))
		mins = string.format("%02i", mins)
		local secs = timeDiff - (mins * 60) - (hours * 60 * 60)
		secs = string.format("%02i", secs)

		frame:WaitForChild("RefreshTime").Text = "Refreshes in " .. hours .. ":" .. mins .. ":" .. secs
	end
	frame:WaitForChild("RefreshTime").Text = "Rejoin for new quests"
end)


function updateQuestsUI()
	for i, child in pairs(frame.QuestsScroller:GetChildren()) do

		if child.ClassName == script:WaitForChild("QuestLabel").ClassName then
			child:Destroy()
		end
	end

	for i, child in pairs(questsFolder:GetChildren()) do
		if child:IsA("Folder") then

			local newLabel = script:WaitForChild("QuestLabel"):Clone()

			local questDesc = child.Name
			local reward = child.Reward.Value
			local goal = child.Goal.Value
			
			newLabel.Clipping.Bar.Pattern.ScaleType = "Tile"
			newLabel.CompletedLabel.Visible = false
			newLabel.CompletedLabel.Pattern.ScaleType = "Tile"
			newLabel.BarBackground.ClipsDescendants = true
			newLabel.QuestDescription.Text = questDesc
			if newLabel.QuestDescription:FindFirstChild("TextShadow") then
				newLabel.QuestDescription.TextShadow.Text = questDesc
			end
			newLabel.Reward.Text = "$" .. reward
			if newLabel.Reward:FindFirstChild("TextShadow") then
				newLabel.Reward.TextShadow.Text = "$" .. reward
			end

			newLabel.Parent = frame.QuestsScroller

			local progress = child.Progress
			local maxSizeX = newLabel.Clipping.Size.X.Scale

			local function updateBar()

				local scale = math.clamp(progress.Value / goal, 0, 1) * maxSizeX
				newLabel.BarProgress.Text = math.floor(progress.Value) .. "/" .. goal
				if newLabel.BarProgress:FindFirstChild("TextShadow") then
					newLabel.BarProgress.TextShadow.Text = math.floor(progress.Value) .. "/" .. goal
				end

				newLabel.Clipping:TweenSize(UDim2.new(scale, 0, newLabel.Clipping.Size.Y.Scale, 0), "InOut", "Linear", 0.2, true)
				newLabel.Clipping.Bar:TweenSize(UDim2.new(maxSizeX / scale, 0, 1, 0), "InOut", "Linear", 0.2, true)
			end

			updateBar()
			progress:GetPropertyChangedSignal("Value"):Connect(updateBar)

			child.ChildAdded:Connect(function(added)
				if added.Name == "Completed" then
					newLabel.CompletedLabel.Visible = true
				end
			end)
			if child:FindFirstChild("Completed") then
				newLabel.CompletedLabel.Visible = true
			end
		end

		local contentSizeY = frame.QuestsScroller.UIListLayout.AbsoluteContentSize.Y
		local scale = contentSizeY / frame.AbsoluteSize.Y
		frame.QuestsScroller.CanvasSize = UDim2.new(0, 0, scale, 0)
	end
end


updateQuestsUI()
questsFolder.ChildAdded:Connect(updateQuestsUI)

Server Script:

local dss = game:GetService("DataStoreService")
local questsDS = dss:GetDataStore("QuestData1")

local quests = { --["QUEST DESCRIPTION"] = {GOAL, CASH REWARD}
	["Play for 10 minutes"] = {10, 500},
	["Walk 500 studs"] = {500, 100},
	["Stand still for 10 seconds"] = {10, 50},
	["Jump 10 times"] = {10, 80},
}
local numQuests = 3 --Number of quests given daily


function saveData(plr)
	
	local cash = plr.CoinsF.Coins.Value
	
	local questsFolder = plr.Quests
	local lastRefresh = questsFolder.LastRefresh.Value
	local currentQuests = {}
	
	for i, child in pairs(questsFolder:GetChildren()) do
		if child:IsA("Folder") then
			
			local questDesc = child.Name
			local progress = child.Progress.Value
			local completed = child:FindFirstChild("Completed") and true
			
			currentQuests[questDesc] = {progress, completed}
		end
	end
	
	local dataList = {}
	dataList.cash = cash
	dataList.refresh = lastRefresh
	dataList.quests = currentQuests
	
	questsDS:SetAsync(plr.UserId, dataList)
end

game.Players.PlayerRemoving:Connect(saveData)
game:BindToClose(function()
	for i, plr in pairs(game.Players:GetPlayers()) do
		saveData(plr)
	end
end)


game.Players.PlayerAdded:Connect(function(plr)
	
	local cash = plr.CoinsF.Coins
	
	local questsFolder = Instance.new("Folder")
	questsFolder.Name = "Quests"
	questsFolder.Parent = plr
	
	
	plr.CharacterAdded:Connect(function(char)
		local currentQuests = {}
		repeat 
			currentQuests = questsFolder:GetChildren()
			task.wait()
		until #currentQuests == (numQuests + 1)
		
		for i, child in pairs(currentQuests) do
			if child:IsA("Folder") and not child:FindFirstChild("Completed") then
				
				if child.Name == "Walk 500 studs" then
					local lastPos = char.HumanoidRootPart.Position * Vector3.new(1, 0, 1)
					
					task.spawn(function()
						while child.Progress.Value ~= child.Goal.Value do 
							local currentPos = char.HumanoidRootPart.Position * Vector3.new(1, 0, 1)
							local distance = (lastPos - currentPos).Magnitude
							
							child.Progress.Value = math.clamp(child.Progress.Value + distance, 0, child.Goal.Value)

							lastPos = currentPos

							task.wait()
						end
						
						local completedValue = Instance.new("BoolValue")
						completedValue.Name = "Completed"
						completedValue.Parent = child
						
						cash.Value += quests[child.Name][2]
					end)
					
				elseif child.Name == "Jump 10 times" then
					char.Humanoid.Jumping:Connect(function(active)

						if active then
							child.Progress.Value = math.clamp(child.Progress.Value + 1, 0, child.Goal.Value)
						end

						if child.Progress.Value == child.Goal.Value and not child:FindFirstChild("Completed") then

							local completed = Instance.new("BoolValue")
							completed.Name = "Completed"
							completed.Parent = child
							
							cash.Value += quests[child.Name][2]
						end
					end)
					
				elseif child.Name == "Stand still for 10 seconds" then
					
					local startTime = os.time()
					
					task.spawn(function()
						while child.Progress.Value ~= child.Goal.Value do
							
							if char.Humanoid.MoveDirection.Magnitude > 0 then
								startTime = os.time()
							end
							
							local timeStill = os.time() - startTime
							child.Progress.Value = math.clamp(timeStill, 0, child.Goal.Value)

							task.wait()
						end

						local completed = Instance.new("BoolValue")
						completed.Name = "Completed"
						completed.Parent = child
						
						cash.Value += quests[child.Name][2]
					end)
				end
			end
		end
	end)
	
	
	local data = questsDS:GetAsync(plr.UserId)
	local cashData = 0
	local lastRefresh = os.time()
	local currentQuests = {}
	
	if data then
		cashData = data.cash
		lastRefresh = data.refresh
		currentQuests = data.quests
	end
	
	if not data or os.time() - lastRefresh >= (24*60*60) then

		currentQuests = {}
		lastRefresh = os.time()

		local questDescs = {}
		for desc, info in pairs(quests) do
			table.insert(questDescs, desc)
		end

		for i = 1, numQuests do

			local randomIndex = math.random(1, #questDescs)
			local randomQuest = questDescs[randomIndex]
			table.remove(questDescs, randomIndex)

			currentQuests[randomQuest] = {0, false}
		end
	end
	
	cash.Value = cashData
	
	local refreshValue = Instance.new("NumberValue")
	refreshValue.Name = "LastRefresh"
	refreshValue.Value = lastRefresh
	refreshValue.Parent = questsFolder
	
	for questDesc, info in pairs(currentQuests) do
		
		local questFolder = Instance.new("Folder")
		questFolder.Name = questDesc
		questFolder.Parent = questsFolder
		
		local progressValue = Instance.new("NumberValue")
		progressValue.Name = "Progress"
		progressValue.Value = info[1]
		progressValue.Parent = questFolder
		
		local goalValue = Instance.new("NumberValue")
		goalValue.Name = "Goal"
		goalValue.Value = quests[questDesc][1]
		goalValue.Parent = questFolder
		
		local rewardValue = Instance.new("NumberValue")
		rewardValue.Name = "Reward"
		rewardValue.Value = quests[questDesc][2]
		rewardValue.Parent = questFolder
		
		local completedValue
		if info[2] == true then
			completedValue = Instance.new("BoolValue")
			completedValue.Name = "Completed"
			completedValue.Parent = questFolder
		end
		
		if questDesc == "Play for 10 minutes" and not completedValue then
			local previous = os.time()
			
			task.spawn(function()
				while task.wait(1) do
					local now = os.time()
					local timeDiff = (now - previous) / 60
					
					progressValue.Value = math.clamp(progressValue.Value + timeDiff, 0, goalValue.Value)
					
					previous = now
					
					if progressValue.Value == 10 then
						break
					end
				end
				
				completedValue = Instance.new("BoolValue")
				completedValue.Name = "Completed"
				completedValue.Parent = questFolder
				
				cash.Value += quests[questDesc][2]
			end)
		end
	end
end)

i used to have this problem before, but i found out some solutions later:

  1. add a wait at the start of the script, for example a task.wait(2-6)
  2. a repeat loop might help, repeat task.wait() until game.Players.LocalPlayer.Quests ~= nil
  3. you can fire a remote event from another script to a local script, which enables the one you’re having the problem with after the folder has been created
Instance.new("Folder")
re:FireClient(plr) -- plr is from the playeradded event as an example

good luck

2 Likes

Which script? The local script or the server script?

a server script, i mentioned FireClient in the example

1 Like

oh alright, should i use only one of the solutions or all of them?

its up to you man, the first one may be the best tho

1 Like

okay, thank you for your help!

I used the task.wait at the start of the server script, and it still shows the infinite yield

I added the second solution and it printed this error in the output
image

PlayerAdded should be above every connection (expect functions) that way it doesn’t void.

1 Like

Never mind i found my own solution, thanks for your help!

1 Like

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