just skip to the bottom if you cant be bothered reading lol
I’m currently working on a shop in my game where players purchase items such as hats and hairs in-game. I’m trying to organize these and save them into a table. (which I think is probably the best way of doing it instead of sending like tones of data store reqs)
This is what the items look like:
each player gets this loaded into them containing bool values for all the items and an attribute called Equipped
which also saves. They are created by looping through the folder shown before and creating a new folder for the categories and a new value for the item. The value is checked if they own it and the equipped is checked when they equip it in the menu.
SAVING
Here is how I save the data, which runs on PlayerRemoved
(and BindToClose
). It loops through all the values in the Accesories folder in the player, checks if they are a value and not a category folder and then adds the value and equipped value to a table then that table is added to a bigger table.
function save(player) -- save player data
local folder = player:FindFirstChild("Accessories")
local save = {}
for index, value in pairs(folder:GetDescendants()) do -- loop through values
if value:IsA("ValueBase") then
local tbl = {} -- load data into table
tbl.Value = value.Value
tbl.Equipped = value:GetAttribute("Equipped") or false
table.insert(save, #save + 1, tbl) -- load table into main save table
end
end
print(save)
local success, err = pcall(function()
dataStore:SetAsync(player.UserId, save) -- save table to datastore
end)
end
That save table will end up looking something like this with all the values:
▼ { -- main table (called Save(
[1] = ▼ { -- one table for each item
["Equipped"] = false, -- if item is equipped
["Value"] = false -- owned
},
[2] = ▶ {...},
[3] = ▶ {...} -- so 3 items in total
-- etc etc...
LOADING
When the player loads into the game, this is what happens, and this is where I think the problem occurs. Ready carefully.
players.PlayerAdded:Connect(function(player)
local folder = Instance.new("Folder") -- make folder for the categories
folder.Name = "Accessories"
folder.Parent = player
-- create values
for _, category in pairs(shopItems:GetChildren()) do -- loop through that folder wt the items
local categoryFolder = Instance.new("Folder") -- create a folder for that category inside the player
categoryFolder.Name = category.Name
for index, val in pairs(category:GetChildren()) do -- get all items inside category
local value = Instance.new("BoolValue") -- create value for each item and parent inside of created category folder
value:SetAttribute("Equipped", false)
value.Name = val.Name
value.Parent = categoryFolder
end
categoryFolder.Parent = folder -- parent each category folder into the main accessories folder
end
-- load data
local stats = dataStore:GetAsync(player.UserId) -- get data from datastore
print(stats)
for index, value in pairs(folder:GetDescendants()) do -- load through accessories folder
if not value:IsA("ValueBase") then continue end -- check if it is not a category folder
-- keep in mind, stats[index] is a table shown before containing 2 values, Value and Equipped.
if stats ~= nil and stats[index] ~= nil then -- if the player has data for that index (that is the number of the iteration)
value.Value = stats[index].Value or false -- set the value to the saved data value
value:SetAttribute("Equipped", stats[index].Equipped) -- do the same for equipped value
print("Set value "..value.Name.." to "..tostring(stats[index].Value).." "..tostring(stats[index].Equipped))
else
value.Value = false
value:SetAttribute("Equipped", false) -- if they have no data set to the defaults false and false
print("Set value "..value.Name.." to false false")
end
end
end)
THE PROBLEM
I think is with the for loop. It loops through all of the descendants of this folder called Accessories as shown before.
But it skips the folder meaning it goes up one more index thing because its checking if it is not a folder.
if not value:IsA("ValueBase") then continue end -- check if it is not a category folder
This makes all of the index number the wrong number aswell because in the saving system, it puts the values into a table and the index for those are 1, 2, 3 etc but for this the index 1 or 2 or 3 could be a folder so it skips it. Meaning that the index could be 4 even though in the table it is actually 3 but the folder caused it to skip 1.
I don’t think its just the folders causing the problem though it could be because of different values being in different folders.
For example, lets set HairTest
and HatTest
to true, everything else is false!
Now lets rejoin and you can see now this table here which is the same as the image above with the folders and boolvalues just in a table, prints all the data correctly.
But this prints the index and what it set the values to.
It prints the value and then the equipped value but lets just worry about the value atm.
On the first line it prints 2 because 1 would have been one of the folders so the loop skipped it, and in the table it says that the data for 2 is false, so it sets it to false. Even though it should be true according to the table above, but because it skipped that folder, the index is 2.
Same with the 4, it should be true but was set to 3 which is false, because again it skipped 1 because of the category folder.
And no I cant really just do index = index - 1
because in other cases there could be 2 skipped folders in a row or something etc it wouldn’t work.
In other cases I have tried changing other values and it set the wrong values for the wrong thing. Bassically I’m trying to figure out how to get the right item from the table. And I’ve tried using names for it but if I change the name or if two things have the same name the data is lost.
TLDR
Data not saving to correct values because the loop skips the folder, just read it lol.
Thanks. Comment for anymore info.