How to change this script into having two currencies?

Hey there! To keep it brief, I have this script where it supports a trail shop system. However, the script that I’m using to save two currencies isn’t working… Could anyone convert this into where it saves, and then tell me what I did wrong? I’d really appreciate it.

local StatsName = "Gold" 
local StartingAmt = 1000

local DataStoreService = game:GetService("DataStoreService")
local RunService = game:GetService("RunService")
local PlayersService = game:GetService("Players")

local statsStore = DataStoreService:GetDataStore("-stats")
local StatsName1 = "Voids" 
local StartingAmt = 0 

local DataStoreService = game:GetService("DataStoreService")
local RunService = game:GetService("RunService")
local PlayersService = game:GetService("Players")

local statsStore = DataStoreService:GetDataStore("-stats")

---------------------

game.Players.PlayerAdded:Connect(function(Player)
	local leaderFolder = Instance.new("Folder")
	leaderFolder.Name = "leaderstats"
	leaderFolder.Parent = Player
	
	local statsValue = Instance.new("NumberValue")
	statsValue.Value = StartingAmt
	statsValue.Name = StatsName
	statsValue.Parent = leaderFolder
	
	local statsValue = Instance.new("NumberValue")
	statsValue.Value = StartingAmt
	statsValue.Name = StatsName1
	statsValue.Parent = leaderFolder
	
	local lastEquipped = Instance.new("StringValue")
	lastEquipped.Value = "nil"
	lastEquipped.Parent = Player
	lastEquipped.Name = "equippedTrail"
	
	local oldData
	local foundData,newplr = pcall(function()
		oldData = statsStore:GetAsync(Player.UserId)
	end)
	if foundData and oldData ~= nil then
		statsValue.Value = oldData.Stat
		lastEquipped.Value = oldData.equip
	end
end)

game.Players.PlayerRemoving:Connect(function(Player)
	local succesSaved,ErrorSaved = pcall(function()
		statsStore:SetAsync(Player.UserId,{
			Stat = Player.leaderstats:FindFirstChild(StatsName).Value,
			equip = Player.equippedTrail.Value,
		})
	end)
end)

game:BindToClose(function()
	if RunService:IsStudio() then
		wait(1)
	else
		for _, Player in pairs(PlayersService) do
			local succesSaved,ErrorSaved = pcall(function()
				statsStore:SetAsync(Player.UserId,{
					Stat = Player.leaderstats:FindFirstChild(StatsName).Value,
					equip = Player.equippedTrail.Value
				})
			end)
		end
	end
end)

Try this code.


-- 2 Variables to be stored and 1 not.

GoldName = "Gold"
GoldAnt = 1000

VoidName = "Voids"
VoidAnt = 0

EquippedTrial = "equippedTrail"
EquippedTrailAnt = nil

local DataStoreService = game:GetService("DataStoreService")
local statsStore = DataStoreService:GetDataStore("-stats")
local PlayersService = game:GetService("Players")

function saveStats(Player)
	local leaderFolder = Instance.new("Folder", Player)
	leaderFolder.Name = "leaderstats"
	
    -- 2 Variables to be stored
	local statsValue1 = Instance.new("NumberValue", leaderFolder) -- Use this 
    "NumberValue" , leaderFolder instead of .Parent, to make the code more stable
    statsValue1.Value = GoldName

	local statsValue2 = Instance.new("NumberValue", leaderFolder)
    statsValue2.Name = VoidName

	local lastEquipped = Instance.new("StringValue",Player)
	lastEquipped.Name = EquippedTrail
	lastEquipped.Value = EquippedTrailAnt

    local prlKey= "Player_" .. Player.UserId
	local oldData
	local foundData,newplr = pcall(function()
		oldData = statsStore:GetAsync(PlrKey)
	end)
	if foundData and oldData ~= nil then
		statsValue1.Value = foundData[1]
		statsValue2.Value = foundData[2]
        print("Data loaded for: " ..Player.Name)
        else
        statsValue1.Value = GoldAnt
        statsValue2.Value = VoidAnt
        print("New data for: " ..Player.Name)
	end
end

PlayerService.PlayerAdded:Connect(function(Player)
local succesLoaded,ErrorLoaded = pcall(function()
saveStats(Player)
end)
if succesLoaded then
print("Data loaded for: " ..Player.Name)
else
print("Data not loaded: " ..Player.Name)
end
end)

