Consecutive daily rewards

local DataStoreService = game:GetService('DataStoreService')

local RewardDataStore = DataStoreService:GetDataStore('RewardsDataStore', '001')

-- Fire below when player is added
local LastLogin = RewardDataStore:GetAsync(player.UserId)
			
if LastLogin then
	local Seconds = os.time() - LastLogin
	local Minutes = Seconds / 60
	local Hours = Minutes / 60
	
	if Hours >= 24 then
		RewardDataStore:SetAsync(player.UserId, os.time())
		UpdateCash(player, 50)
		DailyReward:FireClient(player)
	end
else
	RewardDataStore:SetAsync(player.UserId, os.time())
	UpdateCash(player, 50)
	DailyReward:FireClient(player)
end

This is my current daily reward system, however, I wanna try making a consecutive daily reward system. So login the first day, get prize 1, log in the second day in a row get prize 2, etc. up to day 5. After loging in for 6th day in a row it goes back to prize 1 and works its way back up again.

1 Like

Why not just store a number counting the days the logged in that increases every day? You can add the number of currency in a table. Something like this

local StreakAwards = {1,5,10,20,25} --whatever awards you want in consecutive days
local Streak = LastLogin.Streak
Streak = Streak+1
local Award = StreakAwards[Streak]
if not Award then
Award = StreakAwards[#StreakAwards] --Sets a max limit on how much they can really earn consecutively
end


UpdateCash(player,Award)
DailyReward:FireClient(player,Streak,Award) --You might want to tell them how many days they've been on in a row and how much they earned as well
--It's optional if you want to edit your code or whatever

local Data = {}
Data.Streak = Streak
Data.LastLogin = LastLogin
--[[This might be a little confusing, but you need to enter multiple pieces of data. So you must now reference both when unpacking the player data like this:

local LogInfo = NameOfDataStore:GetAsync(player.userId)
local LastLogin = LogInfo.LastLogin
local Streak = LogInfo.Streak]]


-- You now have to save the data from the login by doing this
RewardDataStore:SetAsync(player.userId,Data)

this code would replace this:

With the exception of the RewardsTable. Hope this helped! Please tell me if you had trouble understanding anything

So like so;

local LastLogin = RewardDataStore:GetAsync(player.UserId)
			
	if LastLogin then
		local Seconds = os.time() - LastLogin
		local Minutes = Seconds / 60
		local Hours = Minutes / 60
		
		local StreakAwards = {1,5,10,20,25}
		local Streak = LastLogin.Streak
		
		Streak = Streak + 1
		
		local Award = StreakAwards[Streak]
		if not Award then
			Award = StreakAwards[#StreakAwards]
		end

		UpdateCash(player,Award)
		DailyReward:FireClient(player,Streak,Award)

		local Data = {}
		Data.Streak = Streak
		Data.LastLogin = LastLogin

		RewardDataStore:SetAsync(player.userId,Data)
	end

?? I feel like this wouldnt work as if LastLogin doesn’t exist then it’s never gonna run any of the code

Unfortunately since LastLogin doesn’t store the streak, it would return nil based on your code in your datastore. Since you would have to make a tiny edit

local Streak = LastLoging.Streak or 0

If I’m not forgetting anything, this should work

local LastLogin = RewardDataStore:GetAsync(player.UserId)
	
	local Streak = LastLogin.Streak or 0 -- error
			
	if LastLogin then
		local Seconds = os.time() - LastLogin
		local Minutes = Seconds / 60
		local Hours = Minutes / 60
		
		local StreakAwards = {50, 100, 250, 500, 1000}
		local Streak = LastLogin.Streak
		
		Streak = Streak + 1
		
		local Award = StreakAwards[Streak]
		if not Award then
			Award = StreakAwards[#StreakAwards]
		end

		UpdateCash(player, Award)
		DailyReward:FireClient(player, Streak, Award)

		local Data = {}
		Data.Streak = Streak
		Data.LastLogin = LastLogin

		RewardDataStore:SetAsync(player.UserId, Data)
	end

[attempt to index local ‘LastLogin’ (a nil value)

What returns the error? LastLogin? Or streak?

Well Lastlogin doesn’t exist

local LastLogin = RewardDataStore:GetAsync(player.UserId)
	
local Streak = LastLogin.Streak or 0

If the player hasn’t previously played and had data saved then LastLogin returns nil

In that case, you could do

if LastLogin ~= nil then
    --code here
else
    --do nothing
end
local LastLogin = RewardDataStore:GetAsync(player.UserId)
			
	if LastLogin then
		local Seconds = os.time() - LastLogin
		local Minutes = Seconds / 60
		local Hours = Minutes / 60
		
		local StreakAwards = {50, 100, 250, 500, 1000}
		local Streak = LastLogin.Streak
		
		Streak = Streak + 1
		
		local Award = StreakAwards[Streak]
		if not Award then
			Award = StreakAwards[#StreakAwards]
		end

		UpdateCash(player, Award)
		DailyReward:FireClient(player, Streak, Award)

		local Data = {}
		Data.Streak = Streak
		Data.LastLogin = LastLogin

		RewardDataStore:SetAsync(player.UserId, Data)
	else
		local StreakAwards = {50, 100, 250, 500, 1000}
		local Streak = LastLogin.Streak -- ERROR
		
		Streak = Streak + 1
		
		local Award = StreakAwards[Streak]
		if not Award then
			Award = StreakAwards[#StreakAwards]
		end

		UpdateCash(player, Award)
		DailyReward:FireClient(player, Streak, Award)

		local Data = {}
		Data.Streak = Streak
		Data.LastLogin = LastLogin

		RewardDataStore:SetAsync(player.UserId, Data)
	end

[ attempt to index local ‘LastLogin’ (a nil value)]

Since LastLogin is nil, doing LastLogin.Streak is going to return an error.

Setting Streak to 1 instead of getting it from LastLogin will fix it.

Ok works the first time but if I rejoin it breaks

local LastLogin = RewardDataStore:GetAsync(player.UserId)
			
	if LastLogin then
		local Seconds = os.time() - LastLogin -- ERROR
		local Minutes = Seconds / 60
		local Hours = Minutes / 60
		
		local Streak = LastLogin.Streak
		
		Streak = Streak + 1
		
		local Award = StreakAwards[Streak]
		if not Award then
			Award = StreakAwards[#StreakAwards]
		end

		UpdateCash(player, Award)
		DailyReward:FireClient(player, Streak, Award)

		local Data = {}
		Data.Streak = Streak
		Data.LastLogin = LastLogin

		RewardDataStore:SetAsync(player.UserId, Data)
	else
		local Streak = 1
				
		local Award = StreakAwards[Streak]
		if not Award then
			Award = StreakAwards[#StreakAwards]
		end

		UpdateCash(player, Award)
		DailyReward:FireClient(player, Streak, Award)

		local Data = {}
		Data.Streak = Streak
		Data.LastLogin = LastLogin

		RewardDataStore:SetAsync(player.UserId, Data)
	end

[ attempt to perform arithmetic on local ‘LastLogin’ (a table value)]

Being that LastLogin is nil, setting Data.LastLogin to LastLogin makes it nil. You should set it to os.time(). That, and you have to do LastLogin.LastLogin to get the time.

Since LastLogin is now being set to a table value, holding both the time of their last arrival and they’re currently on, you need to Set LastLogin to

local LastLogin = [PickANewNameToReferenceTheKey].LastLogin

Still get same error on same line

local LastLogin = RewardDataStore:GetAsync(player.UserId)
			
	if LastLogin then
		local Seconds = os.time() - LastLogin -- ERROR
		local Minutes = Seconds / 60
		local Hours = Minutes / 60
		
		local Streak = LastLogin.Streak
		
		Streak = Streak + 1
		
		local Award = StreakAwards[Streak]
		if not Award then
			Award = StreakAwards[#StreakAwards]
		end

		UpdateCash(player, Award)
		DailyReward:FireClient(player, Streak, Award)

		local Data = {}
		Data.Streak = Streak
		Data.LastLogin = LastLogin

		RewardDataStore:SetAsync(player.UserId, Data)
	else
		local Streak = 1
				
		local Award = StreakAwards[Streak]
		if not Award then
			Award = StreakAwards[#StreakAwards]
		end

		UpdateCash(player, Award)
		DailyReward:FireClient(player, Streak, Award)

		local Data = {}
		Data.Streak = Streak
		Data.LastLogin = os.time()

		RewardDataStore:SetAsync(player.UserId, Data)
	end

[attempt to perform arithmetic on local ‘LastLogin’ (a table value)]

Do local Seconds = os.time() - LastLogin.LastLogin

Ok, now I can just join multiple times and get the rewards

local LoginData = RewardDataStore:GetAsync(player.UserId)
			
	if LoginData then
		local Seconds = os.time() - LoginData.LastLogin -- ERROR
		local Minutes = Seconds / 60
		local Hours = Minutes / 60
		
		local Streak = LoginData.Streak
		
		Streak = Streak + 1
		
		local Award = StreakAwards[Streak]
		if not Award then
			Award = StreakAwards[#StreakAwards]
		end

		UpdateCash(player, Award)
		DailyReward:FireClient(player, Streak, Award)

		local Data = {}
		Data.Streak = Streak
		Data.LastLogin = os.time()

		RewardDataStore:SetAsync(player.UserId, Data)
	else
		local Streak = 1
				
		local Award = StreakAwards[Streak]
		if not Award then
			Award = StreakAwards[#StreakAwards]
		end

		UpdateCash(player, Award)
		DailyReward:FireClient(player, Streak, Award)

		local Data = {}
		Data.Streak = Streak
		Data.LastLogin = os.time()

		RewardDataStore:SetAsync(player.UserId, Data)
	end

So I join once, get reward one, join again get reward 2, etc. It’s not waiting a day

You need to check if the hours since last login is >= 24. Do

if Hours >= 24 then
    --code
end
1 Like
local DataStoreService = game:GetService('DataStoreService')
local RewardDataStore = DataStoreService:GetDataStore('RewardsDataStore', '001')

game.Players.PlayerAdded:connect(function(Player)
	local RewardData = RewardDataStore:GetAsync(tostring(Player.UserId))
	
	if typeof(RewardData) == "table" then
		local LastLogin = RewardData[1]
		local DaysInRow = RewardData[2]
		local Seconds = os.time() - LastLogin
		local Minutes = Seconds / 60
		local Hours = Minutes / 60
	
		if Hours >= 12 and Hours <= 36 then -- they logged in 12 to 36 hours since their last (change as you desire)
			RewardDataStore:SetAsync(tostring(Player.UserId), {os.time(), DaysInRow + 1})
			UpdateCash(Player, 50)
			DailyReward:FireClient(Player)
		end
	else
		RewardDataStore:SetAsync(tostring(Player.UserId), {os.time(), 0})
		UpdateCash(Player, 50)
		DailyReward:FireClient(Player)
	end
end)

This works. You need to check between X and Y hours. And it tracks how many days in a row, too!

3 Likes

Instead of using os.time(), I’d recommend you use tick(), because os.time() can be changed on the clients computer to something else.

…? This is being done on the server though. tick() returns the number of seconds since the UNIX Epoch in the server’s time zone, os.time() returns the number of seconds since the UNIX Epoch in UTC explicitly.

Why would you use tick over os.time? This is especially so when it’s on the server. If it’s on the client, then be it tick or os.time, the client can change what it returns easily.

4 Likes