Datastore screwing up max exp

so i am trying to make datastore so levels, currency and stuff like that will be saved everything saves normally except the Max Exp (which is used when exp hits the max exp value to tell that u have enough exp to level up) when i rejoin the game Max Exp is set to 0 which makes instant level up and beacuse level uping is making the max exp * by 2. 0 * 2 = 0 which means you get instant level ups everytime. i have no idea on how to fix this issue so please help me!

Script:

local DataStoreService = game:GetService("DataStoreService")
local LeaderstatsDataStore = DataStoreService:GetDataStore("leaderstatsDataStoreKey222333444")

game.Players.PlayerAdded:Connect(function(plr)
	local leaderstats = Instance.new("Folder", plr)
	leaderstats.Name = "leaderstats"
	
	local Inventory = Instance.new("Folder", plr)
	Inventory.Name = "Inventory"
	
	local Money = Instance.new("IntValue", leaderstats)
	Money.Name = "Money"
	Money.Value = 0
	
	local Level = Instance.new("IntValue", plr)
	Level.Name = "Level"
	Level.Value = 1

	local Exp = Instance.new("IntValue", leaderstats)
	Exp.Name = "Exp"
	Exp.Value = 0
	
	local MaxExp = Instance.new("IntValue", Level)
	MaxExp.Name = "Max"
	MaxExp.Value = 10
	
	Exp.Changed:Connect(function(val)
		if Exp.Value >= MaxExp.Value then
			Level.Value += 1
			Exp.Value = 0
			MaxExp.Value *= 2
		end
	end)
	
	local playerUserId = "Player_"..plr.UserId
	local data = LeaderstatsDataStore:GetAsync(playerUserId)
	
	if data then
		Money.Value = data["Money"]
		Level.Value = data["Level"]
		Exp.Value = data["Exp"]
		MaxExp.Value = data["Max"]
	else
		Money.Value = 0
		Level.Value = 0
		Exp.Value = 0
		MaxExp.Value = 10
	end
end)

local function create_table(player)
	local player_stats = {}
	for _, stat in pairs(player.leaderstats:GetChildren()) do
		player_stats[stat.Name] = stat.Value
	end
	return player_stats
end

game.Players.PlayerRemoving:Connect(function(plr)
	local player_stats = create_table(plr)
	local success, errormessage = pcall(function()
		local playerUserId = "Player_"..plr.UserId
		LeaderstatsDataStore:SetAsync(playerUserId, player_stats)
	end)
	
	if not success then
		print("save error")
		warn(errormessage)
	end
end)
1 Like
MaxExp.Value = data["Max"]

You’re assuming the player’s saved data contains a “Max” entry, which is usually a fair assumption to make. However, you’re not actually saving the player’s max exp value.

local function create_table(player)
	local player_stats = {}
	for _, stat in pairs(player.leaderstats:GetChildren()) do
		player_stats[stat.Name] = stat.Value
	end
	return player_stats
end

Your create table function parses all the data that is parented to the player’s leaderstats folder, but Max is not parented to that folder, it’s parented to Level. So when you call this function, it pulls all of the available data, except Max.

Instead of using :GetChildren() on the player’s leaderstats, I would use :GetDescendants() in order to get every value contained in that folder.

Edit:

Another glance at the code shows me that Level isn’t even parented to the player’s leaderstats, so that value isn’t being saved at all. You can either have level parented to leaderstats and implement the change I recommended, or modify your create_table function to fetch the Level and Max values.

1 Like

i actaully have no idea how to do this when i change it to GetDescendants() then it just doesnt save at all

1 Like

It should be as simple as changing Level to be parented to leaderstats instead of the player and replacing GetChildren with GetDescendants, or you could add these two lines of code to your create_table function

player_stats.Level = player.Level.Value
player_stats.Max = player.Level.Max.Value
1 Like

ok thanks it works now! but also i have a question. do you have any idea on how i could make insides of a folder save?

1 Like

What do you mean by insides of a folder?

1 Like

