Daily Rewards System Not Working

Hello!

I am trying to make a Daily Rewards System for my game.

However there are two problems.

  • The System does not check properly if the reward is already claimed for that day
  • The System does not change days if the reward is claimed and the player has joined on a new day.
  • There are probably a few more problems

Script:

local DataStoreService = game:GetService("DataStoreService")
local dailyRewardStore = DataStoreService:GetDataStore("DailyRewardsTest21")
local ChangeTextRewardRemote = game:GetService("ReplicatedStorage").Remotes.DailyRewardsFold.ChangeTextReward

local dailyRewards = {
	[1] = {reward = 30, type = "Currency"},
	[2] = {reward = "Swift Lure", type = "Lure"},
	[3] = {reward = "100", type = "Currency"},
	[4] = {reward = "500", type = "Currency"},
	[5] = {reward = "1000", type = "Currency"},
	[6] = {reward = "Blessed Lure", type = "Lure"},
	[7] = {reward = "2x Luck for 15 minutes", type = "Buff"}
}

game.Players.PlayerAdded:Connect(function(player)
	local char = player.CharacterAdded:Wait()
	local PlayerLuck = player:WaitForChild("LuckFolder"):WaitForChild("PlayerLuck")

	local playerKey = "Player_" .. player.UserId
	local savedData = dailyRewardStore:GetAsync(playerKey)

	-- Ensure correct initialization after DataStore wipe
	if not savedData then
		savedData = {lastClaimedDay = tonumber(os.date("%j")) - 1, currentDay = 0}
	end

	local lastClaimedDay = savedData.lastClaimedDay
	local currentDay = savedData.currentDay

	print("Last claimed day:", lastClaimedDay)
	print("Current date:", tonumber(os.date("%j")))
	print("Current reward day:", currentDay)

	-- Ensure rewards are only given once per actual day
	local CurrentDate = tonumber(os.date("%j"))
	if CurrentDate == lastClaimedDay then
		print("Already Claimed Rewards For Today") 
		return -- Prevents multiple claims in one day
	else
		print("Ready to Claim Reward!") 
	end

	-- Increment daily reward progression
	if CurrentDate > lastClaimedDay then
		currentDay += 1
		lastClaimedDay = CurrentDate -- Update last claim date
	end

	-- Reset progression if past day 7
	if currentDay > #dailyRewards then
		currentDay = 1
	end

	-- Fire UI event to show the reward day
	if ChangeTextRewardRemote then
		ChangeTextRewardRemote:FireClient(player, currentDay)
	else
		warn("ChangeTextRewardRemote not found!")
	end

	-- Grant reward
	local rewardInfo = dailyRewards[currentDay]
	print(player.Name .. " received: " .. rewardInfo.reward)

	if rewardInfo.type == "Currency" then
		task.wait(10)
		local Credits = player:WaitForChild("leaderstats"):WaitForChild("Credits")
		Credits.Value += tonumber(rewardInfo.reward)
	elseif rewardInfo.type == "Lure" then
		local LureFound = game:GetService("ReplicatedStorage").LureAssets:FindFirstChild(rewardInfo.reward)
		if LureFound then
			local GiveLure = LureFound:Clone()
			GiveLure.Parent = player.Backpack
		end
	elseif rewardInfo.type == "Buff" then
		PlayerLuck.Value = 2
		delay(900, function()
			PlayerLuck.Value = 0
		end)
	end

	-- **Save both LastClaimedDay & CurrentDay to DataStore**
	local success, err = pcall(function()
		dailyRewardStore:SetAsync(playerKey, {lastClaimedDay = CurrentDate, currentDay = currentDay})
	end)

	if not success then
		warn("Failed to save daily reward data for " .. player.Name .. ": " .. err)
	end
end)

3 Likes

Bump


The issue seems to be that the daily reward claim logic is running right when the player joins, instead of being triggered when they actively claim the reward (like pressing a button). Because of that, the script may reset or grant rewards on join without proper checks. Also, the script compares os.date("%j") (day of the year), which is good, but it doesn’t handle timezone differences or player-driven claims. To fix it, move the reward-claiming part into a separate RemoteEvent that runs only when the player clicks “Claim”. Then, on join, only check and display whether the reward is available. This makes sure it only updates the DataStore and gives rewards when the player chooses to claim, avoiding auto-claims and fixing the new-day detection bug.

1 Like

I will try it out thanks!


1 Like

Would there still be the bugs that I mention in my OG post when i do what you said to do?

nope! just do everything correctly & test it out.

1 Like

For some reason when a new player joins, they recieve Swift Lure instead of 30 credits do you know the reason why?

