Should you add task.wait in front of every script?

I don’t know if this is making my scripting prevent errors less or more but is using task.wait at the top of every script good because sometimes i will get a infinite yield because the leaderstat will not load in fast enough but i’ve also seen somewhere saying task.wait can cuase errors and make the game crash if used in front of every script or maybe im not setting up my leaderstats correctly to load fast enough here’s my leaderstat script

local Promise = require(game.ReplicatedStorage.Packages:WaitForChild("Promise"))

local PROFILE_STORE_NAME = "GameDatas" -- The name of your ProfileStore
local DEFAULT_DATA = {
	Tokens = 10000,
	TotalTokens = 10000, -- New field to track total tokens ever earned
	Gems = 3500,
	TotalGems = 3500, -- New field to track total tokens ever earned
	PhysicalStats = {
		Strength = "0",
		Endurance = "0",
		Psychic = "0",
		Speed = "0",
	},
	Multipliers = {
		StrengthMulti = "1",  -- Default multiplier for Strength
		EnduranceMulti = "1", -- Default multiplier for Endurance
		PsychicMulti = "1",   -- Default multiplier for Psychic
		SpeedMulti = "1",     -- Default multiplier for Speed
	},
	GemMultipliers = {
		GemStrengthMulti = "1",
		GemEnduranceMulti = "1",
		GemPsychicMulti = "1",
	},
	Stats = {
		Killstreak = 0,
		TokensPerMin = 20,
		PowerMultiplier = "1",
		GeneticsPowerMulti = "1",
		DoublePowerMulti = "1",
		BoostdoublePowerMulti = "1",
		QuestId = "1|0",
		QuestId2 = "1|0",
		QuestId3 = "1|0",
		QuestId4 = "1|0"
	},
	Class = "F-Class",
	Genetics = "None",
	Abilities = {
		Fireball = false,
		SoulHarvest = false,
		LightningStrike = false,
		Elastical = false,
		EnergyPunch = false,
		Teleport = false,
		WalkOnWater = false,
		DamageReflection = false,
		Fly = false,
		Invisibility = false,
	},
}


-- Create a ProfileStore
local ProfileStore = ProfileService.GetProfileStore(PROFILE_STORE_NAME, DEFAULT_DATA)

-- Table to store active player profiles
local Profiles = {}

function InitializeMultipliers(player, profile)
	local multipliers = player:FindFirstChild("Multipliers")
	if not multipliers then
		multipliers = Instance.new("Folder")
		multipliers.Name = "Multipliers"
		multipliers.Parent = player
	end

	-- Initialize each multiplier
	local function createMultiplier(name, defaultValue)
		local multiplier = multipliers:FindFirstChild(name)
		if not multiplier then
			multiplier = Instance.new("StringValue")
			multiplier.Name = name
			multiplier.Value = profile.Data.Multipliers[name] or defaultValue
			multiplier.Parent = multipliers
		end

		-- Save changes back to the profile
		multiplier.Changed:Connect(function()
			profile.Data.Multipliers[name] = multiplier.Value
		end)
	end

	-- Initialize each multiplier with default value of "1"
	createMultiplier("StrengthMulti", "1")
	createMultiplier("EnduranceMulti", "1")
	createMultiplier("PsychicMulti", "1")
	createMultiplier("SpeedMulti", "1")
end



function InitializeGemMultipliers(player, profile)
	local gemMultipliers = player:FindFirstChild("GemMultipliers")
	if not gemMultipliers then
		gemMultipliers = Instance.new("Folder")
		gemMultipliers.Name = "GemMultipliers"
		gemMultipliers.Parent = player
	end

	local function createMultiplier(name, defaultValue)
		local multiplier = gemMultipliers:FindFirstChild(name)
		if not multiplier then
			multiplier = Instance.new("StringValue")
			multiplier.Name = name
			multiplier.Value = profile.Data.GemMultipliers[name] or defaultValue
			multiplier.Parent = gemMultipliers
		end

		multiplier.Changed:Connect(function()
			profile.Data.GemMultipliers[name] = multiplier.Value
		end)
	end

	-- Initialize gem-based stat multipliers (default value is "1")
	createMultiplier("GemStrengthMulti", "1")
	createMultiplier("GemEnduranceMulti", "1")
	createMultiplier("GemPsychicMulti", "1")
end