i mean that i have a folder named “Inventory” in my player and i want to save whatever is inside the “Inventory” folder

You would need to create a function that can serialize the data within that folder so that it can be saved and another function that can parse the serialized data and recreate the inventory folder.

Let’s say your folder is composed entirely of BoolValues, where true represents that the player has the item and false represents that the player does not have the item.

Your two functions could look something like this

function serializeInventory (player)
	local inventoryTable = {}
	
	for _,v in pairs (player.Inventory:GetChildren ()) do
		inventoryTable[v.Name] = v.Value
		
	end
	
	return inventoryTable
end

function createInventoryTable (player, serializedData)
	for i,v in pairs (serializedData) do
		local inventoryItem = Instance.new ("BoolValue")
		inventoryItem.Name = i
		inventoryItem.Value = v
		
		inventoryItem.Parent = player.Inventory		
	end
end

This is just the basic idea behind saving and loading complex data. It’s up to you to take the concept and figure out how to apply it to your project.

1 Like

well the problem is that the folder has tools

Solution : Save the names of the tools. Use these saved names to clone the proper tools back into the player’s inventory.

1 Like

well i have it like this but i now have no idea how to make this

local DataStoreService = game:GetService("DataStoreService")
local LeaderstatsDataStore = DataStoreService:GetDataStore("leaderstatsDataStoreKey222333444555666677")
local InventoryDataStore = DataStoreService:GetDataStore("INVENTORYDATASTOREBABEEEYY2344")

game.Players.PlayerAdded:Connect(function(plr)
	local leaderstats = Instance.new("Folder", plr)
	leaderstats.Name = "leaderstats"
	
	local Inventory = Instance.new("Folder", plr)
	Inventory.Name = "Inventory"
	
	local Money = Instance.new("IntValue", leaderstats)
	Money.Name = "Money"
	Money.Value = 0
	
	local Level = Instance.new("IntValue", plr)
	Level.Name = "Level"
	Level.Value = 0

	local Exp = Instance.new("IntValue", leaderstats)
	Exp.Name = "Exp"
	Exp.Value = 0
	
	local MaxExp = Instance.new("IntValue", Level)
	MaxExp.Name = "Max"
	MaxExp.Value = 10
	
	Exp.Changed:Connect(function(val)
		if Exp.Value >= MaxExp.Value then
			Level.Value += 1
			Exp.Value = 0
			MaxExp.Value *= 2
		end
	end)
	
	local playerUserId = "Player_"..plr.UserId
	local data = LeaderstatsDataStore:GetAsync(playerUserId)
	local data2 = InventoryDataStore:GetAsync(playerUserId)
	
	if data2 then
		Inventory = data["Inventory"]
	else
		
	end
	
	if data then
		Money.Value = data["Money"]
		Level.Value = data["Level"]
		Exp.Value = data["Exp"]
		MaxExp.Value = data["Max"]
	else
		Money.Value = 666
		Level.Value = 0
		Exp.Value = 0
		MaxExp.Value = 10
	end
end)

local function create_table(player)
	local player_stats = {}
	for _, stat in pairs(player.leaderstats:GetChildren()) do
		player_stats.Level = player.Level.Value
		player_stats.Max = player.Level.Max.Value
		player_stats[stat.Name] = stat.Value
	end
	return player_stats
end

local function create_table2(plar)
	local plar_stats = {}
	for _, stat in pairs(plar.Inventory:GetChildren()) do
		local statclone = stat:Clone()
		plar_stats[stat.Name] = stat
	end
end

game.Players.PlayerRemoving:Connect(function(plr)
	local player_stats = create_table(plr)
	local plar_stats = create_table2(plr)
	
	local success, errormessage = pcall(function()
		local playerUserId = "Player_"..plr.UserId
		LeaderstatsDataStore:SetAsync(playerUserId, player_stats)
		InventoryDataStore:SetAsync(playerUserId, plar_stats)
	end)
	
	if not success then
		print("save error")
		warn(errormessage)
	end
end)