Datastores saving the wrong data?

Typically I don’t need help with stuff like this, but my brain is currently melting at the fact that this is even happening. Basically I am making a tower defense game and for some reason when players leave after staying in a round for long enough, they unlock all the towers and units, this also only happens when I am in the game (which I unlocked all the towers and units normally)

(also the code is stored in a package if that makes a difference because it makes it easier to update across the whole game)

Here is the data store code if it will help.

main code
local DSS = game:GetService("DataStoreService")
local DataStore = DSS:GetDataStore("PlayerData")

game.Players.PlayerAdded:Connect(function(plr)
	plr:SetAttribute("DataLoaded",false)
	local data = nil
	local success = pcall(function()
		data = DataStore:GetAsync(plr.UserId)
	end)
	if not success or not data then
		data = require(script.Parent.DataStored)
	end
	if data then
		local t = Instance.new("Folder")
		t.Name = "Towers"
		t.Parent = plr
		local u = Instance.new("Folder")
		u.Name = "Units"
		u.Parent = plr
		for _, towers in data.TowersOwn do
			local tower = Instance.new("StringValue")
			tower.Name = towers
			tower.Value = towers
			tower.Parent = t
		end
		for _, units in data.UnitsOwn do
			local unit = Instance.new("StringValue")
			unit.Name = units
			unit.Value = units
			unit.Parent = u
		end
		for i, tower in data.Towers do
			plr:SetAttribute("Tower"..i,tower)
		end
		for i, unit in data.Units do
			plr:SetAttribute("Unit"..i,unit)
		end
		plr:SetAttribute("Gold",data.Gold)
		plr:SetAttribute("Exp",data.Exp)
		plr:SetAttribute("MaxExp",data.MaxExp)
		plr:SetAttribute("Level",data.Level)
		plr.AttributeChanged:Connect(function(attrib)
			if attrib == "Exp" then
				local mxp = plr:GetAttribute("MaxExp")
				if plr:GetAttribute("Exp") >= mxp then
					plr:SetAttribute("Level",plr:GetAttribute("Level")+1)
					plr:SetAttribute("MaxExp",math.floor(mxp*1.25))
					plr:SetAttribute("Exp",plr:GetAttribute("Exp")-mxp)
				end
			end
		end)
	end
	plr:SetAttribute("DataLoaded",true)
end)
game.Players.PlayerRemoving:Connect(function(plr)
	if plr:SetAttribute("DataLoaded") == false then return end
	local data = require(script.Parent.DataStored)
	for _, tower in plr.Towers:GetChildren() do
		if not table.find(data.TowersOwn,tower.Value) then
			table.insert(data.TowersOwn,tower.Value)
		end
	end
	for _, unit in plr.Units:GetChildren() do
		if not table.find(data.UnitsOwn,unit.Value) then
			table.insert(data.UnitsOwn,unit.Value)
		end
	end
	data.Units[1] = plr:GetAttribute("Unit1")
	data.Units[2] = plr:GetAttribute("Unit2")
	data.Units[3] = plr:GetAttribute("Unit3")
	
	data.Towers[1] = plr:GetAttribute("Tower1")
	data.Towers[2] = plr:GetAttribute("Tower2")
	data.Towers[3] = plr:GetAttribute("Tower3")
	data.Towers[4] = plr:GetAttribute("Tower4")
	
	data.Gold = plr:GetAttribute("Gold")
	data.Exp = plr:GetAttribute("Exp")
	data.MaxExp = plr:GetAttribute("MaxExp")
	data.Level = plr:GetAttribute("Level")
	
	DataStore:SetAsync(plr.UserId,data)
end)
game:BindToClose(function()
	while #game.Players:GetPlayers() > 0 and game:GetService("RunService"):IsRunning() do
		task.wait(1)
	end
end)
DataStored module
local module = {
	TowersOwn = {"Survivor"},
	Towers = {[1] = "Survivor",[2] = "",[3] = "",[4] = ""},
	UnitsOwn = {"Zombie","Runner","Tank"},
	Units = {[1] = "Zombie",[2] = "Runner",[3] = "Tank"},
	Gold = 0,
	Exp = 0,
	MaxExp = 100,
	Level = 1
}

return module

You cannot change constant values in a module. I have two ways for you.

1 - Add __index to the module, like following:
module.__index = module

If you don’t set metatables inside a module, it will always return the first given data.
More into metatables: Metatables | Documentation - Roblox Creator Hub

2 - Or, try setting the data template in the server script:

local __DATATEMP = {
	TowersOwn = {"Survivor"},
	Towers = {[1] = "Survivor",[2] = "",[3] = "",[4] = ""},
	UnitsOwn = {"Zombie","Runner","Tank"},
	Units = {[1] = "Zombie",[2] = "Runner",[3] = "Tank"},
	Gold = 0,
	Exp = 0,
	MaxExp = 100,
	Level = 1
}

Hope this works for you, since it worked for me before.

Also, I found another error in your code.
Instead of setting data to nil, do like this:

local success, result = pcall(function()
 -- Success = Boolean
 -- Result = Table or Number, it will return the data given anyway.

return __DATA:GetAsync(player.UserId)
end)

if success and result then
-- Result = The data retrieved (In your way, this will be a table.)

--[[
You can reach the table values as following:

This is what it's going to return:
{
	TowersOwn = {"Survivor"},
	Towers = {[1] = "Survivor",[2] = "",[3] = "",[4] = ""},
	UnitsOwn = {"Zombie","Runner","Tank"},
	Units = {[1] = "Zombie",[2] = "Runner",[3] = "Tank"},
	Gold = 0,
	Exp = 0,
	MaxExp = 100,
	Level = 1
}

For example, we want to reach "Level":

- Just do: 
local level = result.Level (will return 1 in this case, since the level value is 1)
]]--

end
1 Like

Thanks for the help I will try this when I get back home.

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