Hi!
I can't get my DataStore script to save the Tools purchased. I don't know why. I don't get any error for it. The leaderstats save, the Tools do not. I've included my entire Leaderboard/DataStore script.
I've included two versions I've been advised to try for the DataStore, the first one tries to save it into a Folder, the second one checks for BoolValues, but neither one will save the Tools, just the leaderstats.
First attempt with a Folder:
game.Players.ChildAdded:connect(function(newPlayer) local stats = Instance.new('IntValue') stats.Name = 'leaderstats' local points = Instance.new('IntValue', stats) points.Name = 'Points' points.Value = 0 local experience = Instance.new('IntValue', stats) experience.Name = 'EXP' experience.Value = 0 local wins = Instance.new('IntValue', stats) wins.Name = 'Wins' wins.Value = 0 local kills = Instance.new('IntValue', stats) kills.Name = 'Kills' kills.Value = 0 local level = Instance.new('IntValue', stats) level.Name = 'Level' level.Value = 1 -- MAX HEALTH INCREASE if newPlayer.Character and newPlayer.Character:FindFirstChild("Humanoid") then newPlayer.Character.Humanoid.MaxHealth = 100 + level.Value*10 end level.Changed:connect(function(value) if newPlayer.Character and newPlayer.Character:FindFirstChild("Humanoid") then newPlayer.Character.Humanoid.MaxHealth = 100 + level.Value*10 end end) newPlayer.CharacterAdded:connect(function(character) character:WaitForChild("Humanoid").MaxHealth = 100 + level.Value*10 end) -- EXP NEEDED TO LEVEL UP experience.Changed:connect(function() local required=(level.Value*70) -- Number reflects the EXP points needed to level up. if experience.Value >= required then level.Value=level.Value+1 experience.Value=experience.Value-required end end) --DATASTORE stats.Parent = newPlayer local datastore = game:GetService("DataStoreService"):GetDataStore(newPlayer.Name.."Stats") local tools = game.ServerStorage.ToolStorage;-- ADDED FOR TOOLS local stats = stats:GetChildren() for i = 1, #stats do stats[i].Value = datastore:GetAsync(stats[i].Name) print("stat number "..i.." has been found") end local save_interval = 60 * 2 -- every 2 minutes wait(save_interval) while newPlayer.Parent do local stats = newPlayer.leaderstats:GetChildren() for i = 1, #stats do datastore:SetAsync(stats[i].Name, stats[i].Value) print("stat number "..i.." has been auto-saved") end local data = false print("DataStoreBackSave1") newPlayer.CharacterAdded:connect(function(char) -- this will run everytime the Player's Character has been added in workspace. if not data then data = datastore:GetAsync(newPlayer.UserId); end if data then --If it does, loop and clone respective tools. for _,v in next,data do local tool = tools:FindFirstChild(v); if tool then tool:Clone().Parent = newPlayer.Backpack; end end end end) end wait(save_interval) end) game.Players.ChildRemoved:connect(function(oldPlayer) local datastore = game:GetService("DataStoreService"):GetDataStore(oldPlayer.Name.."Stats") local stats = oldPlayer.leaderstats:GetChildren() for i = 1, #stats do datastore:SetAsync(stats[i].Name, stats[i].Value) print("stat number "..i.." has been saved") --Make a table to hold all the data local toolList = {}; --Iterate through the backpack and fill the table in for _,v in next,oldPlayer.Backpack:GetChildren() do --Make sure it's actually a tool if v:IsA("Tool") or v:IsA("HopperBin") then toolList[#toolList+1] = v.Name; end end --Save the table datastore:SetAsync(oldPlayer.UserId,toolList); end print("DataStoreBackSave2") end)
Second attempt with BoolValues:
stats.Parent = newPlayer local datastore = game:GetService("DataStoreService"):GetDataStore(newPlayer.Name.."Stats") local stats = stats:GetChildren() for i = 1, #stats do stats[i].Value = datastore:GetAsync(stats[i].Name) print("stat number "..i.." has been found") end local save_interval = 60 * 2 -- every 2 minutes wait(save_interval) while newPlayer.Parent do local stats = newPlayer.leaderstats:GetChildren() for i = 1, #stats do datastore:SetAsync(stats[i].Name, stats[i].Value) print("stat number "..i.." has been auto-saved") end wait(save_interval) end newPlayer.PlayerGui:WaitForChild("HasM9").Changed:Connect(function() if newPlayer.PlayerGui.HasM9.Value == true then local DataStorem9 = game:GetService("DataStoreService"):GetDataStore("HasM9") game.ServerStorage.ToolStorage.M9:Clone().Parent = newPlayer.Backpack DataStorem9:SetAsync(newPlayer.userId, true) end end) end) game.Players.ChildRemoved:connect(function(oldPlayer) local datastore = game:GetService("DataStoreService"):GetDataStore(oldPlayer.Name.."Stats") local stats = oldPlayer.leaderstats:GetChildren() for i = 1, #stats do datastore:SetAsync(stats[i].Name, stats[i].Value) print("stat number "..i.." has been saved") end oldPlayer.PlayerGui:WaitForChild("HasM9").Changed:Connect(function() if oldPlayer.PlayerGui.HasM9.Value == true then local DataStorem9 = game:GetService("DataStoreService"):GetDataStore("HasM9") DataStorem9:SetAsync(oldPlayer.userId, true) end end) end)
I could really appreciate some help here, this has been bothering me for months now. x.x
Unfortunately, your question was a bit more complex than I though it was, but I am sure I can still answer it.
Step 1. You want to create a folder of bool values in the player, each one named for ex: HasM9, HasM82 etc, each one should be false.
Then you want to create your data-store, I haven't changed mine to fit your question, but I have added lots of comments so you know what to do with the code.
Note : You should save tables on your keys, not individual values, each key can take alot, and it will lower how many times you access the data-store, lowering the chance of the data store budget being reached. Make sure to also use one datastore, not lots of datastores, unless each datastore holds different types of data, e.g XP datastore, Gun datastore etc. Your datastore should have a Unique name, this prevents the data you have saved being overwritten by data that has been saved in other games, also make sure your keys have unique names, and use Player.UserId, because if a player changes their name, they lose all of their data.
A Module script, in ServerScriptService
local module = {} local DataStoreService = game:GetService("DataStoreService") --get DataStoreService local InventoryItems = DataStoreService:GetDataStore("InventoryItems") --Change it to whatever you want to call it e.g :GetDataStore("examplename"), should be complex name AUTOSAVE_INTERVAL = 120 --should be no lower than 60 (DataStore Budget) game.Players.PlayerAdded:Connect(function(Player) --When a player is added to the game, load in their data local Key = 'PlayerIdNum-'..Player.UserId.."_InvItemKey" --"This is the key you use to save players data on (must be no longer than 50 characters and must be unique) --The key is also what you use to load data as well so it MUST be the exact same variable in the other parts of the script --Values to Save (create them also, e.g instance.new) local InvData = Player:WaitForChild("Backpack"):WaitForChild("Inventory") --The folder of values you want to save local Bananas = InvData:WaitForChild("Bananas") local Apples = InvData:WaitForChild("Apples") local FirstAid = InvData:WaitForChild("FirstAid") local Coconuts = InvData:WaitForChild("Coconuts") local MetalScraps = InvData:WaitForChild("MetalScraps") local Logs = InvData:WaitForChild("Logs") local Sticks = InvData:WaitForChild("Sticks") --DataStore Stuff --The table that is used to save it after it is all loaded in local StoreToSet = {} --Get the data and store it local DataToGet = InventoryItems:GetAsync(Key) --Returns the data the key stores (as a table) --Changing the table back into values if DataToGet ~= nil then --If there is a table if #DataToGet >= 1 then --If the table length is 1 or more print("Has Data") --For each value you have, copy the below code (MUST BE IN ORDER OF SAVED IN!) if DataToGet[1] ~= nil then --if the first bit of data in the table does exist Bananas.Value = DataToGet[1] --Set the values of bananas as that value table.insert(StoreToSet , DataToGet[1]) --Store it in another table so it can be saved end if DataToGet[2] ~= nil then Apples.Value = DataToGet[2] table.insert(StoreToSet , DataToGet[2]) end if DataToGet[3] ~= nil then FirstAid.Value = DataToGet[3] table.insert(StoreToSet , DataToGet[3]) end if DataToGet[4] ~= nil then Coconuts.Value = DataToGet[4] table.insert(StoreToSet , DataToGet[4]) end if DataToGet[5] ~= nil then MetalScraps.Value = DataToGet[5] table.insert(StoreToSet , DataToGet[5]) end if DataToGet[6] ~= nil then Logs.Value = DataToGet[6] table.insert(StoreToSet , DataToGet[6]) end if DataToGet[7] ~= nil then Sticks.Value = DataToGet[7] table.insert(StoreToSet , DataToGet[7]) end print(DataToGet[1], DataToGet[2], DataToGet[3], DataToGet[4], DataToGet[5], DataToGet[6], DataToGet[7] .. " Data") --Print the data values end else DataToGet = {} --Create a table, since there was no data or table returned in the GetAsync (this only happens with new players) DataToGet[1] = Bananas.Value --The first bit of data in the table is equal to Bananas.Value Bananas.Value = 0 --Make sure it is 0 table.insert(StoreToSet , DataToGet[1]) --Insert it into table, so it can be saved, so next time they join, it loads a table DataToGet[2] = Apples.Value Apples.Value = 0 table.insert(StoreToSet , DataToGet[2]) DataToGet[3] = FirstAid.Value FirstAid.Value = 0 table.insert(StoreToSet , DataToGet[3]) DataToGet[4] = Coconuts.Value Coconuts.Value = 0 table.insert(StoreToSet , DataToGet[4]) DataToGet[5] = MetalScraps.Value MetalScraps.Value = 0 table.insert(StoreToSet , DataToGet[5]) DataToGet[6] = Logs.Value Logs.Value = 0 table.insert(StoreToSet , DataToGet[6]) DataToGet[7] = Sticks.Value Sticks.Value = 0 table.insert(StoreToSet , DataToGet[7]) print(DataToGet[1], DataToGet[2], DataToGet[3], DataToGet[4], DataToGet[5], DataToGet[6], DataToGet[7] .. " New Data") --Print new data (all should be 0) end InventoryItems:SetAsync(Key, StoreToSet) --Set the data to the key as a table, so next time they join there is a table to load in (only affects the first time they join) end) game.Players.PlayerRemoving:Connect(function(Player) --When the player leaves the game, save their data local Key = 'PlayerIdNum-'..Player.UserId.."_InvItemKey" --"This is the key you use to save players data on (must be no longer than 50 characters and must be unique) --The key is also what you use to load data as well so it MUST be the exact same variable in the other parts of the script --Values to Save local InvData = Player:WaitForChild("Backpack"):WaitForChild("Inventory") local Bananas = InvData:WaitForChild("Bananas") local Apples = InvData:WaitForChild("Apples") local FirstAid = InvData:WaitForChild("FirstAid") local Coconuts = InvData:WaitForChild("Coconuts") local MetalScraps = InvData:WaitForChild("MetalScraps") local Logs = InvData:WaitForChild("Logs") local Sticks = InvData:WaitForChild("Sticks") --Put what you need to save here (THE ORDER YOU USE IN THIS IS THE ORDER YOU MUST USE WHEN THEY JOIN) local DataToSave = { Bananas.Value, --must put.Value after or it will error Apples.Value, FirstAid.Value, Coconuts.Value, MetalScraps.Value, Logs.Value, Sticks.Value, } InventoryItems:SetAsync(Key, DataToSave) end) --You may want to reorder this --Autosaving spawn(function() while wait(AUTOSAVE_INTERVAL) do for i, Player in pairs (game:GetService("Players"):GetChildren()) do --for every player in the game, save print("Auto-saving " .. Player.Name .. "'s Data") local Key = 'PlayerIdNum-'..Player.UserId.."_InvItemKey" local InvData = Player:WaitForChild("Backpack"):WaitForChild("Inventory") local Bananas = InvData:WaitForChild("Bananas") local Apples = InvData:WaitForChild("Apples") local FirstAid = InvData:WaitForChild("FirstAid") local Coconuts = InvData:WaitForChild("Coconuts") local MetalScraps = InvData:WaitForChild("MetalScraps") local Logs = InvData:WaitForChild("Logs") local Sticks = InvData:WaitForChild("Sticks") local DataToSave = { Bananas.Value, Apples.Value, FirstAid.Value, Coconuts.Value, MetalScraps.Value, Logs.Value, Sticks.Value, } InventoryItems:SetAsync(Key, DataToSave) print("Successfully Auto-saved " .. Player.Name .. "'s Data") end end end) return module
A normal script, but a child/decendent of/inside of the module script
require(script.Parent)
After this, you will want another script that reads the values and gives them the tools based on the bool value, e.g:(local)
local player = game.Players.LocalPlayer if player.Folder.HasM9.Value == true then local m9 = game.replicatedstorage.M9:Clone() m9.Parent = player.Backpack end
I hope you can edit the script I have provided, to help you with your problem, if it has helped, please remember to accept the answer! :)