Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

IntValue always load as: 0, but not as last number as it was. Where is mistake?

So, I trying to create auto-saving stats for players. But, for some reason it always loads at 0. Something like: I close game with "strength 3", but when start game again "strength" will be at 0.

local DSS = game:GetService("DataStoreService")
local MDS = DSS:GetDataStore("MyDataStore")

game.Players.PlayerAdded:Connect(function(player)
	local Stats = Instance.new("Folder") --All "stats" with folder.
    Stats.Name = "Stats"
    Stats.Parent = player
	
	local AGL = Instance.new("IntValue")
	AGL.Name = "AGL"
	AGL.Parent = Stats
	AGL.Value = 1
	
	local STR = Instance.new("IntValue")
	STR.Name = "STR"
	STR.Parent = Stats
	STR.Value = 1
	
	local INT = Instance.new("IntValue")
	INT.Name = "INT"
	INT.Parent = Stats
	INT.Value = 1
	
	local VIT = Instance.new("IntValue")
	VIT.Name = "VIT"
	VIT.Parent = Stats
	VIT.Value = 1
	
	local LOD = Instance.new("IntValue")
	LOD.Name = "LAD"
	LOD.Parent = Stats
	LOD.Value = 1
	
	local LeVeL = Instance.new("IntValue")
	LeVeL.Name = "LeVeL"
	LeVeL.Parent = Stats
	LeVeL.Value = 0
	
	local essenceNeeded = Instance.new("IntValue") --checking data
	essenceNeeded.Name = "essenceNeeded"
	essenceNeeded.Parent = Stats
	essenceNeeded.Value = 1
	
	local data
	local success, errormessage = pcall(function()
		data = MDS:GetAsync(player.UserId)
	end)
	
	if success then
		AGL.Value = data[1] --loading data or sending error
		INT.Value = data[2]
		STR.Value = data[3]
		VIT.Value = data[4]
		LOD.Value = data[5]
	    LeVeL.Value = data[6]
		essenceNeeded.Value = data[7]
		print("Data loaded")
	else
		print("Not success")
		warn(errormessage)
	end
end)

game.Players.PlayerRemoving:Connect(function(player) --saving data
	local function create_table(player)
		local player_stats = {}
		for _, stat in pairs(player.Stats:GetChildren()) do
			    player_stats[stat.Name] = stat.Value
	end
		return player_stats
end

	local success, errormessage = pcall(function()
		local player_stats = create_table(player)
		        local playerUserId = "Player_" .. player.UserId
		        MDS:SetAsync(playerUserId, player_stats)
    end)

	if success then
		print("Data saved")
	else
		print("Fail")
		warn(errormessage)
	end
end)

I already tried changing script, or creating new but different. I tried added 'print("1works")' everything goes right.

1 answer

✓ Accepted answer

Your code looks reasonably correct, but you are missing BindToClose, which you can use to delay Roblox from shutting down right away (giving your script time to save to the data store).

[Edit]

The idea is to keep your code mostly the same, but tell Roblox to keep the server open while you still need to save data:

local DSS = game:GetService("DataStoreService")
local MDS = DSS:GetDataStore("MyDataStore")

game.Players.PlayerAdded:Connect(function(player)
    local Stats = Instance.new("Folder") --All "stats" with folder.
    Stats.Name = "Stats"
    Stats.Parent = player

    local AGL = Instance.new("IntValue")
    AGL.Name = "AGL"
    AGL.Parent = Stats
    AGL.Value = 1

    local STR = Instance.new("IntValue")
    STR.Name = "STR"
    STR.Parent = Stats
    STR.Value = 1

    local INT = Instance.new("IntValue")
    INT.Name = "INT"
    INT.Parent = Stats
    INT.Value = 1

    local VIT = Instance.new("IntValue")
    VIT.Name = "VIT"
    VIT.Parent = Stats
    VIT.Value = 1

    local LOD = Instance.new("IntValue")
    LOD.Name = "LAD"
    LOD.Parent = Stats
    LOD.Value = 1

    local LeVeL = Instance.new("IntValue")
    LeVeL.Name = "LeVeL"
    LeVeL.Parent = Stats
    LeVeL.Value = 0

    local essenceNeeded = Instance.new("IntValue") --checking data
    essenceNeeded.Name = "essenceNeeded"
    essenceNeeded.Parent = Stats
    essenceNeeded.Value = 1

    local data
    local success, errormessage = pcall(function()
        data = MDS:GetAsync(player.UserId)
    end)

    if success then
        AGL.Value = data[1] --loading data or sending error
        INT.Value = data[2]
        STR.Value = data[3]
        VIT.Value = data[4]
        LOD.Value = data[5]
        LeVeL.Value = data[6]
        essenceNeeded.Value = data[7]
        print("Data loaded")
    else
        print("Not success")
        warn(errormessage)
    end
end)

local saving = {}

if not game:GetService("RunService"):IsStudio() then -- you can delete this line if you want to save data in studio tests
	game:BindToClose(function()
		while #game.Players:GetPlayers() > 0 or next(saving) do
			wait()
		end
	end)
end

local function create_table(player)
    local player_stats = {}
    for _, stat in ipairs(player.Stats:GetChildren()) do
        player_stats[stat.Name] = stat.Value
    end
    return player_stats
end
game.Players.PlayerRemoving:Connect(function(player) --saving data
    local player_stats = create_table(player)
    local playerUserId = "Player_" .. player.UserId
    saving[player] = true
    local success, errormessage = pcall(function()
        MDS:SetAsync(playerUserId, player_stats)
    end)
    saving[player] = nil

    if success then
        print("Data saved")
    else
        print("Fail")
        warn(errormessage)
    end
end)

We put the saving[player] = lines as close to the pcall as possible (without being inside) so that, if other code errors for whatever reason, we won't end up with a memory leak. Any yielding statements (ex SetAsync pauses while the save is occurring) must occur between saving[player] = true and saving[player] = nil. The BindToClose loop uses next(saving) to determine if there are any players in the table - if there are no players in the server and none in saving, it exits the loop, allowing Roblox to close the server.

5 comments

0

chess123mate, BindToClose helped but then new error shows: "ServerScriptService.statsStorage:67: attempt to index nil with 'Stats'"

0

I assume you've changed your code somehow because 'player' should be defined on line 67. I would print out 'player' at various parts of your code (in the PlayerRemoving function) to make sure that it exists and figure out how it becomes nil.

0

Probably because I changed "64: game.Players.PlayerRemoving:Connect(function(player)" to "64: game.BindToClose:Connect(function(player)".

0

I've edited the answer to clarify

0

chess123mate, really thanks for help. I would never correct that without help.

This discussion is preserved as it was. New answers, comments, and votes are closed.