Cooldown Module Feedback

local players = game:GetService('Players')

local cooldown = {} allCooldowns = {}

players.PlayerRemoving:Connect(function(player)
	
	if not allCooldowns[player] then return end
	
	for i, v in pairs(allCooldowns[player]) do
		
		cooldown.Rem(player, i)
	end
	
	allCooldowns[player] = nil
end)

function cooldown.new(player: Player, move: string, duration: number)
	
	allCooldowns[player] = allCooldowns[player] or {}
	
	allCooldowns[player][move] = allCooldowns[player][move] or {}
	
	local cd = allCooldowns[player][move]
	
	cd._start = tick() cd._duration = duration
end

function cooldown.Has(player: Player, move: string)
	
	if not allCooldowns[player] then
		
		return false
	end
	
	for i, v in pairs(allCooldowns[player]) do
		
		if tick() - v._start > v._duration then
			
			cooldown.Rem(player, i)
		end
	end
	
	return not not allCooldowns[player][move]
end

function cooldown.All(player: Player, move: string)
	
	local returns = {}
	
	if not allCooldowns[player] then
		
		return returns
	end
	
	for i, v in pairs(allCooldowns[player]) do

		if tick() - v._start > v._duration then

			cooldown.Rem(player, i) continue
		end
		
		table.insert(returns, i)
	end
	
	return returns
end

function cooldown.Rem(player: Player, move: string)
	
	if not allCooldowns[player] then return end
	
	allCooldowns[player][move] = nil
end

return cooldown

Is there any way I can make this more perfromant/efficient? Is it well scripted? Is the system I’m using the best way to do it? If not, what is a better way of doing this? (Combat game with 30 max players)

2 Likes

Your code looks good and well-structured, and it should perform well under normal circumstances with up to 30 players.

However, because you asked for some improvements, here are some of my suggestions.

  1. Localizing global functions: In Lua, localizing global functions can improve performance. It means storing a reference to a global function/variable in a local variable for faster access. For example, you’re using pairs() and tick() multiple times, it would be more efficient to localize them.
local pairs = pairs
local tick = tick
  1. Avoid unnecessary table operations: In the Has and All functions, you’re iterating through all the cooldowns, even if the specific move you’re interested in isn’t on cooldown. Instead, you could directly access the specific move and check if it’s on cooldown.
  2. Avoid creating tables unnecessarily: In your All function, you’re creating an empty table for returns even if there are no cooldowns for the player. You could instead return an empty table literal if there are no cooldowns for the player.
  3. Use os.clock() instead of tick(): tick() is more accurate than os.clock() but it can be slower due to its precision. If you don’t need that level of precision, os.clock() can be a faster option.
  4. Avoid unnecessary function calls: In the PlayerRemoving event, you’re calling cooldown.Rem() for each cooldown, which is unnecessary because you’re setting allCooldowns[player] to nil anyway. You could just set allCooldowns[player] to nil without calling cooldown.Rem().

Here’s a version of your script with these optimizations:

local players = game:GetService('Players')

local pairs = pairs
local os_clock = os.clock

local cooldown = {}
local allCooldowns = {}

players.PlayerRemoving:Connect(function(player)
	allCooldowns[player] = nil
end)

function cooldown.new(player, move, duration)
	local playerCooldowns = allCooldowns[player] or {}
	playerCooldowns[move] = {_start = os_clock(), _duration = duration}
	allCooldowns[player] = playerCooldowns
end

function cooldown.Has(player, move)
	local playerCooldowns = allCooldowns[player]
	if playerCooldowns then
		local moveCooldown = playerCooldowns[move]
		if moveCooldown and os_clock() - moveCooldown._start > moveCooldown._duration then
			playerCooldowns[move] = nil
			return false
		end
		return moveCooldown ~= nil
	end
	return false
end

function cooldown.All(player)
	local playerCooldowns = allCooldowns[player]
	if playerCooldowns then
		local returns = {}
		for move, cooldown in pairs(playerCooldowns) do
			if os_clock() - cooldown._start > cooldown._duration then
				playerCooldowns[move] = nil
			else
				table.insert(returns, move)
			end
		end
		return returns
	end
	return {}
end

function cooldown.Rem(player, move)
	if allCooldowns[player] then
		allCooldowns[player][move] = nil
	end
end

return cooldown

2 Likes

Thanks for at least replying but I’ve already asked ChatGPT and recognize the answers. I have already drastically improved the module and am thinking about adding a heap system to better expire cooldowns with great performance.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.