Pulse.Cooldown
Pulse.Cooldown prevents actions from happening too frequently. There are two variants: a single shared cooldown, and a per-entity cooldown where each entity tracks its own timer.
Single cooldown
local cd = Pulse.Cooldown.new(1.0) -- 1 second
cd:ready() -- → bool: has the cooldown expired?
cd:use() -- start the timer
cd:reset() -- mark as ready immediately
cd:set(dur) -- change duration
Pattern:
if cd:ready() then
cd:use()
-- do the action
end
Per-entity cooldown
One timer per entity. Use when each target needs independent rate limiting:
local pcd = Pulse.Cooldown.perEntity(0.5)
pcd:ready(entity) -- is this entity's cooldown expired?
pcd:use(entity) -- start this entity's timer
pcd:reset(entity) -- clear one entity's timer
pcd:purge(fn) -- remove entries where fn(entity) returns true
Pattern:
for _, titan in ipairs(func.GetCachedTitans()) do
if pcd:ready(titan) then
pcd:use(titan)
-- hit titan
end
end
-- Clean up dead titans so the table doesn't grow forever
pcd:purge(function(t) return not t or not t.Parent end)
Always call purge in a periodic loop. Without it, the cooldown table grows indefinitely as entities come and go.
When to use it
- Firing a remote more than once per second per target
- Applying an effect to each enemy at most once every N seconds
- Preventing a keybind from spamming
The debounce N modifier on on InputBegan handlers covers the simple case. Use Pulse.Cooldown when you need programmatic control or per-entity tracking.