How would you go about making skills. And I don’t mean the actual skills, what I mean is how would you assign the skill to the player and also how would you save what skills the player has bought.
How would I store the skills that he owns and save the last one he equipped so when he gets back on the game he has the same skill equipped. Would that require 2 data stores?
The closest example that I could’ve think of is how Blade Ball handles skills (one skill equipped at a time).
The best way you could do this is by using a StringValue to control what skill the player has equipped, and then a folder of BoolValues to note what skills the player owns.
Then, save an array to the DataStore, something like:
local dataToSave = {
["EquippedSkill"] = player.EquippedSkill.Value,
["OwnedSkills"] = {
--array of skills the player owns, in strings (use the names)
}
}
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local SkillsDataStore = DataStoreService:GetDataStore("PlayerSkills")
local Skills = {
[1] = "Run",
[2] = "Jump"
}
local function savePlayerData(player)
local key = "Player_".. player.UserId
local dataToSave = {
EquippedSkill = player.Info.EquippedSkill,
OwnedSkills = player.Info.OwnedSkills
}
local success, error = pcall(function()
SkillsDataStore:SetAsync(key, dataToSave)
end)
end
local function loadPlayerData(player)
local key = "Player_".. player.UserId
local success, data = pcall(function()
return SkillsDataStore:GetAsync(key)
end)
if success and data then
player.Info.EquippedSkill = data.EquippedSkill
player.Info.OwnedSkills = data.OwnedSkills
else
local Info = Instance.new("Folder", player)
Info.Name = "Info"
local EquippedSkill = Instance.new("StringValue", Info)
EquippedSkill.Name = "EquippedSkill"
local OwnedSkills = Instance.new("Folder", Info)
OwnedSkills.Name = "OwnedSkills"
player.Info.EquippedSkill.Value = "None"
for i, v in Skills do
local BoolValue = Instance.new("BoolValue", OwnedSkills)
BoolValue.Name = Skills[i]
BoolValue.Value = false
end
savePlayerData(player)
end
end
Players.PlayerAdded:Connect(function(player)
loadPlayerData(player)
player.Changed:Connect(function(property)
if property == "EquippedSkill" or property == "OwnedSkills" then
savePlayerData(player)
end
end)
end)
Players.PlayerRemoving:Connect(function(player)
savePlayerData(player)
end)
No, it probably wouldn’t - I think you’re trying to save an instance value.
For the BoolValues folder, you want to have every skill in your game and have the value to true for ones the player owns.
So, when you save:
local ownedSkills = {}
for _, skill in ipairs(player.Info.OwnedSkills:GetChildren()) do
if skill.Value == true then
table.insert(ownedSkills, skill.Name)
end
end
local data = {
["EquippedSkill"] = player.Info.EquippedSkill.Value,
["OwnedSkills"] = ownedSkills
}
local success, result = pcall(function()
SkillsDataStore:UpdateAsync(key, function(old)
--UpdateAsync is better for helping to prevent data loss
--you can insert comparison code here as well btw
return data
end)
end)
You mean like this? Probably not, cuz the second time I enter the game I no longer have the folder.
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local SkillsDataStore = DataStoreService:GetDataStore("PlayerSkills")
local Skills = {
[1] = "Run",
[2] = "Jump"
}
local function savePlayerData(player)
local key = "Player_".. player.UserId
local ownedSkills = {}
for _, skill in ipairs(player.Info.OwnedSkills:GetChildren()) do
if skill.Value == true then
table.insert(ownedSkills, skill.Name)
end
end
local data = {
["EquippedSkill"] = player.Info.EquippedSkill.Value,
["OwnedSkills"] = ownedSkills
}
local success, result = pcall(function()
SkillsDataStore:UpdateAsync(key, function(old)
return data
end)
end)
end
local function loadPlayerData(player)
local key = "Player_".. player.UserId
local success, data = pcall(function()
return SkillsDataStore:GetAsync(key)
end)
if success and data then
player.Info.EquippedSkill.Value = data.EquippedSkill
for _, skillName in ipairs(data.OwnedSkills) do
local skillValue = player.Info.OwnedSkills[skillName]
if skillValue then
skillValue.Value = true
end
end
else
local Info = Instance.new("Folder", player)
Info.Name = "Info"
local EquippedSkill = Instance.new("StringValue", Info)
EquippedSkill.Name = "EquippedSkill"
local OwnedSkills = Instance.new("Folder", Info)
OwnedSkills.Name = "OwnedSkills"
player.Info.EquippedSkill.Value = "None"
for i, v in ipairs(Skills) do
local BoolValue = Instance.new("BoolValue", OwnedSkills)
BoolValue.Name = v
BoolValue.Value = false
end
savePlayerData(player)
end
end
Players.PlayerAdded:Connect(function(player)
loadPlayerData(player)
player.Changed:Connect(function(property)
if property == "EquippedSkill" or property == "OwnedSkills" then
savePlayerData(player)
end
end)
end)
Players.PlayerRemoving:Connect(function(player)
savePlayerData(player)
end)
No, the folder doesn’t save with the data - you cannot save an instance. You would still have to set up the folder and values, but then you can iterate over them and set whatever ones they have to true.