Currency Conversion Not Saving To Leaderstats

What do you mean by “gems getting converted to coins”. In the script all it does is load the player’s leaderstats when they join and save the leaderstats when the player leaves. It doesn’t add or change any leaderstats values while the player is playing. In order to actually change the values, you need to do it in a server script too.

example:

player.leaderstats.Gems += 5

Sorry, I guess I was not clear enough about the whole topic. There is another script in a GUI (which is a local script) that does all of that, which works fine, it just for some reason does not save. I will put it below, I used it off of a post on here.

local player = game.Players.LocalPlayer
local coins = player.leaderstats.Coins
local gems = player.leaderstats.Gems
local Amount = script.Parent.Parent.Parent.TypeBar.NumberHere.Text
local confirm = script.Parent.Parent.Yes

script.Parent:GetPropertyChangedSignal("Text"):Connect(function()
	script.Parent.Parent.Parent.TypeBar.NumberHere.Text = script.Parent.Parent.Parent.TypeBar.NumberHere.Text:gsub('%D+', '');  -- Forces only numerical value input
end)

function Click(mouse)	--Conversion system
	Amount = script.Parent.Parent.Parent.TypeBar.NumberHere.Text
	print(Amount)
	if tonumber(Amount) then
		if gems.Value >= tonumber(Amount) then
			coins.Value = coins.Value + Amount * 20
			gems.Value = gems.Value - Amount
			
			script.Parent.Parent.Visible = false
			script.Parent.Parent.Parent.Visible = false
			wait(3)
		end
	end
end
confirm.MouseButton1Down:connect(Click)

Whatever is typed into the TextBox will be multiplied by 20 and added to the players coins balance, subtracting the original number from the players gem balance

As I’ve said before, anything related to the DataStoreService will NOT WORK in a LOCALscript.
I’ll make a step by step guide on doing this:

  1. Create a RemoteEvent and put it in ReplicatedStorage. Call it “ChangeLeaderstat”.

  2. Create a variable at the start of your localscript:
    local ChangeLeaderstat = game.ReplicatedStorage.ChangeLeaderstat

  3. In the localscript replace everything in the Click() function to this:

Amount = script.Parent.Parent.Parent.TypeBar.NumberHere.Text
   	
if tonumber(Amount) then
	if gems.Value >= tonumber(Amount) then
		ChangeLeaderstat:FireServer("Coins", coins.Value + Amount * 20)
		ChangeLeaderstat:FireServer("Gems",	gems.Value = gems.Value - Amount)
			
		script.Parent.Parent.Visible = false
		script.Parent.Parent.Parent.Visible = false
		wait(3)
	end
end
  1. In the same serverscript, add the same variable at the start of the script:
    local ChangeLeaderstat = game.ReplicatedStorage.ChangeLeaderstat

  2. Add this to the end of the script:

ChangeLeaderstat.OnClientEvent:Connect(function(plr, stat, value)
    plr.leaderstats[stat].Value = value
end)

I have to warn you to be careful with how much control you give players over datastores/currency in your game. With this remote event, anyone could just set any amount of coins they would like using a lua executor/hack

Which serverscript? or am i just changing the (converting script) localscript to a normal? Again, sorry for all the trouble.

There is only one server script, and that is the one I mentioned before, with the PlayerAdded/PlayerRemoved events. And no you are not chang the localscript, they are 2 separate scripts

1 Like
		ChangeLeaderstat:FireServer("Gems",	gems.Value = gems.Value - Amount)

In this the “=” is underlined red, so I am assuming you need another???

As for the Click part of the function, that is the part of the code that allowed the whole code to be played. Now, when I play the game and hit “Confirm” (to convert the currency), nothing happens.

confirm.MouseButton1Down:connect(Click)

Hey, sorry for replying late.

Sorry, I haven’t tested this code so I am doing it in my browser.

replace it with this:
ChangeLeaderstat:FireServer("Coins", coins.Value + Amount * 20)
ChangeLeaderstat:FireServer("Gems", gems.Value - Amount)

If it doesn’t work show me ur scripts

local ChangeLeaderstat = game.ReplicatedStorage.ChangeLeaderstat
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("MoneyStats")

game.Players.PlayerAdded:Connect(function(Player)
	local leaderstats = Instance.new("Folder") --Added this part because it gave an error that leaderstats isnt apart of player
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = Player
	local Gems = Instance.new("IntValue")
	Gems.Name = "Gems"
	Gems.Value = 250
	Gems.Parent = leaderstats
	local Coins = Instance.new("IntValue")
	Coins.Name = "Coins"
	Coins.Value = 0
	Coins.Parent = leaderstats
	-- These variables need to be defined when the player joins, because each player has their own unique leaderstats
	local Gems = Player.leaderstats.Gems
	local Coins = Player.leaderstats.Coins

	local Data
	pcall(function()
		Data = DataStore:GetAsync(Player.UserId)
	end)

	if Data then
		Gems.Value = Data["Gems"]
		Coins.Value = Data["Coins"]
	else -- there is no data, which means the player joined for the first time
		Gems.Value = 0 -- Any default value you want
		Coins.Value = 0 -- Any default value you want
	end
end)
game.Players.PlayerRemoving:Connect(function(Player)
	DataStore:SetAsync(Player.UserId, {
		["Gems"] = Player.leaderstats.Gems.Value;
		["Coins"] = Player.leaderstats.Coins.Value;
	})
	ChangeLeaderstat.OnClientEvent:Connect(function(plr, stat, value)
		plr.leaderstats[stat].Value = value
	end)
end)
local ChangeLeaderstat = game.ReplicatedStorage.ChangeLeaderstat
local player = game.Players.LocalPlayer
local coins = player.leaderstats.Coins
local gems = player.leaderstats.Gems
local Amount = script.Parent.Parent.Parent.TypeBar.NumberHere.Text
local confirm = script.Parent.Parent.Yes

