Is there a way to stop the saved items from an inventory saving script to be treated as seperate ones in a loadout system?

I want to make a loadout system, however the inventory saving script I have doesn’t work as intended, for example, if I buy a primary, then leave, and then rejoin to replace that primary, the previous primary does not get replaced and there’s just 2 primaries now due to the saved one being treated as a seperate item : (

Here’s a screenshot to see what I mean:

image

Here’s my data saving script:

local DataStoreService = game:GetService("DataStoreService")
local conf = game.ReplicatedStorage:WaitForChild("Configuration")
local currencyName = conf:WaitForChild("CurrencyName")
local startingCurrency = conf:WaitForChild("StartingCurrency")
local dsKey = conf:WaitForChild("DatastoreKey")

local datastore = DataStoreService:GetDataStore(dsKey.Value)

local CreateLeaderstats = require(game.ServerScriptService.ShopServer.ModuleScripts.CreateLeaderstats)

-- Function to save player data
local function SaveData(player)
	if not player then
		return
	end

	local plrKey = player.UserId
	local plrCash = player:FindFirstChild("leaderstats") and player.leaderstats[currencyName.Value].Value or 0

	-- Collect player's tools data
	local tools = {}
	local function collectToolsFromContainer(container)
		for _, tool in ipairs(container:GetChildren()) do
			if tool:IsA("Tool") then
				tools[tool.Name] = true -- Use a table to ensure uniqueness
			end
		end
	end

	collectToolsFromContainer(player.Backpack)
	if player.Character then
		collectToolsFromContainer(player.Character)
	end

	local ownedTools = player:FindFirstChild("OwnedTools")
	if ownedTools then
		for _, tool in ipairs(ownedTools:GetChildren()) do
			tools[tool.Name] = true
		end
	end

	local toolsList = {}
	for toolName, _ in pairs(tools) do
		table.insert(toolsList, toolName)
	end

	local plrData = { Cash = plrCash, Tools = toolsList }

	local success, err = pcall(function()
		datastore:SetAsync(plrKey, plrData)
	end)

	if not success then
		warn("Error saving " .. player.Name .. "'s (" .. plrKey .. ") data:\n" .. err)
	else
		print("Data saved successfully for player:", player.Name)
	end
end

-- Function to load player data
local function LoadData(player)
	if not player then
		return
	end

	local plrKey = player.UserId

	local dataFailedWarning = Instance.new("BoolValue")
	dataFailedWarning.Name = "DataLoadFailed"
	dataFailedWarning.Value = true
	dataFailedWarning.Parent = player

	local success, plrData = pcall(function()
		return datastore:GetAsync(plrKey)
	end)

	if success and plrData then
		if not player:FindFirstChild("leaderstats") then
			CreateLeaderstats(player, plrData.Cash or startingCurrency.Value)
		end

		-- Create the OwnedTools folder if it doesn't exist
		local ownedTools = player:FindFirstChild("OwnedTools")
		if not ownedTools then
			ownedTools = Instance.new("Folder")
			ownedTools.Name = "OwnedTools"
			ownedTools.Parent = player
		end

		-- Give the player their saved tools
		local backpack = player:WaitForChild("Backpack")
		local toolNames = {}
		for _, toolName in ipairs(plrData.Tools or {}) do
			if not toolNames[toolName] then
				toolNames[toolName] = true

				local tool = nil
				-- Search in the ReplicatedStorage folders
				for _, folder in ipairs({"Coins", "Tools", "Gamepass"}) do
					local folderRef = game.ReplicatedStorage:FindFirstChild(folder)
					if folderRef then
						tool = folderRef:FindFirstChild(toolName)
						if tool then break end
					end
				end

				if tool then
					-- Add tool to OwnedTools folder
					local ownedTool = tool:Clone()
					ownedTool.Parent = ownedTools

					-- Ensure only one instance of each tool in Backpack
					local existingTool = backpack:FindFirstChild(toolName)
					if existingTool then
						existingTool:Destroy()
					end

					-- Clone tool to backpack
					tool:Clone().Parent = backpack
				end
			end
		end

		dataFailedWarning.Value = false
	else
		warn("Error loading " .. player.Name .. "'s (" .. plrKey .. ") data.")
	end

	dataFailedWarning:Destroy()
end

-- Create OwnedTools folder for the player
game.Players.PlayerAdded:Connect(function(player)
	local ownedTools = Instance.new("Folder")
	ownedTools.Name = "OwnedTools"
	ownedTools.Parent = player

	player.CharacterAdded:Connect(function()
		LoadData(player)
	end)
end)

-- Connect function to player leaving event
game.Players.PlayerRemoving:Connect(function(player)
	SaveData(player)
end)

-- Bind to close function to save data for all players
game:BindToClose(function()
	for _, player in ipairs(game.Players:GetPlayers()) do
		SaveData(player)
	end
end)

You should look for old primary item and delete it, then add new primary item

1 Like

You can make it as you want, in datastoreservice or anything else

1 Like

If thats solved your problem then mark it’s as “Solved” otherwise i tryed.

I am currently trying to fix some bugs to see if it will work , , ,

Didn’t seem to work,

image

Maybe I did something wrong?

local DataStoreService = game:GetService("DataStoreService")
local conf = game.ReplicatedStorage:WaitForChild("Configuration")
local currencyName = conf:WaitForChild("CurrencyName")
local startingCurrency = conf:WaitForChild("StartingCurrency")
local dsKey = conf:WaitForChild("DatastoreKey")

local datastore = DataStoreService:GetDataStore(dsKey.Value)

local CreateLeaderstats = require(game.ServerScriptService.ShopServer.ModuleScripts.CreateLeaderstats)

-- Function to save player data
local function SaveData(player)
	if not player then
		return
	end

	local plrKey = player.UserId
	local plrCash = player:FindFirstChild("leaderstats") and player.leaderstats[currencyName.Value].Value or 0

	-- Collect player's tools data
	local tools = {}
	local function collectToolsFromContainer(container)
		for _, tool in ipairs(container:GetChildren()) do
			if tool:IsA("Tool") then
				tools[tool.Name] = true -- Use a table to ensure uniqueness
			end
		end
	end

	collectToolsFromContainer(player.Backpack)
	if player.Character then
		collectToolsFromContainer(player.Character)
	end

	local ownedTools = player:FindFirstChild("OwnedTools")
	if ownedTools then
		for _, tool in ipairs(ownedTools:GetChildren()) do
			tools[tool.Name] = true
		end
	end

	local toolsList = {}
	for toolName, _ in pairs(tools) do
		table.insert(toolsList, toolName)
	end

	local plrData = { Cash = plrCash, Tools = toolsList }

	local success, err = pcall(function()
		datastore:SetAsync(plrKey, plrData)
	end)

	if not success then
		warn("Error saving " .. player.Name .. "'s (" .. plrKey .. ") data:\n" .. err)
	else
		print("Data saved successfully for player:", player.Name)
	end
end

-- Function to load player data
local function LoadData(player)
	if not player then
		return
	end

	local plrKey = player.UserId

	local dataFailedWarning = Instance.new("BoolValue")
	dataFailedWarning.Name = "DataLoadFailed"
	dataFailedWarning.Value = true
	dataFailedWarning.Parent = player

	local success, plrData = pcall(function()
		return datastore:GetAsync(plrKey)
	end)

	if success and plrData then
		if not player:FindFirstChild("leaderstats") then
			CreateLeaderstats(player, plrData.Cash or startingCurrency.Value)
		end

		-- Create the OwnedTools folder if it doesn't exist
		local ownedTools = player:FindFirstChild("OwnedTools")
		if not ownedTools then
			ownedTools = Instance.new("Folder")
			ownedTools.Name = "OwnedTools"
			ownedTools.Parent = player
		end

		-- Clear existing tools in Backpack and OwnedTools folder before loading saved tools
		player.Backpack:ClearAllChildren()
		ownedTools:ClearAllChildren()

		-- Give the player their saved tools
		local backpack = player:WaitForChild("Backpack")
		local toolNames = {}
		for _, toolName in ipairs(plrData.Tools or {}) do
			if not toolNames[toolName] then
				toolNames[toolName] = true

				local tool = nil
				-- Search in the ReplicatedStorage folders
				for _, folder in ipairs({"Coins", "Tools", "Gamepass"}) do
					local folderRef = game.ReplicatedStorage:FindFirstChild(folder)
					if folderRef then
						tool = folderRef:FindFirstChild(toolName)
						if tool then break end
					end
				end

				if tool then
					-- Add tool to OwnedTools folder
					local ownedTool = tool:Clone()
					ownedTool.Parent = ownedTools

					-- Ensure only one instance of each tool in Backpack
					local existingTool = backpack:FindFirstChild(toolName)
					if existingTool then
						existingTool:Destroy()
					end

					-- Clone tool to backpack
					tool:Clone().Parent = backpack
				end
			end
		end

		dataFailedWarning.Value = false
	else
		warn("Error loading " .. player.Name .. "'s (" .. plrKey .. ") data.")
	end

	dataFailedWarning:Destroy()
end

-- Function to replace old primary tool with new one
local function ReplacePrimaryTool(player, newToolName)
	local backpack = player:WaitForChild("Backpack")
	local oldPrimaryTool = backpack:FindFirstChildWhichIsA("Tool")

	-- Remove old primary tool if it exists
	if oldPrimaryTool then
		oldPrimaryTool:Destroy()
	end

	-- Add new primary tool
	local tool = nil
	for _, folder in ipairs({"Coins", "Tools", "Gamepass"}) do
		local folderRef = game.ReplicatedStorage:FindFirstChild(folder)
		if folderRef then
			tool = folderRef:FindFirstChild(newToolName)
			if tool then break end
		end
	end

	if tool then
		local newTool = tool:Clone()
		newTool.Parent = backpack
	end
end

-- Create OwnedTools folder for the player
game.Players.PlayerAdded:Connect(function(player)
	local ownedTools = Instance.new("Folder")
	ownedTools.Name = "OwnedTools"
	ownedTools.Parent = player

	player.CharacterAdded:Connect(function()
		LoadData(player)
	end)
end)

-- Connect function to player leaving event
game.Players.PlayerRemoving:Connect(function(player)
	SaveData(player)
end)

-- Bind to close function to save data for all players
game:BindToClose(function()
	for _, player in ipairs(game.Players:GetPlayers()) do
		SaveData(player)
	end
end)

Sorry, I am not good at coding.

1 Like

I think you should first Set playerlist to empty table then to toolsList like:

local plrData = { Cash = plrCash, Tools = {} }
local success2, err2 = pcall(function()
	datastore:SetAsync(plrKey, plrData)
end)
plrData = { Cash = plrCash, Tools = toolsList }
local success, err = pcall(function()
	datastore:SetAsync(plrKey, plrData)
end)
1 Like

So it should overwrite data with empty table then it will set the new value

1 Like

also make sure that you dont have anything in starterPack

1 Like

Im not very good at DataStoreServices and i very rarery use it

I put the code like this, right?

image

yeap, and make sure to make 2rd check if that was success

1 Like

It didn’t seem to work : ( Is there any other method possible to save items and that not happening?

There is defenetlly another method, but sorry i cant really help you with that one, maybe it’s caused by other script because i have no idea why its saving old primary tool, also you tried to remove old primary tool then saving?

1 Like

Can you please check if you removed old primary tool before saving and reply me.

1 Like

I think I did try that, but it didn’t work

You did that locally or on server side?

I did locally on accident :skull: woops

Lemme try it again

Update: the bug still persists.

Welp, im tryed. Good luck developing your game and fixing ur bugs, Data saving is not my, if you need help with other game aspects i can help you.

1 Like