The StringValue is an achievement unlocked by the player.
The StringValue’s name is the name of the achievement.
The StringValue’s value is the description of the achievement.
But I don’t understand how I can save both the name and the value in a single DataStore. Can someone please help me implement it?
Here’s the ModuleScript I guess. It’s a bit long and MUST be required by the server:
local functions = {}
local dss = game:GetService("DataStoreService")
local da = dss:GetDataStore("PlayerAchievemtUnlockedStorage")
local remote = script.Parent:WaitForChild("AchievementsRemoteEvent")
function functions.LoadPlayerAchievements(plr:Player)
if not game:GetService("RunService"):IsServer() then return end
if plr.Parent == game.Players and not plr:FindFirstChild("ACHIEVEMENTS FOLDER") then
local plrData
local DataDescription
local success, err
while not success do
success, err = pcall(function()
plrData = da:GetAsync(plr.UserId) or {}
end)
if not success then
warn(err)
end
task.wait(0.5)
end
if success then
local newFolder = Instance.new("Folder")
newFolder.Name = "ACHIEVEMENTS FOLDER"
newFolder.Parent = plr
for _, achName in pairs(plrData) do -- this is where the name is gonna insert, but I also need the value
local newAchievementValue = Instance.new("StringValue")
newAchievementValue.Name = achName
newAchievementValue.Parent = newFolder
end
end
end
end
function functions.SavePlayerAchievements(plr:Player)
if not game:GetService("RunService"):IsServer() then return end
if plr.Parent == game.Players and plr:FindFirstChild("ACHIEVEMENTS FOLDER") then
local plrAchievements = {}
for _, achievementValue in pairs(plr["ACHIEVEMENTS FOLDER"]:GetChildren()) do
table.insert(plrAchievements, achievementValue.Name)
-- this is the part where it saves the name, but I dunno how to save the value with it too...
end
local success, err
while not success do
success, err = pcall(function()
return da:SetAsync(plr.UserId, plrAchievements)
end)
task.wait(0.1)
end
end
end
function functions.AwardAchievement(plr:Player, achName:string, Desc:string)
if not game:GetService("RunService"):IsServer() then return end
if plr.Parent == game.Players and plr:FindFirstChild("ACHIEVEMENTS FOLDER") and not plr["ACHIEVEMENTS FOLDER"]:FindFirstChild(achName) then
remote:FireClient(plr, "text", achName, Desc)
local newAchievementValue = Instance.new("StringValue")
newAchievementValue.Name = achName
newAchievementValue.Parent = plr["ACHIEVEMENTS FOLDER"]
newAchievementValue.Value = Desc
end
end
return functions
with this, you will be able to store both the name and the value of the achievement. When loading data, all you need is a for loop to get both the values
for achievementName,achievementValue in pairs(plrAchievements) do
--code
end
you can add things to a table in 2 ways. The first way is by using table.insert() and the second is by setting the key manually. when you use table.insert, the key gets set automatically. If I were to write down a table made with table.insert(), it would look something like this:
You notice how each item in the table is indexed by a number? Thats called a key. When you want to build something more complex, you can set the key directly so your table turns out like so:
local myTable = {
["Item1"] = "Description of item1",
["Item2"] = "Description of item2"
}
using item names as the key is probably not the best example, because there cant be 2 keys with the same name in one array. So for an inventory you would probably use table.insert(), however in your case, all achievement names should be different, thus not causing any problems. If you need any further clarification just let me know!
After implementing what you suggested, something is going wrong. I don’t know if it’s either loading or saving, but the unlocked achievements are gone on every join.
Sorry for the late response! It might be because of the loading. Try printing the saved data every time the data gets saved, and when the data gets loaded. If you have the datastore editor plugin, check if the data is being saved through that.
I used that, and yes, the data is being saved and loaded normally. I checked it with “print” and everything is there, but for some reason the achievements are still not applied in the “ACHIEVEMENTS FOLDER”. Can you please help troubleshoot this? Here’s the updated module.
local functions = {}
local dss = game:GetService("DataStoreService")
local da = dss:GetDataStore("PlayerAchievementsUnlockedStorageData")
local remote = script.Parent:WaitForChild("AchievementsRemoteEvent")
function functions.LoadPlayerAchievements(plr:Player)
if not game:GetService("RunService"):IsServer() then return end
if plr.Parent == game.Players and not plr:FindFirstChild("ACHIEVEMENTS FOLDER") then
local plrAchievement
local success, err
while not success do
success, err = pcall(function()
plrAchievement = da:GetAsync(plr.UserId) or {}
end)
if not success then
warn(err)
end
task.wait(0.5)
end
if success then
print(plrAchievement)
local newFolder = Instance.new("Folder")
newFolder.Name = "ACHIEVEMENTS FOLDER"
newFolder.Parent = plr
for achievementName, achievementValue in pairs(plrAchievement) do
local newAchievementValue = Instance.new("StringValue")
newAchievementValue.Name = achievementName
newAchievementValue.Value = achievementValue
end
end
end
end
function functions.SavePlayerAchievements(plr:Player)
if not game:GetService("RunService"):IsServer() then return end
if plr.Parent == game.Players and plr:FindFirstChild("ACHIEVEMENTS FOLDER") then
local plrAchievements = {}
for achievementName, achievementValue in pairs(plr["ACHIEVEMENTS FOLDER"]:GetChildren()) do
plrAchievements[achievementValue.Name] = achievementValue.Value
end
local success, err
while not success do
success, err = pcall(function()
print(plrAchievements)
return da:SetAsync(plr.UserId, plrAchievements)
end)
task.wait(0.1)
end
end
end
function functions.AwardAchievement(plr:Player, achName:string, Desc:string)
if not game:GetService("RunService"):IsServer() then return end
if plr.Parent == game.Players and plr:FindFirstChild("ACHIEVEMENTS FOLDER") and not plr["ACHIEVEMENTS FOLDER"]:FindFirstChild(achName) then
remote:FireClient(plr, "text", achName, Desc)
local newAchievementValue = Instance.new("StringValue")
newAchievementValue.Name = achName
newAchievementValue.Parent = plr["ACHIEVEMENTS FOLDER"]
newAchievementValue.Value = Desc
end
end
return functions