-- Function to initialize Class and save updates to the profile
function InitializeClass(Player, profile)
	local leaderstats = Player:FindFirstChild("leaderstats")
	if not leaderstats then
		warn("Leaderstats folder is missing for player: " .. Player.Name)
		return
	end

	-- Retrieve the existing Class value from leaderstats or set to the default if missing
	local class = leaderstats:FindFirstChild("Class")
	if not class then
		class = Instance.new("StringValue")
		class.Name = "Class"
		class.Value = profile.Data.Class or "F-Class"  -- Set the value from profile or default
		class.Parent = leaderstats
	else
		-- If the Class already exists, ensure it reflects the value from the profile
		class.Value = profile.Data.Class or "F-Class"
	end

	-- Listen to changes and save to profile
	class.Changed:Connect(function()
		profile.Data.Class = class.Value
		print("Class updated to:", class.Value)  -- Debugging output to ensure the class is saved
	end)
end
-- Function to initialize Fusion and save updates to the profile
function InitializeFusion(Player, profile)
	local leaderstats = Player:FindFirstChild("leaderstats")
	if not leaderstats then
		warn("Leaderstats folder is missing for player: " .. Player.Name)
		return
	end

	-- Retrieve the existing Genetics value from leaderstats or set to the default if missing
	local genetics = leaderstats:FindFirstChild("Genetics")
	if not genetics then
		genetics = Instance.new("StringValue")
		genetics.Name = "Genetics"
		genetics.Value = profile.Data.Genetics or "None"  -- Set the value from profile or default
		genetics.Parent = leaderstats
	else
		-- If the Genetics already exists, ensure it reflects the value from the profile
		genetics.Value = profile.Data.Genetics or "None"
	end

	-- Listen to changes and save to profile
	genetics.Changed:Connect(function()
		profile.Data.Genetics = genetics.Value
		print("Genetics updated to:", genetics.Value)  -- Debugging output to ensure the genetics value is saved
	end)
end


function InitializeAbilities(Player, profile)
	local abilities = Player:FindFirstChild("Abilities")
	if not abilities then
		abilities = Instance.new("Folder")
		abilities.Name = "Abilities"
		abilities.Parent = Player
	end

	local abilityList = {"Fireball", "SoulHarvest", "LightningStrike", "Elastical", "EnergyPunch", "Teleport", "WalkOnWater", "DamageReflection", "Fly", "Invisibility"}

	for _, abilityName in ipairs(abilityList) do
		local ability = abilities:FindFirstChild(abilityName)
		if not ability then
			ability = Instance.new("BoolValue")
			ability.Name = abilityName
			ability.Value = profile.Data.Abilities[abilityName] or false  -- Default to true
			ability.Parent = abilities
		end

		-- Listen for changes to the ability and save to profile
		ability.Changed:Connect(function()
			profile.Data.Abilities[abilityName] = ability.Value
			print(abilityName .. " ability updated to:", ability.Value)
		end)

		-- Add an "Equipped" BoolValue for each ability
		local equipped = abilities:FindFirstChild(abilityName .. "Equipped")
		if not equipped then
			equipped = Instance.new("BoolValue")
			equipped.Name = abilityName .. "Equipped"
			equipped.Value = false -- Default to not equipped
			equipped.Parent = abilities
		end

		-- Listen for changes to the "Equipped" status and save to profile
		equipped.Changed:Connect(function()
			profile.Data.Abilities[abilityName .. "Equipped"] = equipped.Value
			print(abilityName .. " equipped status updated to:", equipped.Value)
		end)
	end
end


