Datastore failing to save

Hey devs,

So I’m making an open-world rpg with stat points and it is saving everything (levels, experience and stat points - you will see what I mean)

Here is my explorer in case it is not referring to the right place:

image (this is inside of every player)

Here is the script (it is a server script in serverscriptservice)

local dss = game:GetService("DataStoreService")
local savedLevelsDS = dss:GetDataStore("LevelsDSS")

function saveData(player)
	pcall(function()
		local level = player.Stats.Level.Value
		local exp = player.Stats.Experience.Value
		local statPoints = player.Stats.StatPoints.Value
		local defensePoints = player.Stats.StatPointStorage.DefensePoints.Value
		local damagePoints = player.Stats.StatPointStorage.DamagePoints.Value

		savedLevelsDS:SetAsync(player.UserId .. "LevelsDSS", {level, exp, statPoints, defensePoints, damagePoints})
	end)
end

game.Players.PlayerAdded:Connect(function(player)
	-- Levels system with xp
	local statsFolder = Instance.new("Folder", player)
	statsFolder.Name = "Stats"

	local levelVal = Instance.new("IntValue", statsFolder)
	levelVal.Name = "Level"
	levelVal.Value = 1

	local expVal = Instance.new("IntValue", statsFolder)
	expVal.Name = "Experience"

	local statPoints = Instance.new("IntValue", statsFolder)
	statPoints.Name = "StatPoints"

	-- Damage, Defense that stuff (stat points)
	local statPointStorage = Instance.new("Folder", statsFolder)
	statPointStorage.Name = "StatPointStorage"

	local defense = Instance.new("IntValue", statPointStorage)
	defense.Name = "DefensePoints"
	
	local damage = Instance.new("IntValue", statPointStorage)
	damage.Name = "DamagePoints"

	pcall(function()
		local data = savedLevelsDS:GetAsync(player.UserId .. "LevelsDSS")
		if data then
			levelVal.Value = data[1]
			expVal.Value = data[2]
			statPoints.Value = data[3]
			defense.Value = data[4]
			damage.Value = data[5]
		end
	end)

	expVal:GetPropertyChangedSignal("Value"):Connect(function()
		local neededExp = math.floor(levelVal.Value ^ 1.5 + 0.5) * 500
		if expVal.Value >= neededExp then
			levelVal.Value += 1
			statPoints.Value += 5
		end
	end)
end)

game.Players.PlayerRemoving:Connect(function(player)
	saveData(player)
end)

game:BindToClose(function()
	for _, player in game.Players:GetPlayers() do
		saveData(player)
	end
end)

Thank you for helping me! :heart:

3 Likes

Are there any error codes caused by this script or other scripts to do with datastores?

1 Like

No, there is no errors. Like I said it is saving everything but the DefensePoints and DamagePoints.

I think DefensePoints and DamagePoints have a different parent from everything else.

1 Like

They do, but it should be redirected to the right place:

image

EDIT: I’m changing it to remove ‘StatPointStorage’ to see if that does anything.

EDIT 2: It did not do anything, it is something wrong with the datastore saving script. Here is the updated explorer:

image

1 Like

I’m assuming you’re testing the script in studio since you sent all the explorer pictures, have you made sure data store access is enabled in your studio on your specific experience?

Yes it certainly is, because like I have said before, the datastore works for everything but the damage and defense points. I’m going to try something, 1 second.

What I tried did not work. I still need help.

Throw in some prints if you haven’t already, what does data print when you join the game, another thing to try is (I HIGHLY doubt this is the problem but what have you got to lose) but use the proper way of parenting instances aka

local x = y
x.Parent = z

also print the values in the savedata function to see where they’re at.

2 Likes

afaik, using this syntax ignores all elements that are nil. Printing them should explain everything

1 Like

I added some prints but it says it’s saving.

What do you mean by this?

1 Like

you are currently parenting your values like this

local x = Instance.new(something, parent)

--instead of

local x = Instance.new(something)
x.Parent = z

also if the data is printed correctly when you join, then the issue lies in the logic with which you are using/applying the saved data to the values

3 Likes

have you tried saving the data in new key?

That didn’t change anything.

I’ll try saving the StatPoints (defensepoints and damagepoints) in another datastore.

I know I’m letting you know for future practice you should do it like that.
Anyhow so the data is being printed correctly?

According to roblox docs, passing a parent in the Instance.new constructor is discouraged for performance reasons

This didn’t work, so I’m going to revert the script back to the old one.

Okay, thank you.

I added some prints before it saved the data and loaded the data and they all printed.