script.Parent:GetPropertyChangedSignal("Text"):Connect(function()
	script.Parent.Parent.Parent.TypeBar.NumberHere.Text = script.Parent.Parent.Parent.TypeBar.NumberHere.Text:gsub('%D+', '');  -- Forces only numerical value input
end)

Amount = script.Parent.Parent.Parent.TypeBar.NumberHere.Text

if tonumber(Amount) then
	if gems.Value >= tonumber(Amount) then
		ChangeLeaderstat:FireServer("Coins", coins.Value + Amount * 20)
		ChangeLeaderstat:FireServer("Gems", gems.Value - Amount)

		script.Parent.Parent.Visible = false
		script.Parent.Parent.Parent.Visible = false
		wait(3)
	end
end

I believe it would work, there is just nothing that fires the second script once the button gui is clicked.

Basically the first script is the normal leaderstat script i have

Haha. You haven’t read my instructions correctly XD

in step 3 I mentioned to replace everything in the Click() function with that code. So this would be the whole script:

local ChangeLeaderstat = game.ReplicatedStorage.ChangeLeaderstat
local player = game.Players.LocalPlayer
local coins = player.leaderstats.Coins
local gems = player.leaderstats.Gems
local Amount = script.Parent.Parent.Parent.TypeBar.NumberHere.Text
local confirm = script.Parent.Parent.Yes

script.Parent:GetPropertyChangedSignal("Text"):Connect(function()
	script.Parent.Parent.Parent.TypeBar.NumberHere.Text = script.Parent.Parent.Parent.TypeBar.NumberHere.Text:gsub('%D+', '');  -- Forces only numerical value input
end)
function Click(mouse)	--Conversion system
    Amount = script.Parent.Parent.Parent.TypeBar.NumberHere.Text
    if tonumber(Amount) then
	    if gems.Value >= tonumber(Amount) then
		    ChangeLeaderstat:FireServer("Coins", coins.Value + Amount * 20)
		    ChangeLeaderstat:FireServer("Gems", gems.Value - Amount)

		    script.Parent.Parent.Visible = false
		    script.Parent.Parent.Parent.Visible = false
		    wait(3)
	    end
    end
end
confirm.MouseButton1Down:connect(Click)

Oh, geez im clumsy. The button works now, but now no currencies change which is weird…

You added the ChangeLeaderstat.OnClientEvent inside the PlayerRemoving event.

Which means it wont even check for the event until the player leaves…

Just add the ChangeLeaderstat event function to the end of the script

game.Players.PlayerRemoving:Connect(function(Player)
	DataStore:SetAsync(Player.UserId, {
		["Gems"] = Player.leaderstats.Gems.Value;
		["Coins"] = Player.leaderstats.Coins.Value;
	})

end)

ChangeLeaderstat.OnClientEvent:Connect(function(plr, stat, value)
	plr.leaderstats[stat].Value = value
end)

Did my peanut brain do this correct? If so theres an error.

  20:37:57.713  OnClientEvent can only be used on the client  -  Server - OtherLeaderstats:42
  20:37:57.714  Stack Begin  -  Studio
  20:37:57.714  Script 'ServerScriptService.OtherLeaderstats', Line 42  -  Studio - OtherLeaderstats:42
  20:37:57.714  Stack End  -  Studio

Sorry lol this is my bad its like 3 am and Im not thinking straight myself

replace OnClientEvent with OnServerEvent

XD, you are good. It worked now. Thanks a lot for putting up with me lol

1 Like

Haha, I like to help people, are u sure its all working now? If so, you can mark one of my posts as a solution so people don’t have to keep finding it and trying to help further :slight_smile:

1 Like

If I may ask, how can this be prevented?

Yep I am 100% sure, marked as solution.

So lua executors/hacks work like this:

The user basically injects a local script into the game and runs any possible code they want on the client. So they could run something like this:

local value = 9999999999999999999
game.ReplicatedStorage.ChangeLeaderstat:FireServer("Coins", value)
game.ReplicatedStorage.ChangeLeaderstat:FireServer("Gems", value)

-- ez free money

The best way to counter this is by doing the math and checking if the value is valid on the SERVER. This is a rather hard thing to learn and hard to explain so I would recommend this post that explains it well. You could also do some research on how to secure your game better.

As I’ve just mentioned have to warn you though, it’s pretty complicated seeing your current level of scripting knowledge, but see what u can do. It’s fine if you don’t understand it yet as currently its not the most important thing since you are still learning. But it is important to address security of your future serious projects/games in the future.

2 Likes

Thanks, I will dig deeper into that before the game is completed. Now I’ll do my best just to learn. Mainly what this game is for, learning. :slight_smile:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.