function InitializeOtherStats(Player)
	local profile = Profiles[Player]
	if not profile then
		warn("No profile found for player:", Player.Name)
		return
	end

	-- Initialize Class, Fusion, FireballAbility, and Killstreak inside leaderstats
	InitializeAbilities(Player, profile)

	-- Create Stats Folder
	local Stats = Instance.new("Folder")
	Stats.Name = "Stats"
	Stats.Parent = Player


	-- Initialize TokensPerMin
	local tokensPerMin = Instance.new("IntValue")
	tokensPerMin.Name = "TokensPerMin"
	tokensPerMin.Value = profile.Data.Stats.TokensPerMin or 20
	tokensPerMin.Parent = Stats

	-- Listen for changes and save to profile
	tokensPerMin.Changed:Connect(function()
		profile.Data.Stats.TokensPerMin = tokensPerMin.Value
		print("TokensPerMin updated to:", tokensPerMin.Value)
	end)

	-- Initialize PowerMultiplier
	local powerMultiplier = Instance.new("StringValue")
	powerMultiplier.Name = "PowerMultiplier"
	powerMultiplier.Value = profile.Data.Stats.PowerMultiplier or "1"
	powerMultiplier.Parent = Stats

	-- Listen for changes and save to profile
	powerMultiplier.Changed:Connect(function()
		profile.Data.Stats.PowerMultiplier = powerMultiplier.Value
		print("PowerMultiplier updated to:", powerMultiplier.Value)
	end)

	-- Initialize GeneticsPowerMulti
	local geneticsPowerMulti = Instance.new("StringValue")
	geneticsPowerMulti.Name = "GeneticsPowerMulti"
	geneticsPowerMulti.Value = profile.Data.Stats.GeneticsPowerMulti or "1"
	geneticsPowerMulti.Parent = Stats

	-- Listen for changes and save to profile
	geneticsPowerMulti.Changed:Connect(function()
		profile.Data.Stats.GeneticsPowerMulti = geneticsPowerMulti.Value
		print("GeneticsPowerMulti updated to:", geneticsPowerMulti.Value)
	end)

	-- Initialize DoublePowerMulti
	local doublePowerMulti = Instance.new("StringValue")
	doublePowerMulti.Name = "DoublePowerMulti"
	doublePowerMulti.Value = profile.Data.Stats.DoublePowerMulti or "1"
	doublePowerMulti.Parent = Stats

	-- Listen for changes and save to profile
	doublePowerMulti.Changed:Connect(function()
		profile.Data.Stats.DoublePowerMulti = doublePowerMulti.Value
		print("DoublePowerMulti updated to:", doublePowerMulti.Value)
	end)

	-- Initialize BoostdoublePowerMulti
	local boostDoublePowerMulti = Instance.new("StringValue")
	boostDoublePowerMulti.Name = "BoostdoublePowerMulti"
	boostDoublePowerMulti.Value = profile.Data.Stats.BoostdoublePowerMulti or "1"
	boostDoublePowerMulti.Parent = Stats

	-- Listen for changes and save to profile
	boostDoublePowerMulti.Changed:Connect(function()
		profile.Data.Stats.BoostdoublePowerMulti = boostDoublePowerMulti.Value
		print("BoostdoublePowerMulti updated to:", boostDoublePowerMulti.Value)
	end)

	-- Initialize QuestIds inside Player
	local QuestId = Instance.new("StringValue")
	QuestId.Name = "QuestId"
	QuestId.Value = profile.Data.Stats.QuestId or "1|0"
	QuestId.Parent = Player

	-- Listen for changes and save to profile
	QuestId.Changed:Connect(function()
		profile.Data.Stats.QuestId = QuestId.Value
		print("QuestId updated to:", QuestId.Value)
	end)

	local QuestId2 = Instance.new("StringValue")
	QuestId2.Name = "QuestId2"
	QuestId2.Value = profile.Data.Stats.QuestId2 or "1|0"
	QuestId2.Parent = Player

	-- Listen for changes and save to profile
	QuestId2.Changed:Connect(function()
		profile.Data.Stats.QuestId2 = QuestId2.Value
		print("QuestId2 updated to:", QuestId2.Value)
	end)

	local QuestId3 = Instance.new("StringValue")
	QuestId3.Name = "QuestId3"
	QuestId3.Value = profile.Data.Stats.QuestId3 or "1|0"
	QuestId3.Parent = Player

	-- Listen for changes and save to profile
	QuestId3.Changed:Connect(function()
		profile.Data.Stats.QuestId3 = QuestId3.Value
		print("QuestId3 updated to:", QuestId3.Value)
	end)
	
	local QuestId4 = Instance.new("StringValue")
	QuestId4.Name = "QuestId4"
	QuestId4.Value = profile.Data.Stats.QuestId4 or "1|0"
	QuestId4.Parent = Player

	-- Listen for changes and save to profile
	QuestId4.Changed:Connect(function()
		profile.Data.Stats.QuestId4 = QuestId4.Value
		print("QuestId4 updated to:", QuestId4.Value)
	end)


	-- Debugging message to confirm stats initialization
end


