Reward system when player reaches a certain target

Hello there,

I have been working on a game and currently I am trying to implement a system where if you reach a certain Value (For example 100k) in your leaderstats.Money Value it fires a remote event.

I have been trying to think about how I can implement this one of the first solution I has was to use ‘==’ to see if the player has reached the value. But the value will never be the exact 100k as the money giving reward is a random amount. I also thought about using >= 100k to fire the event but if I do that whenever the player joins the game again he will be rewarded again which I don’t want.

If someone can help me with this that would be awesome.

That mean we need to save somewhere like datastore :sweat_smile:

Just save a bool value and check the bool value is true meaning they have already claimed it for an example. If they haven’t, set it to true and give them the reward.

1 Like

I am saving all the values into a datastore. But if the script runs all the time to just check if the player has more then 100k as the value it will reward the player each time.

For example if I have like 100 different targets when the player has to be rewarded wouldn’t that be a lot of values?

No just 1 value for each milestone, but to each players datastore.

so, combine bool value [each player] + datastore :sweat_smile:

I guess yeah. That would be how to do it.

maybe something like this :sweat_smile:

game.Players.PlayerAdded:Connect(function(plr)
	local c = Instance.new("IntValue")
	c.Name = "Coin"
	c.Parent = plr
	--get reward table data from datastore or if new player create a dictionary table as below
	local reward = {
		[100000] = false,
		[200000] = false,
		[300000] = false
	}
	c.Changed:Connect(function()
		for i,v in pairs(reward) do
			if c.Value > tonumber(i) then
				if reward[i] == false then
                    --must set the value to table first, if not will cause error
					reward[i] = true --or reward[i] = nil --remove from table to prevent more checking
                    --give reward
                    --break --better remove this because of certain conditions
				else 
					--player already claim
				end
			end
		end
	end)
	plr.AncestryChanged:Connect(function()
		--save the reward table to datastore
        --you can yield BindToClose using bindableEvent to make sure datastore save here when server shutdown                  
	end)
end)

	

Edit : made some changes

local AlreadyHas100k = false -- See if player has 100k
local ReceivedPrize = false -- BoolValue, Activates to prevents the player to receive again if they rejoin

game.Players.PlayerAdded:Connect(function(player) -- Let's say that the player Rejoined in the game again
			
-- {
		
--Probaly here is the section that takes care of Creating your Money/Etc
		
-- }
	
if player.Money < 100.000 then -- Player has less than 100.000 money? THEN
		AlreadyHas100k = false -- The player don't has 100k 

		ReceivedPrize = false -- ( This will activate because the player has less than 100k, and he will be able to receive the prize again )
		-- DELETE THIS LINE if you don't want the player to obtain the REWARD again
		
       -- Since he rejoined, ReceivedPrize will be set to false every single time the server checks out that ''The player has less than 100k of Money"... that's why you must delete this
			
if player.Money >= 100.000 and AlreadyHas100k == false then -- Second, see if player has more than or Equal to 100k and if BoolValue is False
				AlreadyHas100k = true -- If yes, then set BoolValue to true
			--You don't need to save this BoolValue in a Datastore, it will be Set to false every single time the player leave the game ( If you want, you Can )
			
if player.Money >= 100.000 and AlreadyHas100k == true and ReceivedPrize == false then -- Third, if somehow the player dind't received the prize, award them-
			
-- If the player has more than 100k. Has the BoolValue TRUE, and dind't received the prize BEFORE >>>> THEN
			
			 ReceivedPrize = true -- The player will not get again this prize ( This value should be saved in Datastore, so whenever the player joins, it will Prevent them from obtaining again)
			
			--Award something to player [ ONLY ONCE ] -- you can change this, too
			
					
					-- This Script[Function] checks if the player has enough Money to proceed some actions, if the player has less than or 99.999 Money, then it will not fire ( When they Join or Rejoin )
			end
		end
	end
end)
if player:WaitForChild("leaderstats"):WaitForChild("Money").Value >= 100000 then
	--do some code
end

Just check if they have exactly or more than 100,000 value of “Money” stat.

If you want to award the user for getting 100,000 money once & not award them again you can use the following:

local player = game.Players.LocalPlayer or game.Players.PlayerAdded:wait()
local moneyStat = player:WaitForChild("leaderstats"):WaitForChild("Money").Value
local awarded = false

moneyStat.Changed:Connect(function(newVal)
	if awarded then
		return
	end
	if newVal >= 100000 then
		--award the user something
		awarded = true --set awarded to true so they cant be awarded again
	end
end)

What about something like this? It’s kind of long though, but it handles if you’ve reached multiple milestones at once, and you don’t need to add a variable for every milestone. The last milestone is inactive to make sure you can add more in the future, and maybe you could assign a function to each of the milestones?

local ds = game:GetService("DataStoreService"):GetDataStore("Last Milestones")
local players = game.Players

local milestones = {
	100,
	500,
	1000,
	10000,
	25000,
	100000
}

local lastMilestones = {}

function HandleMilestone(money, milestone)
	if money >= milestone then
		local nextIndex = table.find(milestones, milestone) + 1

		if nextIndex > #milestones then
			print("You reached the last milestone!")
			return milestone
		end
		
		print("YOUY REACHED THE NEXT MILESTONE")
		
		local nextMilestone = milestones[nextIndex]
		return HandleMilestone(money, nextMilestone)	
	end
	
	return milestone
	
end

function CreateLeaderstats(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local money = Instance.new("IntValue")
	money.Name = "Money"
	money.Parent = leaderstats
	
end

function SaveMilestone(player)
	local succsess, errormessage = pcall(function()
		ds:SetAsync(player.UserId, lastMilestones[player])

	end)

	if not succsess then
		warn(errormessage)
	end
	
end

players.PlayerAdded:Connect(function(player)
	local succsess, errormessage = pcall(function()
		lastMilestones[player] = ds:GetAsync(player.UserId) or milestones[1]
		
	end)
	
	if not succsess then
		warn(errormessage)
	end
	
	CreateLeaderstats(player)
	local money = player:WaitForChild("leaderstats"):WaitForChild("Money")
	
	money.Changed:Connect(function()
		lastMilestones[player]  = HandleMilestone(money.value, lastMilestones[player])
		
	end)
	
end)


players.PlayerRemoving:Connect(function(player)
	SaveMilestone(player)
	
end)

game:BindToClose(function()
	for i, player in ipairs(players:GetPlayers()) do
		SaveMilestone(player)
		
	end
	
end)

3 Likes

I will definitely try this and add some additional code to make it work with my existing ones.

1 Like