Hmm, at this point I’d just try and make a table with all the values and use HttpService:JSONEncode like this:

local HttpService = game:GetService("HttpService")

function saveData(player)
	pcall(function()
		local level = player.Stats.Level.Value
		local exp = player.Stats.Experience.Value
		local statPoints = player.Stats.StatPoints.Value
		local defensePoints = player.Stats.StatPointStorage.DefensePoints.Value
		local damagePoints = player.Stats.StatPointStorage.DamagePoints.Value

        local data = {Level = level, Experience = exp, StatPoints = statPoints, DefensePoints = defensePoints, DamagePoints = damagePoints}

		savedLevelsDS:SetAsync(player.UserId .. "LevelsDSS", HttpService:JSONEncode(data))
	end)
end

gang then how is your data failing to save, the problem isn’t in the saving it’s in the way you’re using the provided data

1 Like

I don’t know, maybe it’s one of the other scripts? I’ll link all connected scripts:

IncreaseDefenseHandler (in ServerScriptService):

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local Event = ReplicatedStorage:WaitForChild("Events"):WaitForChild("IncreaseDefense")

Event.OnServerEvent:Connect(function(player)
	local humanoid = player.Character:FindFirstChildOfClass("Humanoid")
	if humanoid then
		humanoid.MaxHealth = humanoid.MaxHealth + 5
		humanoid.Health = humanoid.Health + 5
	end
end)

A localscript in a screengui:

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Event = ReplicatedStorage:WaitForChild("Events"):WaitForChild("IncreaseDefense")

local button = script.Parent

button.MouseButton1Click:Connect(function()
	local player = Players.LocalPlayer
	local statsFolder = player:WaitForChild("Stats")
	if statsFolder then
		local statPoints = statsFolder:WaitForChild("StatPoints")
		if statPoints and statPoints.Value > 0 then
			local defenseStat = statsFolder:WaitForChild("DefensePoints")
			if defenseStat then
				defenseStat.Value = defenseStat.Value + 5
				statPoints.Value = statPoints.Value - 1
				Event:FireServer(player)
			else
				warn("Failed to find ".. player .."'s defense stat")
			end
		end
	end
end)

And here is the current script:

local dss = game:GetService("DataStoreService")
local savedLevelsDS = dss:GetDataStore("LevelsDSS")

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Event = ReplicatedStorage:WaitForChild("Events"):WaitForChild("IncreaseDefense")

function saveData(player)
	pcall(function()
		local level = player.Stats.Level.Value
		local exp = player.Stats.Experience.Value
		local statPoints = player.Stats.StatPoints.Value
		local defensePoints = player.Stats.DefensePoints.Value
		local damagePoints = player.Stats.DamagePoints.Value

		savedLevelsDS:SetAsync(player.UserId .. "LevelsDSS", {level, exp, statPoints, defensePoints, damagePoints})
	end)
end

game.Players.PlayerAdded:Connect(function(player)
	local statsFolder = Instance.new("Folder", player)
	statsFolder.Name = "Stats"

	local levelVal = Instance.new("IntValue")
	levelVal.Parent = statsFolder
	levelVal.Name = "Level"
	levelVal.Value = 1

	local expVal = Instance.new("IntValue")
	expVal.Parent = statsFolder
	expVal.Name = "Experience"

	local statPoints = Instance.new("IntValue")
	statPoints.Parent = statsFolder
	statPoints.Name = "StatPoints"

	local defense = Instance.new("IntValue")
	defense.Parent = statsFolder
	defense.Name = "DefensePoints"
	
	local damage = Instance.new("IntValue")
	damage.Parent = statsFolder
	damage.Name = "DamagePoints"

	pcall(function()
		local data = savedLevelsDS:GetAsync(player.UserId .. "LevelsDSS")
		if data then
			levelVal.Value = data[1]
			expVal.Value = data[2]
			statPoints.Value = data[3]
			defense.Value = data[4]
			damage.Value = data[5]
		end
	end)

	expVal:GetPropertyChangedSignal("Value"):Connect(function()
		local neededExp = math.floor(levelVal.Value ^ 1.5 + 0.5) * 500
		if expVal.Value >= neededExp then
			levelVal.Value += 1
			statPoints.Value += 5
		end
	end)
end)

Event.OnServerEvent:Connect(function(player)
	saveData(player)
end)

game.Players.PlayerRemoving:Connect(function(player)
	saveData(player)
end)

game:BindToClose(function()
	for _, player in game.Players:GetPlayers() do
		saveData(player)
	end
end)