function InitializeCurrency(player)
	local profile = Profiles[player]
	if not profile then
		warn("No profile found for player:", player.Name)
		return
	end

	-- Create a folder to store currency values
	local currency = Instance.new("Folder")
	currency.Name = "Currency"
	currency.Parent = player

	-- Initialize Tokens
	local Tokens = Instance.new("IntValue")
	Tokens.Name = "Tokens"
	Tokens.Value = profile.Data.Tokens or 0
	Tokens.Parent = currency

	-- Initialize TotalTokens
	local TotalTokens = Instance.new("IntValue")
	TotalTokens.Name = "TotalTokens"
	TotalTokens.Value = profile.Data.TotalTokens or 0
	TotalTokens.Parent = currency

	-- Initialize Gems
	local Gems = Instance.new("IntValue")
	Gems.Name = "Gems"
	Gems.Value = profile.Data.Gems or 0
	Gems.Parent = currency

	-- Initialize TotalGems
	local TotalGems = Instance.new("IntValue")
	TotalGems.Name = "TotalGems"
	TotalGems.Value = profile.Data.TotalGems or 0
	TotalGems.Parent = currency

	-- Save Tokens + TotalTokens
	Tokens.Changed:Connect(function(newTokens)
		local increment = Tokens.Value - profile.Data.Tokens
		profile.Data.Tokens = Tokens.Value

		if increment > 0 then
			TotalTokens.Value = TotalTokens.Value + increment
			profile.Data.TotalTokens = TotalTokens.Value
		end
	end)

	TotalTokens.Changed:Connect(function()
		profile.Data.TotalTokens = TotalTokens.Value
	end)

	-- Save Gems + TotalGems
	Gems.Changed:Connect(function()
		local increment = Gems.Value - profile.Data.Gems
		profile.Data.Gems = Gems.Value

		if increment > 0 then
			TotalGems.Value = TotalGems.Value + increment
			profile.Data.TotalGems = TotalGems.Value
		end
	end)

	TotalGems.Changed:Connect(function()
		profile.Data.TotalGems = TotalGems.Value
	end)
end



-- Function to initialize Physical Stats
function InitializePhysicalStats(player)
	local profile = Profiles[player]
	if not profile then
		warn("No profile found for player:", player.Name)
		return
	end

	-- Create a folder to store physical stats values
	local physicalStats = Instance.new("Folder")
	physicalStats.Name = "PhysicalStats"
	physicalStats.Parent = player

	-- Initialize Physical Stats with saved values (converted from string to number)
	local Strength = Instance.new("StringValue")
	Strength.Name = "Strength"
	Strength.Value = profile.Data.PhysicalStats.Strength
	Strength.Parent = physicalStats

	local Endurance = Instance.new("StringValue")
	Endurance.Name = "Endurance"
	Endurance.Value = profile.Data.PhysicalStats.Endurance
	Endurance.Parent = physicalStats

	local Psychic = Instance.new("StringValue")
	Psychic.Name = "Psychic"
	Psychic.Value = profile.Data.PhysicalStats.Psychic
	Psychic.Parent = physicalStats

	local Speed = Instance.new("StringValue")
	Speed.Name = "Speed"
	Speed.Value = profile.Data.PhysicalStats.Speed
	Speed.Parent = physicalStats

	-- Calculate Total Power based on the saved Physical Stats
	local TotalPower = Instance.new("StringValue")
	TotalPower.Name = "TotalPower"
	TotalPower.Value = tostring(calculateTotalPower(player))
	TotalPower.Parent = physicalStats

	-- Save updated Physical Stats to the profile when they change
	local function onStatChanged()
		profile.Data.PhysicalStats.Strength = Strength.Value
		profile.Data.PhysicalStats.Endurance = Endurance.Value
		profile.Data.PhysicalStats.Psychic = Psychic.Value
		profile.Data.PhysicalStats.Speed = Speed.Value
		TotalPower.Value = tostring(calculateTotalPower(player))
	end

	Strength.Changed:Connect(onStatChanged)
	Endurance.Changed:Connect(onStatChanged)
	Psychic.Changed:Connect(onStatChanged)
	Speed.Changed:Connect(onStatChanged)
end

