Did you try my new method? (also remove the GetData in your regular script, just don’t set the value there, it’ll be set in the module script) Then check your explorer window to see if the data is set there.
Also, just as a recommendation, for the change stat function, also modify it to this:
function PlayerStatManager:ChangeStat(player, statName, value)
local playerUserId = "Player_" .. player.UserId
assert(typeof(sessionData[playerUserId][statName]) == typeof(value), "ChangeStat error: types do not match")
if typeof(sessionData[playerUserId][statName]) == "number" then
sessionData[playerUserId][statName] = sessionData[playerUserId][statName] + value
else
sessionData[playerUserId][statName] = value
end
UpdateBoard2Player(player)
end
I think you meant AddBoard2Player instead of UpdateBoard2Player.
Lol, I wasn’t seeing the code, sorry about that.
I’m not sure if it works; there are no errors.
Yeah so if you’re testing it in Roblox Studio, just check the Explorer tab, and go under your Player object, search for the value, and check its Value property to see if it’s correct. Hope this helps!
Everything in the explorer looks good, but the NameCol and BioCol values are “0, 0, 0” and appear black.
Edit: I think it’s because I made the color of the Gui to be the value, which is “255, 255, 255” instead of adding a Color3.fromRGB in front of it.
I have the Cash value in a leaderstats folder. How would I index the Cash value?
The Color values are blank for some reason.
Oh yeah, I just want to add a friendly tip. As I made two games before, here’s my experience. Sometimes you want to add more types of data in your game, and if you already have data before playing the game, it would cause you to not have that extra data, so here’s my solution for that:
Add a table of the default values you want for your data:
local DefaultData = {
Cash = 50000,
Name = player.Name,
Bio = "",
NameCol = "255, 255, 255",
BioCol = "0, 255, 255"
}
Then a function that can return a copy of your default values (setting a variable as a table will reference it, not make a copy of it):
local function CloneTableFunction(Table)
local CloneTable = {}
for Key,Value in pairs(Table) do
if type(Value) == "table" then
Value = CloneTableFunction(Value)
end
CloneTable[Key] = Value
end
return DefaultData
end
So then you could change your setupPlayerData function to this:
local function setupPlayerData(player)
local playerUserId = "Player_" .. player.UserId
local success, data = pcall(function()
return playerData:GetAsync(playerUserId)
end)
if success then
if data then
local DefaultClone = CloneTableFunction(DefaultData)
local function CheckFunction(BaseTable, CheckTable)
for Key,Value in pairs(CheckTable) do
if BaseTable[Key] and type(Value) == "table" then
CheckFunction(BaseTable[Key], Value)
end
if not BaseTable[Key] then
BaseTable[Key] = Value
end
end
return BaseTable
end
data = CheckFunction(data, DefaultClone)
sessionData[playerUserId] = data
else
sessionData[playerUserId] = CloneTableFunction(DefaultData)
end
AddBoard2Player(player)
else
warn("Cannot access data store for player!")
end
end
Also, I see your new replies as I’m typing this, so can you show me your Value object hierarchy in the Explorer?
Let’s try this:
function AddBoard2Player(player)
local playerUserId = "Player_" .. player.UserId
if sessionData[playerUserId] then
for DataName, DataValue in pairs(sessionData[playerUserId]) do
local DataObject = player:FindFirstChild(DataName)
if DataObject then
DataObject.Value = DataValue
end
local Leaderstats = player:FindFirstChild("leaderstats")
if Leaderstats then
local LeaderstatDataObject = Leaderstats:FindFirstChild(DataName)
if LeaderstatDataObject then
LeaderstatDataObject.Value = DataValue
end
end
end
end
end
How do I get the player value?
Replace that with a “”, but what I don’t really get is that you can already get the player name easily from player.Name, so why bother use up space in the DataStore to store the player’s name? But yeah, after that, also go to your setupPlayerData function and write:
local function setupPlayerData(player)
local playerUserId = "Player_" .. player.UserId
local success, data = pcall(function()
return playerData:GetAsync(playerUserId)
end)
if success then
if data then
local DefaultClone = CloneTableFunction(DefaultData)
local function CheckFunction(BaseTable, CheckTable)
for Key,Value in pairs(CheckTable) do
if BaseTable[Key] and type(Value) == "table" then
CheckFunction(BaseTable[Key], Value)
end
if not BaseTable[Key] then
BaseTable[Key] = Value
end
end
return BaseTable
end
data = CheckFunction(data, DefaultClone)
sessionData[playerUserId] = data
sessionData[playerUserId]["Name"] = player.Name
else
sessionData[playerUserId] = CloneTableFunction(DefaultData)
sessionData[playerUserId]["Name"] = player.Name
end
AddBoard2Player(player)
else
warn("Cannot access data store for player!")
end
end
This is my ModuleScript now:
-- Set up table to return to any script that requires this module script
local PlayerStatManager = {}
local DataStoreService = game:GetService("DataStoreService")
local playerData = DataStoreService:GetDataStore("PlayerData")
-- Table to hold player information for the current session
local DefaultData = {
Cash = 50000,
Name = "",
Bio = "",
NameCol = "255, 255, 255",
BioCol = "0, 255, 255"
}
local function CloneTableFunction(Table)
local CloneTable = {}
for Key,Value in pairs(Table) do
if type(Value) == "table" then
Value = CloneTableFunction(Value)
end
CloneTable[Key] = Value
end
return DefaultData
end
local sessionData = {}
function AddBoard2Player(player)
local playerUserId = "Player_" .. player.UserId
if sessionData[playerUserId] then
for DataName, DataValue in pairs(sessionData[playerUserId]) do
local DataObject = player:FindFirstChild(DataName)
if DataObject then
DataObject.Value = DataValue
end
local Leaderstats = player:FindFirstChild("leaderstats")
if Leaderstats then
local LeaderstatDataObject = player:FindFirstChild(DataName)
if LeaderstatDataObject then
LeaderstatDataObject.Value = DataValue
end
end
end
end
end
-- Function that other scripts can call to change a player's stats
function PlayerStatManager:ChangeStat(player, statName, value)
local playerUserId = "Player_" .. player.UserId
assert(typeof(sessionData[playerUserId][statName]) == typeof(value), "ChangeStat error: types do not match")
if typeof(sessionData[playerUserId][statName]) == "number" then
sessionData[playerUserId][statName] = sessionData[playerUserId][statName] + value
print(sessionData)
else
sessionData[playerUserId][statName] = value
print(sessionData)
end
AddBoard2Player(player)
end
-- Function to add player to the "sessionData" table
local function setupPlayerData(player)
local playerUserId = "Player_" .. player.UserId
local success, data = pcall(function()
return playerData:GetAsync(playerUserId)
end)
if success then
if data then
local DefaultClone = CloneTableFunction(DefaultData)
local function CheckFunction(BaseTable, CheckTable)
for Key,Value in pairs(CheckTable) do
if BaseTable[Key] and type(Value) == "table" then
CheckFunction(BaseTable[Key], Value)
end
if not BaseTable[Key] then
BaseTable[Key] = Value
end
end
return BaseTable
end
data = CheckFunction(data, DefaultClone)
sessionData[playerUserId] = data
sessionData[playerUserId]["Name"] = player.Name
else
sessionData[playerUserId] = CloneTableFunction(DefaultData)
sessionData[playerUserId]["Name"] = player.Name
end
AddBoard2Player(player)
else
warn("Cannot access data store for player!")
end
end
local function savePlayerData(playerUserId)
if sessionData[playerUserId] then
local tries = 0
local success
repeat
tries = tries + 1
success = pcall(function()
playerData:SetAsync(playerUserId, sessionData[playerUserId])
end)
if not success then wait(1) end
until tries == 3 or success
local success, err = pcall(function()
playerData:SetAsync(playerUserId, sessionData[playerUserId])
end)
if not success then
warn("Cannot save data for player!")
end
end
end
function PlayerStatManager:GetData(player, statName)
local playerUserId = "Player_" .. player.UserId
if sessionData[playerUserId][statName] then
return sessionData[playerUserId][statName]
end
end
-- Function to save player data on exit
local function saveOnExit(player)
local playerUserId = "Player_" .. player.UserId
savePlayerData(playerUserId)
end
-- Connect "setupPlayerData()" function to "PlayerAdded" event
game.Players.PlayerAdded:Connect(setupPlayerData)
-- Connect "saveOnExit()" function to "PlayerRemoving" event
game.Players.PlayerRemoving:Connect(saveOnExit)
return PlayerStatManager
I don’t know if its right or not.
This is what my explorer looks like
Just check their properties and see if they’re right. Hopefully they are!
The colors are still black though.
I don’t know if this script is the problem or not:
local DataStoreService = game:GetService("DataStoreService")
local playerData = DataStoreService:GetDataStore("PlayerData")
local Players = game:GetService("Players")
local PlayerStatManager = require(game.ServerScriptService.DataSetup)
Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local Cash = Instance.new("IntValue")
Cash.Name = "Cash"
Cash.Parent = leaderstats
local RPName = Instance.new("StringValue")
RPName.Name = "RPName"
RPName.Parent = player
local RPBio = Instance.new("StringValue")
RPBio.Name = "RPBio"
RPBio.Parent = player
local NameCol = Instance.new("StringValue")
NameCol.Name = "NameCol"
NameCol.Parent = player
local BioCol = Instance.new("StringValue")
BioCol.Name = "BioCol"
BioCol.Parent = player
local OwnsHouse = Instance.new("BoolValue")
OwnsHouse.Name = "OwnsHouse"
OwnsHouse.Value = false
OwnsHouse.Parent = player
local Char = player.Character or player.CharacterAdded:Wait()
local HeadCol = Instance.new("Color3Value")
HeadCol.Parent = player
HeadCol.Value = Char:WaitForChild("Humanoid").HumanoidDescription.HeadColor
HeadCol.Name = "HeadCol"
local TorsoCol = Instance.new("Color3Value")
TorsoCol.Parent = player
TorsoCol.Value = Char:WaitForChild("Humanoid").HumanoidDescription.TorsoColor
TorsoCol.Name = "TorsoCol"
local LeftArmCol = Instance.new("Color3Value")
LeftArmCol.Parent = player
LeftArmCol.Value = Char:WaitForChild("Humanoid").HumanoidDescription.LeftArmColor
LeftArmCol.Name = "LeftArmCol"
local RightArmCol = Instance.new("Color3Value")
RightArmCol.Parent = player
RightArmCol.Value = Char:WaitForChild("Humanoid").HumanoidDescription.RightArmColor
RightArmCol.Name = "RightArmCol"
local LeftLegCol = Instance.new("Color3Value")
LeftLegCol.Parent = player
LeftLegCol.Value = Char:WaitForChild("Humanoid").HumanoidDescription.LeftLegColor
LeftLegCol.Name = "LeftLegCol"
local RightLegCol = Instance.new("Color3Value")
RightLegCol.Parent = player
RightLegCol.Value = Char:WaitForChild("Humanoid").HumanoidDescription.RightLegColor
RightLegCol.Name = "RightLegCol"
local ShirtId = Instance.new("StringValue")
ShirtId.Parent = player
ShirtId.Name = "ShirtId"
if Char:WaitForChild("Shirt") ~= nil then
ShirtId.Value = Char.Shirt.ShirtTemplate
else
ShirtId.Value = ""
end
local PantsId = Instance.new("StringValue")
PantsId.Parent = player
PantsId.Name = "PantsId"
if Char:WaitForChild("Pants") ~= nil then
PantsId.Value = Char.Pants.PantsTemplate
else
PantsId.Value = ""
end
end)
Can you tell me which values isn’t working? And can you provide me a screenshot of your new sessionData?
The Color values are correct, but it makes the TextLabel black.
Also, I’m testing it out right now.
sessionData:
Nice, the data is correct. I think the problem would be that your Label’s Color3 value needs to be set to something like this: Label.TextColor3 = Color3.fromRGB(NameCol.Value)
. Basically it needs to be wrapped by the Color3.fromRGB(). I’m not sure if you already scripted it that way though.