Recently, I have been wondering how to create my own an ‘Offline Earnings’ system after seeing many Simulator type games using them, I didn’t want to create it because I have developed a simulator, I just thought it would be helpful for people. Yes, my script may be flawed, I do apologise, I’m not the best, nor am I where I want to be, but it’s the effort that counts! P.S. this is my first forum post!
local DataStoreService = game:GetService("DataStoreService")
local offlineData = DataStoreService:GetDataStore("offlineData")
local dataSave = DataStoreService:GetDataStore("playerData")
local storeService = game:GetService("MarketplaceService")
local maxHours = 24
local maxSeconds = maxHours * 60 * 60
local dataKey = 'whateverkeyyouwant'
local pVals = Instance.new('ArcHandles')
pVals.Name = 'playerVals'
pVals.Parent = game.ServerStorage
function saveData(Player,Cash,Login,Change)
local playerData = {
[tostring(Player.UserId)] = {
savedCash = Cash,
savedTime = Login,
savedChange = Change
}
}
dataSave:SetAsync(dataKey,playerData)
end
function dataCheck(passedData)
if passedData ~= 0 or passedData ~= nil then
return true
end
end
Players.PlayerAdded:Connect(function(Player)
local dataParent = Instance.new('Folder')
dataParent.Name = 'leaderstats'
dataParent.Parent = Player
local cashData = Instance.new('NumberValue')
cashData.Name = 'Cash'
cashData.Parent = dataParent
local pVal = Instance.new('NumberValue')
pVal.Parent = pVals
pVal.Name = Player.Name
local cChange = Instance.new('NumberValue')
cChange.Parent = Player
cChange.Name = 'CPS'
local loadedData
local success, errormessage = pcall(function()
loadedData = dataSave:GetAsync(dataKey)
end)
if success then
if loadedData[tostring(Player.UserId)] then
local personalData = loadedData[tostring(Player.UserId)]
cashData.Value = personalData.savedCash
pVal.Value = personalData.savedCash
if dataCheck(personalData.savedTime) and dataCheck(personalData.savedChange) then
if personalData.savedTime >= maxSeconds then
local offlineTime = os.time() - maxSeconds
local offlineEarnings = (offlineTime * personalData.savedChange) / 4
cashData.Value += offlineEarnings
elseif loadedData.savedTime < maxSeconds then
local offlineTime = os.time() - personalData.savedTime
local offlineEarnings = (offlineTime * personalData.savedChange) / 4
cashData.Value += offlineEarnings
end
wait()
saveData(Player,Player.leaderstats.Cash.Value,os.time(),0)
end
else
print(errormessage)
end
cashData.Changed:Connect(function()
if cashData.Value >= pVal.Value then
local cashDifference = cashData.Value - pVal.Value
cChange.Value = cashDifference
wait()
pVal.Value = cashData.Value
end
end)
end
end)
Players.PlayerRemoving:Connect(function(Player)
pVals:FindFirstChild(Player.Name):Destroy()
local leaveTime = os.time()
local success, errormessage = pcall(function()
saveData(Player,Player.leaderstats.Cash.Value,leaveTime,Player.CPS.Value)
end)
if success then
print('Successfully saved data!')
else
print(errormessage)
end
end)
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local savedData = DataStoreService:GetDataStore("Cash")
local lastLogin = DataStoreService:GetDataStore("lastLogin")
local cashChange = DataStoreService:GetDataStore("cashChange")
local storeService = game:GetService("MarketplaceService")
local passId = 0
local pVals = Instance.new('ArcHandles')
pVals.Name = 'playerVals'
pVals.Parent = game.ServerStorage
function dataCheck(passedData)
if passedData ~= 0 or passedData ~= nil then
return true
end
end
Players.PlayerAdded:Connect(function(Player)
local dataParent = Instance.new('Folder')
dataParent.Name = 'leaderstats'
dataParent.Parent = Player
local cashData = Instance.new('NumberValue')
cashData.Name = 'Cash'
cashData.Parent = dataParent
local pVal = Instance.new('NumberValue')
pVal.Parent = pVals
local cChange = Instance.new('NumberValue')
cChange.Parent = Player
cChange.Name = 'CPS'
local loadedCash
local loginData
local changeData
local success, errormessage = pcall(function()
loadedCash = savedData:GetAsync(Player.UserId)
loginData = lastLogin:GetAsync(Player.UserId)
changeData = cashChange:GetAsync(Player.UserId)
end)
if success then
cashData.Value = loadedCash
pVal.Value = loadedCash
if storeService:UserOwnsGamePassAsync(Player.UserId,passId) then
if dataCheck(loginData) and dataCheck(changeData) then
local offlineTime = os.time() - loginData
local offlineEarnings = (offlineTime * changeData) / 4
cashData.Value += offlineEarnings
wait()
cashChange:SetAsync(Player.UserId,0)
end
end
else
print(errormessage)
end
cashData.Changed:Connect(function()
if cashData.Value >= pVal.Value then
local cashDifference = cashData.Value - pVal.Value
cChange.Value = cashDifference
wait()
pVal.Value = cashData.Value
end
end)
end)
Players.PlayerRemoving:Connect(function(Player)
local leaveTime = os.time()
local success, errormessage = pcall(function()
savedData:SetAsync(Player.UserId,Player.leaderstats.Cash.Value)
lastLogin:SetAsync(Player.UserId,leaveTime)
cashChange:SetAsync(Player.UserId,Player.CPS.Value)
end)
if success then
print('Successfully saved data!')
else
print(errormessage)
end
end)
Avoid using more DataStores than you have to. You can put all this related data into one DataStore with the key as the player’s UserId and the value as a dictionary containing all this. Having a DataStore per value of data causes an anti-pattern of too much DataStore use. In your case, you’re hitting a 3n rate limit where per player, 3 Get/Set requests are ran. You’re sure to get throttles very quickly.
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local savedData = DataStoreService:GetDataStore("Cash")
local lastLogin = DataStoreService:GetDataStore("lastLogin")
local cashChange = DataStoreService:GetDataStore("cashChange")
local storeService = game:GetService("MarketplaceService")
local passId = 0
local pVals = Instance.new('ArcHandles')
pVals.Name = 'playerVals'
pVals.Parent = game.ServerStorage
function dataCheck(passedData)
if passedData ~= 0 or passedData ~= nil then
return true
end
end
Players.PlayerAdded:Connect(function(Player)
if success then
cashData.Value = loadedCash
pVal.Value = loadedCash
if storeService:UserOwnsGamePassAsync(Player.UserId,passId) then
if dataCheck(loginData) and dataCheck(changeData) then
local offlineTime = os.time() - loginData
local offlineEarnings = (offlineTime * changeData) / 4
cashData.Value += offlineEarnings
wait()
cashChange:SetAsync(Player.UserId,0)
end
end
else
print(errormessage)
end
cashData.Changed:Connect(function()
if cashData.Value >= pVal.Value then
local cashDifference = cashData.Value - pVal.Value
cChange.Value = cashDifference
wait()
pVal.Value = cashData.Value
end
end)
end)
Players.PlayerRemoving:Connect(function(Player)
local leaveTime = os.time()
local success, errormessage = pcall(function()
savedData:SetAsync(Player.UserId,Player.leaderstats.Cash.Value)
lastLogin:SetAsync(Player.UserId,leaveTime)
cashChange:SetAsync(Player.UserId,Player.CPS.Value)
end)
if success then
print('Successfully saved data!')
else
print(errormessage)
end
end)