server:

local DataStoreService = game:GetService("DataStoreService")
local dailyRewardStore = DataStoreService:GetDataStore("DailyRewardsTest27")
local ChangeTextRewardRemote = game:GetService("ReplicatedStorage").Remotes.DailyRewardsFold.ChangeTextReward
local NewDailyRewardsRemote = game:GetService("ReplicatedStorage").Remotes.DailyRewardsFold.NewDailyRewards
local GiveRewardsRemote = game:GetService("ReplicatedStorage").Remotes.DailyRewardsFold.GiveReward
local CheckRewardsRemote = game:GetService("ReplicatedStorage").Remotes.DailyRewardsFold.CheckRewards

local dailyRewards = {

	[1] = {reward = 30, type = "Currency"},
	[2] = {reward = "Swift Lure", type = "Lure"},
	[3] = {reward = "100", type = "Currency"},
	[4] = {reward = "500", type = "Currency"},
	[5] = {reward = "1000", type = "Currency"},
	[6] = {reward = "Blessed Lure", type = "Lure"},
	[7] = {reward = "2x Luck for 15 minutes", type = "Buff"}
}

NewDailyRewardsRemote.OnServerInvoke = function(player)
	
	local PlayerLuck = player:WaitForChild("LuckFolder"):WaitForChild("PlayerLuck")

	local playerKey = "Player_" .. player.UserId
	local savedData = dailyRewardStore:GetAsync(playerKey)

	-- Ensure correct initialization after DataStore wipe
	if not savedData then
		savedData = {lastClaimedDay = tonumber(os.date("%j")) - 1, currentDay = 1}
	end

	local lastClaimedDay = savedData.lastClaimedDay
	local currentDay = savedData.currentDay

	print("Last claimed day:", lastClaimedDay)
	print("Current date:", tonumber(os.date("%j")))
	print("Current reward day:", currentDay)

	-- Ensure rewards are only given once per actual day
	local CurrentDate = tonumber(os.date("%j"))
	if CurrentDate == lastClaimedDay then
		print("Already Claimed Rewards For Today") 
		CheckRewardsRemote:FireClient(player, currentDay)
		return false, currentDay
	else
		CheckRewardsRemote:FireClient(player, currentDay)
	end
	
	GiveRewardsRemote.OnServerEvent:Wait()
	print("Ready to Claim Reward!") 
	
	-- Increment daily reward progression
	if CurrentDate > lastClaimedDay then
		currentDay += 1
		lastClaimedDay = CurrentDate -- Update last claim date
	end

	-- Reset progression if past day 7
	if currentDay > #dailyRewards then
		currentDay = 1
	end

	-- Fire UI event to show the reward day
	if ChangeTextRewardRemote then
		ChangeTextRewardRemote:FireClient(player, currentDay)
	else
		warn("ChangeTextRewardRemote not found!")
	end
	print(dailyRewards[currentDay])
	-- Grant reward
	local rewardInfo = dailyRewards[currentDay]
	if currentDay == 1 and rewardInfo.reward == "Swift Lure" then
		rewardInfo -= 1
		print(rewardInfo.reward)
	end
	print(player.Name .. " received: " .. rewardInfo.reward)

	if rewardInfo.type == "Currency" then
		task.wait(10)
		local Credits = player:WaitForChild("leaderstats"):WaitForChild("Credits")
		Credits.Value += tonumber(rewardInfo.reward)
		return true, currentDay
	elseif rewardInfo.type == "Lure" then
		local LureFound = game:GetService("ReplicatedStorage").LureAssets:FindFirstChild(rewardInfo.reward)
		if LureFound then
			local GiveLure = LureFound:Clone()
			GiveLure.Parent = player.Backpack
			return true, currentDay
		end
	elseif rewardInfo.type == "Buff" then
		PlayerLuck.Value = 2
		delay(900, function()
			PlayerLuck.Value = 0
		end)
		return true, currentDay
	end

	-- **Save both LastClaimedDay & CurrentDay to DataStore**
	local success, err = pcall(function()
		dailyRewardStore:SetAsync(playerKey, {lastClaimedDay = CurrentDate, currentDay = currentDay})
	end)

	if not success then
		warn("Failed to save daily reward data for " .. player.Name .. ": " .. err)
	end
	
end

game.Players.PlayerAdded:Connect(function(player)
	
	
end)

Bump


Bump


well you start off with currentDay = 1, so when you increment it it becomes 2 and fetches the item in the 2nd index, which is the lure

Where did I do that in the script?


and
image

The original script you posted correctly had currentDay initialized to 0, but it seems you changed it inadvertently in the second one