-- Function to calculate Total Power based on Physical Stats
function calculateTotalPower(player)
	local stats = player:FindFirstChild("PhysicalStats")
	if not stats then
		return "0"
	end

	local strength = tonumber(stats.Strength.Value) or 0
	local endurance = tonumber(stats.Endurance.Value) or 0
	local psychic = tonumber(stats.Psychic.Value) or 0
	local speed = tonumber(stats.Speed.Value) or 0

	return strength + endurance + psychic + speed
end


local function LoadProfile(player)
	return Promise.new(function(resolve, reject)
		local profile = ProfileStore:LoadProfileAsync("Player_" .. player.UserId)
		if profile then
			profile:Reconcile()
			profile:ListenToRelease(function()
				Profiles[player] = nil
				player:Kick("Your data has been released!")
			end)

			if player:IsDescendantOf(game.Players) then
				resolve(profile)
			else
				profile:Release()
				reject("Player left before data was ready.")
			end
		else
			reject("Failed to load profile.")
		end
	end)
end

game.Players.PlayerAdded:Connect(function(player)
	LoadProfile(player):andThen(function(profile)
		-- ✅ Data loaded successfully
		Profiles[player] = profile

		-- ✅ Create leaderstats early to prevent timing issues
		local leaderstats = Instance.new("Folder")
		leaderstats.Name = "leaderstats"
		leaderstats.Parent = player

		-- ✅ Initialize everything else
		InitializePhysicalStats(player)
		InitializeClass(player, profile)
		InitializeFusion(player, profile)
		InitializeCurrency(player)
		InitializeMultipliers(player, profile)
		InitializeGemMultipliers(player, profile)
		InitializeOtherStats(player)

		print("✅ Player fully initialized:", player.Name)

	end):catch(function(err)
		warn("❌ Error loading profile for", player.Name, ":", err)
		player:Kick("There was a problem loading your data.")
	end)
end)

-- PlayerRemoving handler
game.Players.PlayerRemoving:Connect(function(player)
	local profile = Profiles[player]
	if profile then
		profile:Release()
	end
	Profiles[player] = nil
end)

-- Shutdown handler to save all profiles
game:BindToClose(function()
	for _, profile in pairs(Profiles) do
		profile:Release()
	end
end)
1 Like

You should be able to just do Player:WaitForChild("Leaderstats") on all scripts. Using task.wait() should be avoided.

2 Likes

Not really, but it can be utilized.

The script should have WaitForChild() commands. With server scripts adding players or characters, an up-top pause could make those commands miss altogether. If the script doesn’t have that and it isn’t needed, a longer wait could help overall loading times. Other than that, maybe for a quick test. I do use it on most scripts that are not dependent on startup triggers, however, just for a small boost in loading times. It probably isn’t much and more of a habit.

Alright thanks but do you know what could be the root cause of getting infinite yield errors then? I mean in my game I can clearly see the folder are there but the it seems its not waiting for it and just results to infinite yield for half my scripts which causes other errors idk if im initializing it badly or something.

It’s not right. The path is wrong or the spelling is incorrect. If it is buried in the hierarchy you’ll have to WaitForChild() all the way to it.

local p = game.Players.PlayerAdded:Wait()
local c = p.Character or p.CharacterAdded:Wait()
local part = c:WaitForChild("Head"):WaitForChild("Hat"):WaitForChild("Handle")

That will work for sure..

task.wait(2) — or whatever

This isn’t even going to be for sure, as the character isn’t even loaded yet in this case, and there’s a possible miss in other cases as well. Key words here are “for sure.”

Character appearance loaded event exists so you don’t have to chain waits :broken_heart:

3 Likes

well i know its not a mispell as it only happens sometimes or when multiple people are joining at once i mean here’s one script for example that causes it but that get’s errors a lot

local RS = game:GetService("ReplicatedStorage")
local Player = Players.LocalPlayer

-- Wait for child objects with default wait time of 5 seconds
local Stats = Player:WaitForChild("PhysicalStats", 3)
local Multis = Player:WaitForChild("Multipliers", 3)
local ReputationFolder = Player:WaitForChild("ReputationFolder", 3)
local CurrencyFolder = Player:WaitForChild("Currency", 3)

local MultiFrame = script.Parent.Parent:WaitForChild("MultiFrame", 3)
local MultiInfo = MultiFrame and MultiFrame:WaitForChild("InfoText", 3)

local Modules = RS:WaitForChild("Modules", 3)
local MultiModule = Modules and require(Modules:WaitForChild("Multis", 3))

