Script Location : ServerScriptService Script Type : ModuleScript
-- My scripter and I have been stuck on it for hours, help would be nice! We have no idea why it doesn't work! --
-- Setup table that we will return to scripts that require the ModuleScript. local PlayerStatManager = {} -- Create variable for the DataStore. local DataStoreService = game:GetService('DataStoreService') local Events = workspace:WaitForChild("Events", 30) local playerData = DataStoreService:GetDataStore('PlayerData') -- Create variable to configure how often the game autosaves the player data. local AUTOSAVE_INTERVAL = 30 -- Number of times we can retry accessing a DataStore before we give up and create -- an error. local DATASTORE_RETRIES = 3 -- Table to hold all of the player information for the current session. local sessionData = {} -- Function the other scripts in our game can call to change a player's stats. This -- function is stored in the returned table so external scripts can use it. function PlayerStatManager:ChangeStat(player, statName, changeValue) sessionData[player][statName] = changeValue end function UpdateData(player) local playerleaderstats = player:WaitForChild("leaderstats", 30) local playerWins = playerleaderstats:WaitForChild("Wins", 30) local playerLevel = playerleaderstats:WaitForChild("Level", 30) local playerCoins = playerleaderstats:WaitForChild("Coins", 30) local playerBoughtItems = player:WaitForChild("BoughtItems", 30) local playerTimesVisited = player:WaitForChild("TimesVisited", 30) local boughtitemst = {} for i, v in pairs(playerBoughtItems:GetChildren()) do boughtitemst[i] = v.Name end sessionData[player] = { Wins = playerWins.Value, Level = playerLevel.Value, Coins = playerCoins.Value, BoughtItems = boughtitemst, TimesVisited = playerTimesVisited.Value } end -- Function to retry the passed in function several times. If the passed in function -- is unable to be run then this function returns false and creates an error. local function dataStoreRetry(dataStoreFunction) local tries = 0 local success = true local data = nil repeat tries = tries + 1 success = pcall(function() data = dataStoreFunction() end) if not success then wait(1) end until tries == DATASTORE_RETRIES or success if not success then warn('Could not access DataStore! Warn players that their data might not get saved!') end return success, data end -- Function to retrieve player's data from the DataStore. local function getPlayerData(player) Events:WaitForChild("DataIconEvent", 30):FireClient(player, "In Progress", "Getting progress...", true) return dataStoreRetry(function() Events:WaitForChild("DataIconEvent", 30):FireClient(player, "Success", "Progress loaded!", true) return playerData:GetAsync(player.UserId) end) end -- Function to save player's data to the DataStore. local function savePlayerData(player) if sessionData[player] then Events:WaitForChild("DataIconEvent", 30):FireClient(player, "In Progress", "Saving progress...", false) return dataStoreRetry(function() Events:WaitForChild("DataIconEvent", 30):FireClient(player, "Success", "Progress saved!", false) print("Saved") return playerData:SetAsync(player.UserId, sessionData[player]) end) end end -- Function to add player to the sessionData table. First check if the player has -- data in the DataStore. If so, we'll use that. If not, we'll add the player to -- the DataStore. local function setupPlayerData(player) local success, data = getPlayerData(player) if not success then -- Could not access DataStore, set session data for player to false. sessionData[player] = false Events:WaitForChild("DataIconEvent", 30):FireClient(player, "Fail", "Something went wrong...", true) else if not data then -- DataStores are working, but no data for this player sessionData[player] = { Wins = 0, Level = 1, Coins = 10, BoughtItems = {}, TimesVisited = 1 } savePlayerData(player) else -- DataStores are working and we got data for this player sessionData[player] = data local playerleaderstats = player:WaitForChild("leaderstats", 30) local playerWins = playerleaderstats:WaitForChild("Wins", 30) local playerLevel = playerleaderstats:WaitForChild("Level", 30) local playerLvlUpExp = playerLevel:WaitForChild("LvlUpExp", 30) local playerCoins = playerleaderstats:WaitForChild("Coins", 30) local playerBoughtItems = player:WaitForChild("BoughtItems", 30) local playerTimesVisited = player:WaitForChild("TimesVisited", 30) local CoinsMultiplier = player:WaitForChild("CoinsMultiplier", 30) local ExpMultiplier = player:WaitForChild("ExpMultiplier", 30) playerWins.Value = sessionData[player].Wins playerLevel.Value = sessionData[player].Level playerLvlUpExp.Value = ((playerLevel.Value * 3) / ExpMultiplier.Value) playerCoins.Value = sessionData[player].Coins for i, v in pairs(sessionData[player].BoughtItems) do local boughtitem = Instance.new("BoolValue", playerBoughtItems) boughtitem.Name = v boughtitem.Value = true end playerTimesVisited.Value = sessionData[player].TimesVisited end end end -- Function to run in the background to periodically save player's data. local function autosave() while wait(AUTOSAVE_INTERVAL) do for player, data in pairs(sessionData) do --UpdateData(player) savePlayerData(player) print("Autosaving...") end end end -- Bind setupPlayerData to PlayerAdded to call it when player joins. game.Players.PlayerAdded:connect(setupPlayerData) -- Call savePlayerData on PlayerRemoving to save player data when they leave. -- Also delete the player from the sessionData, as the player isn't in-game anymore. game.Players.PlayerRemoving:connect(function(player) --UpdateData(player) savePlayerData(player) sessionData[player] = nil end) -- Start running autosave function in the background. spawn(autosave) -- Return the PlayerStatManager table to external scripts can access it. return PlayerStatManager
If you do end up fixing it my scripter and I will add you in credits! Thanks!
On lines 85-87 you can see you're running your first function after binding it to PlayerAdded. Unto which the lines are:
local function setupPlayerData(player) local success, data = getPlayerData(player) if not success then
We can then proceed to getPlayerData(player) to which we then see:
local function getPlayerData(player) Events:WaitForChild("DataIconEvent", 30):FireClient(player, "In Progress", "Getting progress...", true) return dataStoreRetry(function() Events:WaitForChild("DataIconEvent", 30):FireClient(player, "Success", "Progress loaded!", true) return playerData:GetAsync(player.UserId) end) end
Here's the problem, you're returning getPlayerData as a GetAsync, but, there's no Success value! So your GetAsync gets assigned to Success and it is "truthy" so it passes most tests. Which is where your problems start.