Hey! Im making an RNG game and followed an in depth tutorial. Although this tutorial was so “in-depth” they didn’t include inventory saving. So, as a not-so-great scripter, i would like to get some help on this.
I found the PlayerData was being stored in a folder, “PlayerDataFolder” in the Equip Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local EquipEffectEvent = ReplicatedStorage:WaitForChild("EquipEffect")
local GlobalData = ServerStorage:WaitForChild("PlayerData")
local Effects = ServerStorage:WaitForChild("Auras")
-- Define the unequip function
local function delete(player, selectedEffect, CurrentlyEquippedFolder)
local head = player.Character:FindFirstChild("Head")
local torso = player.Character:FindFirstChild("Torso")
if head and torso and selectedEffect then
for i, v in pairs(head:GetChildren()) do
if v.Name == selectedEffect then
v:Destroy()
break
end
end
for i, v in pairs(torso:GetChildren()) do
if v.Name == selectedEffect then
v:Destroy()
break
end
end
CurrentlyEquippedFolder:GetChildren()[1]:Destroy()
end
end
-- Define the equip function
local function equip(player, selectedEffect, CurrentlyEquippedFolder)
local effect = Effects:WaitForChild(selectedEffect)
local title = effect:WaitForChild("Head"):WaitForChild(selectedEffect):Clone()
local particles = effect:WaitForChild("Torso"):WaitForChild(selectedEffect):Clone()
local character = player.Character or player.CharacterAdded:Wait()
title.Parent = character.Head
particles.Parent = character.Torso
local stringVal = Instance.new("StringValue")
stringVal.Name = selectedEffect
stringVal.Parent = CurrentlyEquippedFolder
end
-- Define the main equipEffect function
local function equipEffect(player, operationType, selectedEffect)
local PlayerDataFolder = GlobalData:WaitForChild(player.UserId)
local InventoryFolder = PlayerDataFolder:WaitForChild("Inventory")
local CurrentlyEquippedFolder = PlayerDataFolder:WaitForChild("CurrentlyEquipped")
if operationType == "Equip" and selectedEffect then
if InventoryFolder:FindFirstChild(selectedEffect) then
if #CurrentlyEquippedFolder:GetChildren() ~= 0 and CurrentlyEquippedFolder:GetChildren()[1].Name ~= selectedEffect then
delete(player, CurrentlyEquippedFolder:GetChildren()[1].Name, CurrentlyEquippedFolder)
end
if #CurrentlyEquippedFolder:GetChildren() == 0 or CurrentlyEquippedFolder:GetChildren()[1].Name ~= selectedEffect then
equip(player, selectedEffect, CurrentlyEquippedFolder)
end
end
elseif operationType == "delete" and selectedEffect and CurrentlyEquippedFolder:FindFirstChild(selectedEffect) then
delete(player, selectedEffect, CurrentlyEquippedFolder)
end
end
-- Connect equipEffect function to the event
EquipEffectEvent.OnServerEvent:Connect(equipEffect)
Although its in the script, i cant figure out a way to save the auras! Any help would be appreciated! Thank you so much and if you need any more information im here.
You’ll need to leverage DataStoreService to store and retrieve the player’s inventory and equipped items when they join and leave the game.
Initialize the DataStore: Create a DataStore to save the player’s inventory and currently equipped items.
Load Data on Player Join: Retrieve and set up the player’s inventory and equipped items from the DataStore when they join the game.
Save Data on Player Leave: Save the player’s inventory and equipped items to the DataStore when they leave the game.
You might need to mess around with the code, but this is a basic implementation.
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local PlayerDataStore = DataStoreService:GetDataStore("PlayerData")
local ServerStorage = game:GetService("ServerStorage")
local EquipEffectEvent = game:GetService("ReplicatedStorage"):WaitForChild("EquipEffect")
local GlobalData = ServerStorage:WaitForChild("PlayerData")
local Effects = ServerStorage:WaitForChild("Auras")
-- Function to load player data
local function loadPlayerData(player)
local playerFolder = Instance.new("Folder")
playerFolder.Name = player.UserId
playerFolder.Parent = GlobalData
local inventoryFolder = Instance.new("Folder")
inventoryFolder.Name = "Inventory"
inventoryFolder.Parent = playerFolder
local equippedFolder = Instance.new("Folder")
equippedFolder.Name = "CurrentlyEquipped"
equippedFolder.Parent = playerFolder
local success, data = pcall(function()
return PlayerDataStore:GetAsync(player.UserId)
end)
if success and data then
-- Load inventory
for _, itemName in ipairs(data.Inventory or {}) do
local item = Instance.new("StringValue")
item.Name = itemName
item.Parent = inventoryFolder
end
-- Load currently equipped items
for _, equippedItem in ipairs(data.CurrentlyEquipped or {}) do
local item = Instance.new("StringValue")
item.Name = equippedItem
item.Parent = equippedFolder
end
-- Equip the currently equipped items
for _, item in pairs(equippedFolder:GetChildren()) do
equip(player, item.Name, equippedFolder)
end
end
end
-- Function to save player data
local function savePlayerData(player)
local playerFolder = GlobalData:FindFirstChild(player.UserId)
if playerFolder then
local inventory = {}
local currentlyEquipped = {}
for _, item in pairs(playerFolder.Inventory:GetChildren()) do
table.insert(inventory, item.Name)
end
for _, item in pairs(playerFolder.CurrentlyEquipped:GetChildren()) do
table.insert(currentlyEquipped, item.Name)
end
local data = {
Inventory = inventory,
CurrentlyEquipped = currentlyEquipped
}
pcall(function()
PlayerDataStore:SetAsync(player.UserId, data)
end)
end
end
-- Equip and unequip functions
local function delete(player, selectedEffect, CurrentlyEquippedFolder)
local head = player.Character:FindFirstChild("Head")
local torso = player.Character:FindFirstChild("Torso")
if head and torso and selectedEffect then
for _, v in pairs(head:GetChildren()) do
if v.Name == selectedEffect then
v:Destroy()
break
end
end
for _, v in pairs(torso:GetChildren()) do
if v.Name == selectedEffect then
v:Destroy()
break
end
end
CurrentlyEquippedFolder:GetChildren()[1]:Destroy()
end
end
local function equip(player, selectedEffect, CurrentlyEquippedFolder)
local effect = Effects:WaitForChild(selectedEffect)
local title = effect:WaitForChild("Head"):WaitForChild(selectedEffect):Clone()
local particles = effect:WaitForChild("Torso"):WaitForChild(selectedEffect):Clone()
local character = player.Character or player.CharacterAdded:Wait()
title.Parent = character.Head
particles.Parent = character.Torso
local stringVal = Instance.new("StringValue")
stringVal.Name = selectedEffect
stringVal.Parent = CurrentlyEquippedFolder
end
-- Main equipEffect function
local function equipEffect(player, operationType, selectedEffect)
local PlayerDataFolder = GlobalData:WaitForChild(player.UserId)
local InventoryFolder = PlayerDataFolder:WaitForChild("Inventory")
local CurrentlyEquippedFolder = PlayerDataFolder:WaitForChild("CurrentlyEquipped")
if operationType == "Equip" and selectedEffect then
if InventoryFolder:FindFirstChild(selectedEffect) then
if #CurrentlyEquippedFolder:GetChildren() ~= 0 and CurrentlyEquippedFolder:GetChildren()[1].Name ~= selectedEffect then
delete(player, CurrentlyEquippedFolder:GetChildren()[1].Name, CurrentlyEquippedFolder)
end
if #CurrentlyEquippedFolder:GetChildren() == 0 or CurrentlyEquippedFolder:GetChildren()[1].Name ~= selectedEffect then
equip(player, selectedEffect, CurrentlyEquippedFolder)
end
end
elseif operationType == "delete" and selectedEffect and CurrentlyEquippedFolder:FindFirstChild(selectedEffect) then
delete(player, selectedEffect, CurrentlyEquippedFolder)
end
end
-- Connect equipEffect function to the event
EquipEffectEvent.OnServerEvent:Connect(equipEffect)
-- Load data when player joins
Players.PlayerAdded:Connect(function(player)
loadPlayerData(player)
end)
-- Save data when player leaves
Players.PlayerRemoving:Connect(function(player)
savePlayerData(player)
end)
I’ve been playing around with it and im not sure what “equip” is supposed to be. Is it supposed to call for a remoteEvent?
equip(player, item.Name, equippedFolder)
It always says “Unknown global “equip”” which i know means that its not able to find the right thing and the error is:
ServerScriptService.Equip:45: attempt to call a nil value - Server - Equip:45
20:07:22.730 Stack Begin - Studio
20:07:22.730 Script 'ServerScriptService.Equip', Line 45 - function loadPlayerData - Studio - Equip:45
20:07:22.731 Script 'ServerScriptService.Equip', Line 140 - Studio - Equip:140
20:07:22.731 Stack End - Studio
and thank you for your help so far, i finally got somewhere in this topic because of you, its just not quite done yet. @JamesBlossoms
Try inserting print statements throughout the code to pinpoint where it’s stalling. Start with the playeradded and playerremoving events and their respective functions to see what’s going on.
local DataStoreService = game:GetService("DataStoreService")
local mainDS = DataStoreService:GetDataStore("Rolls")
local function loadPlayerData(player)
print("Loading data for player: " .. player.Name)
local leaderstats = Instance.new("Folder", player)
leaderstats.Name = "leaderstats"
local Rolls = Instance.new("IntValue", leaderstats)
Rolls.Name = "Rolls"
local success, data = pcall(function()
return mainDS:GetAsync(player.UserId)
end)
if success then
if data then
Rolls.Value = data[1]
print("Data loaded successfully for player " .. player.Name .. ". Rolls: " .. Rolls.Value)
else
Rolls.Value = 0 -- Default value if no data is found
print("No data found for player " .. player.Name .. ". Setting Rolls to default: 0")
end
else
warn("Failed to load data for player " .. player.Name)
Rolls.Value = 0 -- Default value if loading fails
end
end
local function savePlayerData(player)
print("Saving data for player: " .. player.Name)
local leaderstats = player:FindFirstChild("leaderstats")
if leaderstats then
local Rolls = leaderstats:FindFirstChild("Rolls")
if Rolls then
local success, err = pcall(function()
mainDS:SetAsync(player.UserId, { Rolls.Value })
end)
if success then
print("Data saved successfully for player " .. player.Name .. ". Rolls: " .. Rolls.Value)
else
warn("Failed to save data for player " .. player.Name .. ": " .. err)
end
else
warn("Rolls not found for player " .. player.Name)
end
else
warn("Leaderstats not found for player " .. player.Name)
end
end
-- Connect player events
game.Players.PlayerAdded:Connect(loadPlayerData)
game.Players.PlayerRemoving:Connect(savePlayerData)
-- Throttled saving mechanism
local savingEnabled = true
local saveQueue = {}
local function processSaveQueue()
savingEnabled = false
for _, player in ipairs(saveQueue) do
savePlayerData(player)
end
saveQueue = {}
savingEnabled = true
end
local function addToSaveQueue(player)
if savingEnabled then
savePlayerData(player)
else
table.insert(saveQueue, player)
end
end
while true do
wait(30) -- Adjust the interval as per your needs
processSaveQueue()
end
If you need the equip script which we’ve been working on in this forum i can provide that for you, too!
Can I see the code that does this? I don’t understand why more are being created every time you rejoin. From what I see all that’s being saved is the Rolls which is a number.
local RS = game:GetService("ReplicatedStorage")
local updateInventoryEvent = RS:WaitForChild("UpdateInventory")
local ScrollingFrame = script.Parent.ScrollingFrame
local EffectTitles = ScrollingFrame:WaitForChild("EffectTitles")
local function addItem(effect)
local clonedTitle = EffectTitles:WaitForChild(effect):Clone()
clonedTitle.Parent = ScrollingFrame
clonedTitle.Visible = true
end
updateInventoryEvent.OnClientEvent:Connect(addItem)
So basically i have a button for each aura in the inventory but its invisible and in the startergui. when the player obtains an aura, i clone the button from the inventory in the startergui and put it in the playergui and make it visible and so on.