-- Abbreviation Function
local function abbreviateNumber(num)
	num = tonumber(num)
	if not num then return "Invalid" end

	local abbreviations = {
		{1e75, "QaVg"}, -- Quadravigintillion
		{1e72, "TVg"},  -- Tresvigintillion
		{1e69, "DVg"},  -- Duovigintillion
		{1e66, "UVg"},  -- Unvigintillion
		{1e63, "Vg"},   -- Vigintillion
		{1e60, "Nod"},  -- Novemdecillion
		{1e57, "Ocd"},  -- Octodecillion
		{1e54, "Spd"},  -- Septendecillion
		{1e51, "Sxd"},  -- Sexdecillion
		{1e48, "Qui"},  -- Quindecillion
		{1e45, "Qua"},  -- Quattuordecillion
		{1e42, "Td"},   -- Tredecillion
		{1e39, "Dd"},   -- Duodecillion
		{1e36, "Ud"},   -- Undecillion
		{1e33, "Dc"},   -- Decillion
		{1e30, "N"},    -- Nonillion
		{1e27, "Oc"},   -- Octillion
		{1e24, "Sp"},   -- Septillion
		{1e21, "Sx"},   -- Sextillion
		{1e18, "Qi"},   -- Quintillion
		{1e15, "Qa"},   -- Quadrillion
		{1e12, "T"},    -- Trillion
		{1e9, "B"},     -- Billion
		{1e6, "M"},     -- Million
		{1e3, "K"}      -- Thousand
	}

	for i = 1, #abbreviations do
		local factor, suffix = unpack(abbreviations[i])
		if num >= factor then
			local formattedNumber = num / factor
			if formattedNumber % 1 == 0 then
				return string.format("%d%s", formattedNumber, suffix)
			else
				return string.format("%.2f%s", formattedNumber, suffix)
			end
		end
	end

	return string.format("%d", num)
end

-- Initialize total tokens earned value
local totalTokensEarned = 0
local previousTokenAmount = 0

-- Update Total Power Display
local function updateTotalPowerDisplay()
	local totalPowerFrame = script.Parent:WaitForChild("Total Power", 3)
	if totalPowerFrame then
		local totalPowerDisplay = totalPowerFrame:WaitForChild("TotalPowerDisplay", 3)
		local totalPower = Stats:WaitForChild("TotalPower", 3)
		if totalPowerDisplay and totalPower then
			totalPowerDisplay.Text = "Total Power: " .. abbreviateNumber(tonumber(totalPower.Value) or 0)
		end
	end
end

-- Update Player's Name Display
local function updatePlayersNameDisplay()
	local playersNameFrame = script.Parent:WaitForChild("Players Name", 3)
	if playersNameFrame then
		local playersNameDisplay = playersNameFrame:WaitForChild("PlayersNameDisplay", 3)
		if playersNameDisplay then
			playersNameDisplay.Text = "Name: " .. Player.Name
		end
	end
end

-- Update Reputation Display
local function updateReputationDisplay()
	local reputationFrame = script.Parent:WaitForChild("Reputation", 3)
	if reputationFrame then
		local reputationDisplay = reputationFrame:WaitForChild("ReputationDisplay", 3)
		local reputationValue = ReputationFolder:WaitForChild("Reputation", 3)
		if reputationDisplay and reputationValue then
			reputationDisplay.Text = "Reputation: " .. abbreviateNumber(tonumber(reputationValue.Value) or 0)
		end
	end
end

-- Update Total Tokens Earned Display
local function updateTotalTokensDisplay()
	local totalTokensFrame = script.Parent:WaitForChild("Total Tokens Earned", 3)
	if totalTokensFrame then
		local totalTokensDisplay = totalTokensFrame:WaitForChild("TotalTokensEarnedDisplay", 3)
		local totalTokensStat = CurrencyFolder:WaitForChild("TotalTokens", 3)

		if totalTokensDisplay and totalTokensStat then
			-- Display the TotalTokens value
			totalTokensDisplay.Text = "Total Tokens Earned: " .. abbreviateNumber(totalTokensStat.Value)
		else
			print("TotalTokens not found in Currency folder.")
		end
	end
end
local function blinkErrorMessage(errorMessage)
	for i = 1, 8 do
		errorMessage.Visible = not errorMessage.Visible
		wait(0.05)
	end
end