game.Players.PlayerRemoving:Connect(function(Player)
    local leaderstats = Player.leaderstats
    local prlKey= "Player_" .. Player.UserId
    local valueToSave = {
    leaderstats.Gold;
    leaderstats.Voids;
    }
	local succesSaved,ErrorSaved = pcall(function()
		statsStore:SetAsync(plrKey,valueToSave)
	end)
if succesSaved then
print("Data saved! for: "..Player.Name)
else
print("Data not saved! for: "..Player.Name)
end
end)

game:BindToClose(function()
for _, v in pairs(PlayersService:GetChildren()) do
local succesSaved,ErrorSaved = pcall(function()
saveStats(v)
end)
if succesSaved then
print("Data saved for:".. v.Name)
else
print("Data not saved for:".. v.Name)
end
end
end)

Thanks! But now, the code for equipping the trail doesn’t work… This is a separate code entirely within the folder, so now I’m kinda stumped. Any ideas on what you can do, or should I make a brand new thread? Thanks in advance.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local REEvent = ReplicatedStorage:FindFirstChild("trailShopRE")

REEvent.OnServerEvent:Connect(function(Player,TrailName,TrailColour,state)
	if state == "equip" and Player.Character then

		local success,errormsg = pcall(function()
			local HRP = Player.Character.HumanoidRootPart
			
			for i, oldTrail in pairs(HRP:GetChildren()) do
				if oldTrail:IsA('Trail') or oldTrail.Name == "trailAttachment" then
					oldTrail:Destroy()
				end
			end
			
			for i, oldTrail in pairs(Player.Character.Head:GetChildren()) do
				if oldTrail:IsA('Trail') or oldTrail.Name == "trailAttachment" then
					oldTrail:Destroy()
				end
			end
			
		--	local r, g, b = R, G, B
		--	local strOne = string.format("%0.f", r*255)
		--	local strTwo = string.format("%0.f", g*255)
		--	local strThree = string.format("%0.f", b*255)
			
		--	print(strOne .. " " .. strTwo .. " " .. strThree) 
		--	local Finalcolour = Color3.new(strOne,strTwo,strThree)
			
			local newTrail = Instance.new("Trail")
			newTrail.Name = TrailName
			newTrail.Color = TrailColour
			newTrail.Parent = HRP
			newTrail.MaxLength = 10
			
			local attachmentOne = Instance.new("Attachment")
			attachmentOne.Name = "trailAttachment"
			attachmentOne.Parent = HRP
			
			local attachmentTwo = Instance.new("Attachment")
			attachmentTwo.Name = "trailAttachment"
			attachmentTwo.Parent = Player.Character.Head
			
			newTrail.Attachment0 = attachmentOne
			newTrail.Attachment1 = attachmentTwo
			
			Player.equippedTrail.Value = TrailName
		end)
		if not success then
			warn(errormsg)
		end
	end
end)

REEvent.OnServerEvent:Connect(function(Player,TrailName,state)
	if state == 'unequip' then
		if Player.Character then
			local unequipped,stillEquipped = pcall(function()
				local HRP = Player.Character.HumanoidRootPart
				
				for i, oldTrail in pairs(HRP:GetChildren()) do
					if oldTrail:IsA('Trail') or oldTrail.Name == "trailAttachment" then
						oldTrail:Destroy()
					end
				end

				for i, oldTrail in pairs(Player.Character.Head:GetChildren()) do
					if oldTrail:IsA('Trail') or oldTrail.Name == "trailAttachment" then
						oldTrail:Destroy()
					end
				end
				
				Player.equippedTrail.Value = "nil"
			end)
			if not unequipped then
				warn(stillEquipped)
			end
		end
	end
end)

REEvent.OnServerEvent:Connect(function(Player,Price,TrailName,state)
	if state == "purchase" then
		local check,errored = pcall(function()
			if Player.leaderstats:FindFirstChild(StatsName).Value >= Price then
				Player.leaderstats:FindFirstChild(StatsName).Value -= Price
				REEvent:FireClient(Player,"purchaseSuccess",TrailName)

				local newValue = Instance.new("BoolValue")
				newValue.Name = TrailName
				newValue.Value = true
				newValue.Parent = Player.trailsOwned
			end
		end)
		if not check then
			warn(errored)
		end
	end
end)

