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)