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)
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.
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)