Use WaitForChild() for event not FindFirstChild()
local REEvent = ReplicatedStorage:WaitForChild(“trailShopRE”)


local ReplicatedStorage = game:GetService("ReplicatedStorage")
local REEvent = ReplicatedStorage:WaitForChild("trailShopRE")

REEvent.OnServerEvent:Connect(function(Player,TrailName,TrailColour,state)
	if state == "equip" and Player.Character then
			
         local success,errormsg = pcall(function()
		--	local r, g, b = R, G, B
		--	local strOne = string.format("%0.f", r*255)
		--	local strTwo = string.format("%0.f", g*255)
		--	local strThree = string.format("%0.f", b*255)
			
		--	print(strOne .. " " .. strTwo .. " " .. strThree) 
		--	local Finalcolour = Color3.new(strOne,strTwo,strThree)
			
			local newTrail = Instance.new("Trail")
			newTrail.Name = TrailName
			newTrail.Color = TrailColour
			newTrail.Parent = HRP
			newTrail.MaxLength = 10
			
			local attachmentOne = Instance.new("Attachment")
			attachmentOne.Name = "trailAttachment"
			attachmentOne.Parent = HRP
			
			local attachmentTwo = Instance.new("Attachment")
			attachmentTwo.Name = "trailAttachment"
			attachmentTwo.Parent = Player.Character.Head
			
			newTrail.Attachment0 = attachmentOne
			newTrail.Attachment1 = attachmentTwo
			
			Player.equippedTrail.Value = TrailName
   
				for i, CharacterModel in pairs(player.Character:GetChildren()) do
					if CharacterModel.HumanoidRootPart.trailAttachment:IsA('Trail') then
						characterModel.HumanoidRootPart.trailAttachmentDestroy()
                     elseif CharacterModel.Head.trailAttachment:IsA("Trail") then
                      characterModel.Head.trailAttachmentDestroy()
					end
				end

		end)
		if not success then
			warn(errormsg)
		end
	end
end)

REEvent.OnServerEvent:Connect(function(Player,TrailName,state)
	if state == 'unequip' then
		if Player.Character then
			local unequipped,stillEquipped = pcall(function()
				
				Player.equippedTrail.Value = nil
          
               	for i, CharacterModel in pairs(player.Character:GetChildren()) do
					if CharacterModel.HumanoidRootPart.trailAttachment:IsA('Trail') then
						characterModel.HumanoidRootPart.trailAttachmentDestroy()
                     elseif CharacterModel.Head.trailAttachment:IsA("Trail") then
                      characterModel.Head.trailAttachmentDestroy()
					end
				end
                 
			end)
			if not unequipped then
				warn(stillEquipped)
			end
		end
	end
end)

REEvent.OnServerEvent:Connect(function(Player,Price,TrailName,state)
	if state == "purchase" then
		local check,errored = pcall(function()
			if Player.leaderstats:FindFirstChild(StatsName).Value >= Price then
				Player.leaderstats:FindFirstChild(StatsName).Value -= Price
				REEvent:FireClient(Player,"purchaseSuccess",TrailName)

				local newValue = Instance.new("BoolValue")
				newValue.Name = TrailName
				newValue.Value = true
				newValue.Parent = Player.trailsOwned
			end
		end)
		if not check then
			warn(errored)
		end
	end
end)

EDIT: You typed two times for i, oldTrail in pairs (
it does the same thing and is unstable).

1 Like

Hey there agian, sorry for the delayed response! I noticed that the code that you’ve given me had some typos and errors, so I corrected them. I also managed to figure out alternative names for the script as well to make it less of an eyesore to edit every time. However, now I’m stuck at another thing again.

For the part that has HRP, it comes up with the red lines underneath. I tried to edit it as much as I could, but to no avail. Could you help me out one more time, please? Thank you.

StatsName1 = "Gold"
StatsAmt1 = 1000

StatsName2 = "Voids"
StatsAmt2 = 0

EquippedTrial = "equippedTrail"
EquippedTrailAnt = nil

local DataStoreService = game:GetService("DataStoreService")
local statsStore = DataStoreService:GetDataStore("-stats")
local PlayersService = game:GetService("Players")

