Hi, I have script for data storing and I am running into an issue where I added a new value to the data store script and now im getting “value of type nil cannot be converted to a number”. Can someone help me please?
local dataStoreService = game:GetService("DataStoreService")
local amountCollected = dataStoreService:GetDataStore("collected")
local CoinsCollected = dataStoreService:GetDataStore("coins")
local RebirthsCollected = dataStoreService:GetDataStore("Rebirths")
game.Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder",player)
leaderstats.Name = "leaderstats"
local collected = Instance.new("IntValue",leaderstats)
collected.Name = "Flags"
collected.Value = 0
local coins = Instance.new("IntValue",leaderstats)
coins.Name = "Geo-Coins"
coins.Value = 0
local Rebirths = Instance.new("IntValue",leaderstats)
Rebirths.Name = "Rebirths"
Rebirths.Value = 0
local playerUserId = "player_"..player.UserId
local amountcollectedData
local coinsData
local rebirthsData
local success, errormessage = pcall(function()
amountcollectedData = amountCollected:GetAsync(playerUserId)
coinsData = CoinsCollected:GetAsync(playerUserId)
rebirthsData = RebirthsCollected:GetAsync(playerUserId)
end)
if success then
coins.Value = coinsData
collected.Value = amountcollectedData
Rebirths.Value = rebirthsData
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local playerUserId = "player_"..player.UserId
local collectedValue = player.leaderstats.Flags.Value
local coinsValue = player.leaderstats["Geo-Coins"].Value
local rebirthsValue = player.leaderstats.Rebirths.Value
local success, errormessage = pcall(function()
amountCollected:SetAsync(playerUserId,collectedValue)
CoinsCollected:SetAsync(playerUserId,coinsValue)
rebirthsValue:SetAsync(playerUserId,rebirthsValue)
end)
end)
game:BindToClose(function()
for _, player in pairs(game.Players:GetPlayers()) do
local playerUserId = "player_"..player.UserId
local collectedValue = player.leaderstats.Flags.Value
local coinsValue = player.leaderstats["Geo-Coins"].Value
local rebirthsValue = player.leaderstats.Rebirths.Value
local success, errormessage = pcall(function()
amountCollected:SetAsync(playerUserId,collectedValue)
CoinsCollected:SetAsync(playerUserId,coinsValue)
RebirthsCollected:SetAsync(playerUserId,rebirthsValue)
end)
end
end)
then who did, why are you tampering with code that you don’t know what the sigma?!
tbh, i suggest just doing UpdateAsync instead of setting some intvalues, and then use GetAsync whenever the player joins and THEN set the intvalues
while i cannot convert the given code for you, i think you should be fine by just looking at my (quite readable) code (saving data only):
function SaveData()
for userId, data in pairs(playerDataTable) do
local success, result = pcall(function()
local key = tostring(userId)
-- These 2 values here are for serializing the color data
-- because you can't store color3 values in datastores
local vitalsGuiColor = data.Settings["Vitals GUI Color"]
local weaponGuiColor = data.Settings["Weapon GUI Color"]
local vitalsGuiColorSerialized = Serialize(vitalsGuiColor)
local weaponGuiColorSerialized = Serialize(weaponGuiColor)
playerDataStorage:UpdateAsync(key, function(oldData)
oldData = oldData or {} -- No current data will instead initialize an empty table :^)
local newData = {
TotalKills = data.TotalKills,
TotalDeaths = data.TotalDeaths,
TotalCurrencyEarned = data.TotalCurrencyEarned,
TotalXpEarned = data.TotalXpEarned,
CurrentLevel = data.CurrentLevel,
CurrentWhisper = data.CurrentWhisper,
Settings = data.Settings
}
newData.Settings["Vitals GUI Color"] = Serialize(newData.Settings["Vitals GUI Color"])
newData.Settings["Weapon GUI Color"] = Serialize(newData.Settings["Weapon GUI Color"])
return newData
end)
end)
if not success then
warn("Failed to save " .. userId .. "'s data!")
warn("Error information: ")
warn(result)
continue -- Skips to the next iteration so that print
-- below doesn't run
end
print("Successfully saved data for " .. userId)
end
end
game.Players.PlayerRemoving:Connect(function(player)
local playerUserId = "player_"..player.UserId
local collectedValue = player.leaderstats.Flags.Value
local coinsValue = player.leaderstats["Geo-Coins"].Value
local rebirthsValue = player.leaderstats.Rebirths.Value
local success, errormessage = pcall(function()
amountCollected:SetAsync(playerUserId,collectedValue)
CoinsCollected:SetAsync(playerUserId,coinsValue)
RebirthsCollected:SetAsync(playerUserId,rebirthsValue) -- changed
end)
if not success then -- changed
warn(errormessage)
end
end)
Also, I suggest saving player data in one single datastore, with this structure:
type PlayerData = {
coins : number,
rebirths : number
collected : number
}
local playerData = PlayerDataStore:GetAsync(playerUserId)
local coins, rebirths, collected = playerData.coins, playerData.rebirths, playerData.collected
Or, alternatively, if it’s a very large project, you could use buffers, but they’re very complicated and I would only suggest using them if memory use is a big issue.
No problem. Also, for the type thing, it’s just a way of clarifying to other programmers and to yourself how you structured your data (or if you’re using --!strict mode).
Here’s a link if you want to learn more about it:
I just find it helps me write nicer code that’s easier to understand, and it works very with roblox’s autocomplete, especially with modules that have classes (object orientation).
An example from a project of mine where I made a radio system:
export type user = {
player : Player,
radio : radiohandle,
connection : RBXScriptConnection
}
export type frequency = {
activeUsers: {user}, -- table containing objects of the user class
freq: number,
Close: () -> (), -- function with no arguments, with no return value
transmitter: ObjectValue,
Connect: (self : frequency, player : Player, radio : radiohandle) -> RBXScriptConnection, -- method taking a player and radiohandle value and returning a RBXScriptConnection so that it can be disconnected.
Disconnect: (self : frequency, player : Player, radio : radiohandle, connection : RBXScriptConnection) -> (),
Transmit: (self : frequency, sourceInstance : AudioListener?) -> boolean, -- method taking the frequency itself as a parameter (common in object oriented programming), and a sourceInstance (the microphone of the transmitting device), and returning a boolean indicating whether the transmission was successful or not
EndTransmit: (self : frequency) -> ()
}
export type radiohandle = {
AudioEmitter: AudioEmitter,
AudioListener: AudioListener,
Events: Folder,
Wire: Wire,
Script: Script
}
local frequencies : {frequency} = {} -- this means that frequencies is a table that contains objects of the "frequency" type defined above