Infinite yield possible

This sometimes happens and then it doesn’t. When it doesn’t happen, it still doesn’t show the quests

Client:

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("DailyQuests")

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"
	game.Players.LocalPlayer.DamageFolder:WaitForChild("DailyDamageVal").Value = 0
end)


function updateQuestsUI()
	for i, child in pairs(frame.DailyQuestsScroller: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
			newLabel.Reward.Text = "$" .. reward

			newLabel.Parent = frame.DailyQuestsScroller

			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.DailyQuestsScroller.UIListLayout.AbsoluteContentSize.Y
		local scale = contentSizeY / frame.AbsoluteSize.Y
		frame.DailyQuestsScroller.CanvasSize = UDim2.new(0, 0, scale, 0)
	end
end


updateQuestsUI()
questsFolder.ChildAdded:Connect(updateQuestsUI)

Server:

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

local quests = { --["QUEST DESCRIPTION"] = {GOAL, CASH REWARD}
	["Play for 30 minutes"] = {30, 500},
	["Walk 50000 studs"] = {50000, 200},
	["Deal 500 damage"] = {500, 250},
	["Deal 1000 damage"] = {1000, 500},
}
local numQuests = 3 --Number of quests given daily

game.Players.PlayerAdded:Connect(function(plr)
	questsFolder = Instance.new("Folder")
	questsFolder.Name = "DailyQuests"
	questsFolder.Parent = plr
end)

function saveData(plr)
	
	local cash = plr.CoinsF.Coins.Value
	
	local questsFolder = plr.DailyQuests
	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
	
	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 50000 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 == "Deal 500 damage" then
					local dailyDmgVal = plr.DamageFolder:WaitForChild("DailyDamageVal")
					
					dailyDmgVal.Changed:Connect(function()
						child.Progress.Value = dailyDmgVal.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
					elseif child.Name == "Deal 1000 damage" then
					
						cash.Value += quests[child.Name][2]local dailyDmgVal = plr.DamageFolder:WaitForChild("DailyDamageVal")

					dailyDmgVal.Changed:Connect(function()
						child.Progress.Value = dailyDmgVal.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
					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

	
	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 30 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 == 30 then
						break
					end
				end
				
				completedValue = Instance.new("BoolValue")
				completedValue.Name = "Completed"
				completedValue.Parent = questFolder
				
				cash.Value += quests[questDesc][2]
			end)
		end
	end
end)
1 Like

Does questsFolder.LastRefresh exist on the server? I don’t see it being created in your server data management script.

WaitForChild has an optional second timeout parameter, by default this parameter is 5 and throws the error shown above, but you can set it manually to check if it just takes time for it to be added or if it never gets added at all(keep in mind when setting the parameter manually, instead of yielding the value will be set to nil if the instance isn’t added within that timeframe):

--in your client script
local timeout = 100 --wait for 100 seconds
local lastRefresh = questsFolder:WaitForChild("LastRefresh", timeout)
if not lastRefresh then
	warn("The lastRefresh didn't load within "..timeout.." seconds, probably never gets added")
	return
else
	print("lastRefresh just takes time to load")
	lastRefresh = lastRefresh.Value
end
2 Likes

It is created on the server, but sometimes it gets created and sometimes it doesn’t. When it does work, none of the quests appear.

1 Like

Oh right i forgot to add it back since I deleted it, but it still doesn’t work (I moved it to a different part)

this is what happened

The server script has the issue then, it never creates LastRefresh on some occasions.

1 Like

how do I fix it so it always works

I somehow managed to fix it myself lol

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