I've made a coin collection system (there are coins around the map and players pick them up and get money). I want to make that when a player joins the game only the coins that he haven't taken yet will be created. I thought of using tables and every time the player takes the coin it adds the coin number to the table, and when it generates the coins it will remove the already taken coins. My question is if it's the right way of doing it and if it is how can I save tables on data store service and then get it from there?
Data store script:
--Save data server script. Parent - Workspace --Get services. local DSService = game:GetService('DataStoreService'):GetDataStore('asdsdafasdgsdfa') local Workspace = game:GetService('Workspace') local ReplicatedStorage = game:GetService('ReplicatedStorage') --Setup remote functions local startCollectedCoinsFunction = ReplicatedStorage:WaitForChild("StartCollectedCoinsFunction")--Holding the table of not taken coins, called when the player is local notTakenCoins = {} --joining the game in antoher script local endCollectedCoinsTable = Instance.new("RemoteFunction") --Holding the table of not taken coins, called when the player is leaving the game. endCollectedCoinsTable.Parent = ReplicatedStorage endCollectedCoinsTable.Name = "EndCollectedCoinsFunction" --Player added game.Players.PlayerAdded:connect(function(plr) local uniquekey = 'id-'..plr.userId -- Define cash variables local leaderstats = Instance.new('IntValue', plr) local cash = Instance.new('IntValue') leaderstats.Name = 'leaderstats' cash.Parent = leaderstats cash.Name = "Cash" cash.Value = 50 --Define coin variables local numberOfCoins = 5 for i = 1 , numberOfCoins do table.insert(notTakenCoins, i) --Inserts the number of coins to the table for a case that it's the first join of the player. end -- GetAsync local GetSaved = DSService:GetAsync(uniquekey) if GetSaved then cash.Value = GetSaved[1] notTakenCoins = GetSaved[2] else DSService:SetAsync(uniquekey, { cash.Value, notTakenCoins }) end --Send table local function SendTable()--Sends the table of the taken coins (from the data store service) to the local script that clones the coin return notTakenCoins end startCollectedCoinsFunction.OnServerInvoke = SendTable --Save data on player remove game.Players.PlayerRemoving:connect(function(plr) local uniquekey = 'id-'..plr.userId DSService:SetAsync(uniquekey, { plr.leaderstats.Cash.Value, endCollectedCoinsTable:InvokeClient(plr) --Sends request to the local script for the current not taken coin }) end) end)
Spawn coins script:
--Spawn coins local script. Parent - StartGui --Get Services local ReplicatedStorage = game:GetService('ReplicatedStorage') local Workspace = game:GetService('Workspace') local Players = game:GetService('Players') --Setup remote functions local endCollectedCoinsFunction = ReplicatedStorage:WaitForChild("EndCollectedCoinsFunction") local startCollectedCoinsFunction = ReplicatedStorage:WaitForChild("StartCollectedCoinsFunction") --Call for table --local notTakenCoins = startCollectedCoinsFunction:InvokeServer()--Requests the table of non taken coins fron the server script --Player Added local PlayerAddedEvent = ReplicatedStorage:WaitForChild('PlayerAddedEvent') --Creates the coins folder local flr = Instance.new("Folder", game.Workspace) flr.Name = "Coins" --Checks if the coinId is in the table local function CheckCoins(table, coinId) for i, value in pairs(table) do if value == coinId then return true end end return false end --Spawn the coins local function SpawnCoins(pos, num) --Call CheckCoins function if CheckCoins(startCollectedCoinsFunction:InvokeServer(), num) then --The coin will be spawned only if it is in the table --Define variables. local coin = game.ReplicatedStorage.Coin:Clone() local coinId = Instance.new("IntValue") coin.Parent = flr coin.Anchored = true coin.Name = "Coin"..num coinId.Parent = coin coinId.Name = "CoinId" coinId.Value = num --Change the coins position coin.Position = pos end end --Calls the spawn function with the position PlayerAddedEvent.OnClientEvent:Connect(function(plr) SpawnCoins(Vector3.new(-20.192,2.943,1.5),1) SpawnCoins(Vector3.new(-20.192,2.943,-5.5),2) SpawnCoins(Vector3.new(-20.192,2.943,-11.5),3) SpawnCoins(Vector3.new(-20.192,2.943,-17.5),4) SpawnCoins(Vector3.new(-20.192,2.943,-23.5),5) end) --Make a table of new not taken coins, called when the player is leaving the game. local newNotTakenCoins = {} local function AddCoinsToTable() for i,v in pairs(flr:GetChildren()) do table.insert(newNotTakenCoins, v.CoinId) end return newNotTakenCoins end endCollectedCoinsFunction.OnClientInvoke = AddCoinsToTable --Calls the function above
Since you did not include a script I will not write one for you. However there are a few tips I can give you to help you on your way. First: If I were you I would have all the coins in a single folder or model. Then create an IntValue inside of each coin which has the number you choose for labeling it. Whenever the player collects a coin remove it from that model/folder. Then when the time comes to save, loop through the folder/model with a for loop and something like: for i,v in pairs(coins:GetChildren()) do
then: table.insert(exampleTable, v.CoinId.Value)
or whatever you prefer. After doing all that save the table to the datastore via :SetAsync and then when the player rejoins get the data using :GetAsync. When the data has loaded loop through the table and the loop through the folder/model and check if a number in the datastore table matches the CoinId or whatever you call it. If it does then remove that coin from the folder/model. I hope this helps. If you have any additional questions you can comment below my answer and I will try to help. Have a great day scripting!