-- Function to show the error message with blinking
local function showErrorMessage(errorMessage, message)
	errorMessage.Text = message
	errorMessage.Visible = true
	blinkErrorMessage(errorMessage)
	wait(1.7)
	errorMessage.Visible = false
end

-- Update UI elements for each stat frame
for _, Frame in script.Parent:GetChildren() do
	if Frame:IsA("Frame") then
		local statName = string.split(Frame.Name, ' ')[1]
		local stat = Stats:WaitForChild(statName, 3)
		if stat then
			local Multi = Multis:WaitForChild(statName.."Multi", 3)

			local statValue = stat.Value
			Frame:WaitForChild("StatDisplay", 3).Text = statName..": "..abbreviateNumber(statValue)

			stat.Changed:Connect(function()
				local newStatValue = stat.Value
				Frame:WaitForChild("StatDisplay", 3).Text = statName..": "..abbreviateNumber(newStatValue)
				updateTotalPowerDisplay()
			end)

			local multiDisplay = Frame:WaitForChild("MultiDisplayGui", 3)
			if multiDisplay then
				multiDisplay.Text = "x"..abbreviateNumber(Multi.Value)

				Multi.Changed:Connect(function()
					multiDisplay.Text = "x"..abbreviateNumber(Multi.Value)
				end)
			end

			Frame:WaitForChild("MultiButton", 3).MouseButton1Click:Connect(function()
				-- Max multiplier check
				local MAX_MULTI = 7.555786372591432e+22

				if tonumber(Multi.Value) and tonumber(Multi.Value) >= MAX_MULTI then
					-- Play error sound
					local errorSound = workspace:FindFirstChild("Error")
					if errorSound then
						errorSound:Play()
					end

					-- Show blinking error message
					local errorGui = Player:FindFirstChild("PlayerGui"):FindFirstChild("ErrorGui")
					if errorGui then
						local errorMessage = errorGui:FindFirstChild("ErrorMessage")
						if errorMessage then
							showErrorMessage(errorMessage, "You have reached the max multiplier!")
						end
					end
					return -- stop here, don't open upgrade frame
				end

				-- Normal upgrade code if not at max
				local Price = MultiModule.GetNextMultiData(Multi)[2]
				MultiInfo.Text = "Your current multiplier is x" .. abbreviateNumber(Multi.Value) ..
					" would you like to upgrade to x" .. abbreviateNumber(Multi.Value * 2) ..
					" for " .. abbreviateNumber(Price) .. " tokens?"
				MultiFrame.Visible = true
				MultiFrame.CurStat.Value = statName
			end)

		end
	end
end
-- Update Reputation Display when Reputation changes
local Reputation = ReputationFolder:WaitForChild("Reputation", 5)
if Reputation then
	Reputation.Changed:Connect(updateReputationDisplay)
else
	print("Reputation not found in ReputationFolder.")
end

-- Update Total Tokens Earned Display when Tokens change
local Tokens = CurrencyFolder:WaitForChild("Tokens", 5)
if Tokens then
	Tokens.Changed:Connect(updateTotalTokensDisplay)
else
	print("Tokens not found in CurrencyFolder.")
end

-- Initial setup
updateTotalPowerDisplay()
updatePlayersNameDisplay()
updateReputationDisplay()
updateTotalTokensDisplay()

Sometimes it still will need that. The character description has not really loaded yet either.
Again, I was talking about “for sure.”

task.wait() wont make it crash but its useless, just use :WaitForChild() for instances you need where race conditions exist. if you get an infinite yield warning, just ignore it. though, you shouldn’t have to wait that long, maybe insert the leaderstats folder faster.

Infinite yield isn’t an error, it’s a warning. It tells you that the script might be waiting forever if it detects a WaitForChild call that takes more than 5 seconds to complete. However, if the call takes more than 5 seconds(for example 8), the warning will appear at 5 seconds, and then after three seconds, the script will run normally.

Therefore if the warning appears it doesn’t necessarily mean that your code wont run and this isn’t a fix, it just silences the output.

Here’s a test you can run to validate this:

task.spawn(function()
	local part = workspace:WaitForChild("foo") 
	print("bar")
end)

task.wait(8)
Instance.new("Part", workspace).Name = "foo"

After 5 seconds, the warning will appear, and after 8 seconds, bar will be printed. This means that the warning didn’t crash the script.