How To Track Time Based Rewards

I would like to offer players rewards which occur over time. Some examples are:

  1. Offering a reward chest every 4 hours.
  2. Offering a daily login bonus.
  3. Rewards for logging in multiple days in a row.
  4. Etc.

But I am unsure on how to keep track of such things on a individual player basis, especially with players logging in and out of the game multiple times per day.

If anyone has any experience designing such things into your games, then I would love to hear some ideas. Thank you.

3 Likes

One method is to save the tick() per user at the time that a timestamp needs to be saved for that user. Then you can compare that every time they join the game to display how much time is remaining or if they can get the reward again.

if newTick - savedTick > secondsInADay then
giveDailyLoginReward()
else
displayRemainingTimer()
end
4 Likes

Just a thought, would it not be better to use os.time() instead of tick(), since otherwise if a player changes their timezone, their timestamp would be affected, allowing them to cheat getting multiple rewards without the wait. Using os.time() would remove this possibility because it always returns the same time zone (UTC).

1 Like

Well I think it would be best using the server’s time rather than the client’s time, but yeah making sure its using the same timezone is the best approach. Don’t want players changing their computer’s clock to get an advantage now do we lol.

It’s better to use os.time, but that has nothing to do with their client’s time. You’re only supposed to check the time on the server for this.

1 Like

os.time() method

local DS = game:GetService("DataStoreService")
local RS = game:GetService("ReplicatedStorage")

--Gonna use a RemoteEvent that is supposedely fired when the player clicks a button.

function DailyReward(v)
     --The actual daily reward function, v is for the player's UserId
end

RS.Remote.OnServerEvent:Connect(function(plr, mode, table)
     if (mode == "DAILY_REWARD") then
         local Data = DS:GetDataStore("DailyRewards_V.1", plr.UserId)
         local timeleft = Data:GetAsync("TimeLeft")
         local hours = os.time() + 86400 --Time in seconds, default is 24 hours
         if timeleft == nil then
             Data:SetAsync("TimeLeft", hours)
             Data:IncrementAsync("Amount", 1) --Amount of times the player got the reward
             DailyReward(plr.UserId)
         else
             local timeleft = tonumber(timeleft)
             if (timeleft > 0 and timeleft - os.time() > 0) then
                 DailyReward(plr.UserId)
             end
         end
     end
end)
7 Likes