function saveStats(Player)
	local leaderFolder = Instance.new("Folder", Player)
	leaderFolder.Name = "leaderstats"

	-- 2 Variables to be stored
	local statsValue1 = Instance.new("NumberValue", leaderFolder) -- Use this 
	--"NumberValue" , leaderFolder instead of .Parent, to make the code more stable
	statsValue1.Value = StatsName1

	local statsValue2 = Instance.new("NumberValue", leaderFolder)
	statsValue2.Name = StatsAmt2

	local lastEquipped = Instance.new("StringValue",Player)
	lastEquipped.Name = EquippedTrial
	lastEquipped.Value = EquippedTrailAnt

	local plrKey= "Player_" .. Player.UserId
	local oldData
	local foundData,newPlayer = pcall(function()
		oldData = statsStore:GetAsync(plrKey)
	end)
	if foundData and oldData ~= nil then
		end
end



local ReplicatedStorage = game:GetService("ReplicatedStorage")
local REEvent = ReplicatedStorage:WaitForChild("trailShopRE")
local HRP = game.WaitForChild("HumanoidRootPart")

REEvent.OnServerEvent:Connect(function(Player,TrailName,TrailColour,state)
	if state == "equip" and Player.Character then

		local success,errormsg = pcall(function()
			--	local r, g, b = R, G, B
			--	local strOne = string.format("%0.f", r*255)
			--	local strTwo = string.format("%0.f", g*255)
			--	local strThree = string.format("%0.f", b*255)

			--	print(strOne .. " " .. strTwo .. " " .. strThree) 
			--	local Finalcolour = Color3.new(strOne,strTwo,strThree)

			local newTrail = Instance.new("Trail")
			newTrail.Name = TrailName
			newTrail.Color = TrailColour
			newTrail.Parent = HRP
			newTrail.MaxLength = 10

			local attachmentOne = Instance.new("Attachment")
			attachmentOne.Name = "trailAttachment"
			attachmentOne.Parent = HRP

			local attachmentTwo = Instance.new("Attachment")
			attachmentTwo.Name = "trailAttachment"
			attachmentTwo.Parent = Player.Character.Head

			newTrail.Attachment0 = attachmentOne
			newTrail.Attachment1 = attachmentTwo

			Player.equippedTrail.Value = TrailName

			for i, CharacterModel in pairs(Player.Character:GetChildren()) do
				if CharacterModel.HumanoidRootPart.trailAttachment:IsA('Trail') then
					CharacterModel.HumanoidRootPart.trailAttachmentDestroy()
				elseif CharacterModel.Head.trailAttachment:IsA("Trail") then
					CharacterModel.Head.trailAttachmentDestroy()
				end
			end

		end)
		if not success then
			warn(errormsg)
		end
	end
end)

REEvent.OnServerEvent:Connect(function(Player,TrailName,state)
	if state == 'unequip' then
		if Player.Character then
			local unequipped,stillEquipped = pcall(function()

				Player.equippedTrail.Value = nil

				for i, CharacterModel in pairs(Player.Character:GetChildren()) do
					if CharacterModel.HumanoidRootPart.trailAttachment:IsA('Trail') then
						CharacterModel.HumanoidRootPart.trailAttachmentDestroy()
					elseif CharacterModel.Head.trailAttachment:IsA("Trail") then
						CharacterModel.Head.trailAttachmentDestroy()
					end
				end

			end)
			if not unequipped then
				warn(stillEquipped)
			end
		end
	end
end)

REEvent.OnServerEvent:Connect(function(Player,Price,TrailName,state)
	if state == "purchase" then
		local check,errored = pcall(function()
			if Player.leaderstats:FindFirstChild(StatsName1).Value >= Price then
				Player.leaderstats:FindFirstChild(StatsName1).Value -= Price
				REEvent:FireClient(Player,"purchaseSuccess",TrailName)

				local newValue = Instance.new("BoolValue")
				newValue.Name = TrailName
				newValue.Value = true
				newValue.Parent = Player.trailsOwned
			end
		end)
		if not check then
			warn(errored)
		end
	end
end)

After a long time, I corrected the code.

local DataStoreService = game:GetService("DataStoreService")
local statsStore = DataStoreService:GetDataStore("-stats")
local PlayersService = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local REEvent = ReplicatedStorage:WaitForChild("trailShopRE")

FolderName = "leaderstats"
FolderType = "Folder"

StatsName1 = "Gold"
StatsAmt1 = 1000
StatsType1 = "NumberValue"

StatsName2 = "Voids"
StatsAmt2 = 0
StatsType2 = "NumberValue"

