[Tutorial] Simple server-sided cooldown system!

After searching quite a lot on the internet I couldn’t find a simple server-sided cooldown system so I made my own and posted so that others could also be helped!

Simple Server-Sided CoolDown System

First, we make a server script for saving the cooldowns [Here for example my cooldown name is “Rebirth”]:

local DS = game:GetService("DataStoreService"):GetDataStore("Save")
local DataStoreSaveSlot = 1
local DataStoreService = game:GetService("DataStoreService")
local Players = game:getService("Players")
local DataStore1 = DataStoreService:GetDataStore("DataStore1 - "..game.CreatorId)
local StartingValue = 0

Players.PlayerAdded:Connect(function(player)
	local UserCoolDownsData
	local success, errMsg = pcall(function()
		UserCoolDownsData = DataStore1:GetAsync(player.UserId.." - CoolDowns: "..DataStoreSaveSlot)
	end)
	if success == false then
		local doNotSave = Instance.new("Folder")
		doNotSave.Name = "DoNotSave"
		doNotSave.Parent = player
	else
		print("[DataStore] "..player.Name.." Data Successfully Found!")
	end
	local CoolDowns = Instance.new("Folder")
	CoolDowns.Name = "CoolDowns"
	CoolDowns.Parent = player
	local RebirthCoolDown = Instance.new("NumberValue")
	RebirthCoolDown.Name = "Rebirth"
	RebirthCoolDown.Value = UserCoolDownsData or StartingValue
	RebirthCoolDown.Parent = CoolDowns
	print("[DataStore] "..player.Name.." Data Successfully Loaded!")
end)

Players.PlayerRemoving:Connect(function(player)
	local SavingPath3 = player.CoolDowns:FindFirstChild("Rebirth")
	if player:FindFirstChild("DoNotSave") then
		warn("[DataStore] "..player.Name.." Data was not saved to avoid data loss.")
	else
		DataStore1:SetAsync(player.UserId.." - CoolDowns: "..DataStoreSaveSlot, SavingPath3.Value)
		print("[DataStore] "..player.Name.." Data Successfully Saved!")
	end
end)

Second, we make another server script [For subtracting each second from the cooldown value]:

while true do
	wait(0.1)
	local players = game.Players:GetPlayers()
	for i=1,#players do
		if players[i]:FindFirstChild("CoolDowns") then -- Checks For the Cooldowns folder in players.
			for i, v in pairs(players[i].CoolDowns:GetChildren()) do 
				if v:IsA("NumberValue") then
					if v.Value ~= 0 then
						v.Value -= 1 -- Subtracts 1 every second from the cooldown value if its more than 0.
					end
				end
			end
		end
		wait(1) 
	end
end

Third, To check the cooldown we can do this:
LocalScript [But checking from server side using remote events is safer because of exploiters!]:

local cooldown = game.Players.LocalPlayer:FindFirstChild("CoolDowns")
if cooldown then
    if cooldown.Rebirth.Value == 0 then
        print("Player doesn't have any cooldowns!")
    end
end

Fourth, To add the cooldown we can do this:
ServerScript [If you want to do it from the client side you can just use a remote event]:

local cooldown = game.Players.LocalPlayer:FindFirstChild("CoolDowns")
if cooldown then
    if cooldown.Rebirth.Value == 0 then -- Optional [you can remove this to just add to the current cooldown going on]
        cooldown.Rebirth.Value += 300 -- Seconds!
    end
end

Fifth, To check the remaining time for cooldown:
Local Script [But checking from server side using remote events is safer because of exploiters!]:

if player.CoolDowns.Rebirth.Value ~= 0 then
		local min, sec = tostring(math.floor(player.CoolDowns.Rebirth.Value/60)), tostring(player.CoolDowns.Rebirth.Value%60)
		if #sec == 1 then
			sec = sec.."0"
		end
		local FixedTime = tostring(min)..":"..tostring(sec)
        print(FixedTime)
end

Video Showcase:
robloxapp-20220807-0900201.wmv (700.7 KB)

  • Note: Sorry Idk how to post embed video here. Im new to DevForums!

That’s it by me. This may not be the best way to handle cooldowns but still, it’s a simple working way! Thanks!

5 Likes

What’s a cooldown system for you? I’m still wondering if it’s for tools or something else.

3 Likes

Did you even read the post? This is about making cooldowns that save even when u leave

3 Likes

It’s a system for like rebirths and kinds of stuff in the game which you want to add a wait time for the player before doing it again and it server sided so exploiters can’t mess with it and ye. I’m not that of a great scripter but it’s a simple one to use, Thanks!

There’s another way to do this, one that disregards a loop in favor of performance.

First, when the cooldown begins, you save the global time, and the reason in a datastore.

local key = "Reason Time" 

key consists of the reason, and the debounce target time.

Key would be something like

local key = "Rebirth "..tostring(os.time()+cooldown) -- add cooldown to os.time total!

Then, the server is locked in, waiting a couple seconds after every request the player makes, to prevent spamming, and once the request is made and the current os.time() is past the key’s time, the request will succeed.

All you’re doing is saving your data in a single string, letting DataStore ensure it’s valid.

The space in front of "Reason " is for a string.find() function, used to separate out the reason, and convert os.time into a number.

1 Like

Hmmm That works too I think but, I tried to keep my script simple for beginner scripters like me! Thanks for your knowledge Thou! And taking about performance, It should matter much by using the render.stepped function I think but, I could be wrong too.

1 Like

You can make it even more performant by using the memory store instead of the data store for my method because they’ll be able to send a request and validate it much quicker than relying on a conventional data store

1 Like

I see. Thank you so much, Ig. And my script is just a simple one!

1 Like

I’m so used to just living on developer forum I just try to contribute everywhere where I can! Jolly good show friend lol

1 Like