EquippedTrial = "equippedTrail"
EquippedTrailAnt = nil
EquippedTrailType = "StringValue"

-- DataStore

function saveStats(Player)
local leaderFolder = Instance.new(FolderType, Player)
leaderFolder.Name = FolderName

-- 2 Variables to be stored
local statsValue1 = Instance.new(StatsType1, leaderFolder) -- Use this 
--"NumberValue" , leaderFolder instead of .Parent, to make the code more stable
statsValue1.Name = StatsName1

local statsValue2 = Instance.new(StatsType2,  leaderFolder)
statsValue2.Name = StatsAmt2

local lastEquipped = Instance.new(EquippedTrailType, Player)
lastEquipped.Name = EquippedTrial
lastEquipped.Value = EquippedTrailAnt
local plrKey= "Player_" .. Player.UserId
local oldData
local foundData,newPlayer = pcall(function()
oldData = statsStore:GetAsync(plrKey)
end)
if foundData and oldData ~= nil then
end
end

PlayersService.PlayerAdded:Connect(function(Player)
local succesLoaded,ErrorLoaded = pcall(function()
saveStats(Player)
end)
if succesLoaded then
print("Data loaded for: " ..Player.Name)
else
print("Data not loaded: " ..Player.Name)
end
end)

PlayersService.PlayerRemoving:Connect(function(Player)
local leaderstats = Player.leaderstats
local plrKey = "Player_" .. Player.UserId
local valueToSave = {
leaderstats:FindFirstChild("Gold").Value;
leaderstats:FindFirstChild("Voids").Value;
}
local succesSaved,ErrorSaved = pcall(function()
statsStore:SetAsync(plrKey,valueToSave)
end)
if succesSaved then
print("Data saved! for: "..Player.Name)
else
print("Data not saved! for: "..Player.Name)
end
end)

game:BindToClose(function()
for _, v in pairs(PlayersService:GetPlayers()) do
local succesSaved,ErrorSaved = pcall(function()
saveStats(v)
end)
if succesSaved then
print("Data saved for:".. v.Name)
else
print("Data not saved for:".. v.Name)
end
end
end)

-- Events
	
REEvent.OnServerEvent:Connect(function(Player,Price,TrailName,TrailColour,state)	
print("Event Fired")
local leaderstats = Player.leaderstats
local HRP = char.HumanoidRootPart
local char = Player.Character
local Head = char.Head

if state == "equip" then
print("equip")
--	local r, g, b = R, G, B
--	local strOne = string.format("%0.f", r*255)
--local strTwo = string.format("%0.f", g*255)
--	local strThree = string.format("%0.f", b*255)
--	print(strOne .. " " .. strTwo .. " " .. strThree) 
--	local Finalcolour = Color3.new(strOne,strTwo,strThree)
local newTrail = Instance.new("Trail")
newTrail.Name = TrailName
newTrail.Color = TrailColour
newTrail.Parent = HRP
newTrail.MaxLength = 10
local attachmentOne = Instance.new("Attachment")
attachmentOne.Name = "trailAttachment"
attachmentOne.Parent = HRP
local attachmentTwo = Instance.new("Attachment")
attachmentTwo.Name = "trailAttachment"
attachmentTwo.Parent = char.Head
newTrail.Attachment0 = attachmentOne
newTrail.Attachment1 = attachmentTwo
Player.equippedTrail.Value = TrailName
if HRP.trailAttachment:IsA("Trail") then
HRP.trailAttachment:Destroy()
elseif Head.trailAttachment:IsA("Trail") then
Head.trailAttachment:Destroy()
end
end
elseif state == "unequip" then	
print("unequip")		
Player.equippedTrail.Value = nil
if HRP.trailAttachment:IsA("Trail") then
HRP.trailAttachment:Destroy()
elseif Head.trailAttachment:IsA("Trail") then
Head.trailAttachment:Destroy()
end
elseif  state == "purchase" then
print("purchase")
if leaderstats:FindFirstChild("Gold").Value >= Price then
leaderstats:FindFirstChild("Gold").Value -= Price
REEvent:FireClient(Player,"purchaseSuccess",TrailName)
local newValue = Instance.new("BoolValue")
newValue.Name = TrailName
newValue.Value = true
end
end)

EDIT: I suggest separating the data store script from the event script to be more stable.