§ How to · with Picoo
How to make an ability system with cooldowns in Roblox
By Sametcan Tasgiran, Founder & Developer·Published ·Updated
Abilities are easy to fake and hard to trust: the hotbar is the visible part, but the cooldown is the part players will try to break.
If the cooldown lives on the client, it is a suggestion. Every cooldown, cost and damage number here is enforced on the server.
Hotbar with keybinds
Per-ability key (Q/E/R/F by default), icon, name, and a cooldown veil that sweeps as it recharges.
Six ability kinds
Projectile, dash, AoE slam, beam, buff and heal — a kit that plays at any size, not four flavours of the same nuke.
One balance table
Cooldown, cost, damage, range and duration all live in a single registry ModuleScript.
Mana with regen
Resource bar that refills over time; casting is refused (and the bar flashes) when you cannot afford it.
Mobile
Every slot is a button, so phone players tap what desktop players press.
Themes
fire, water, ice, lightning, shadow, wind, nature — colours, names and icons per element.
Files Picoo ships for this prompt
4 files · 470 lines · ~45s · 2 credit
AbilityConfig (ModuleScript)
THE registry. Add a row and it appears, binds its key and casts — no new code.
53 lines
AbilityServer
Cooldowns, mana, hit detection and damage. The authority.
255 lines
AbilityHUD (ScreenGui)
48 instances in Edit mode — restyle the hotbar without pressing Play.
48 lines
AbilityClient
Keybinds, taps, the cooldown sweep, and the dash impulse after approval.
114 lines
Sample output: ReplicatedStorage.AbilityConfig
-- THE REGISTRY. Everything reads from it: the hotbar builds its slots from
-- these rows, the client binds these keys, the server enforces these numbers.
-- To re-balance, edit a number here — nothing else.
local abilities: { Ability } = {
{ id = "fire_projectile", name = "Fireball", icon = "🔥", key = "Q", kind = "projectile",
cooldown = 1.5, cost = 12, damage = 18, range = 180, power = 95, duration = 0 },
{ id = "fire_dash", name = "Flame Rush", icon = "💨", key = "E", kind = "dash",
cooldown = 4, cost = 15, damage = 0, range = 0, power = 78, duration = 0 },
{ id = "fire_aoe", name = "Meteor Slam", icon = "☄️", key = "R", kind = "aoe",
cooldown = 9, cost = 35, damage = 40, range = 22, power = 0, duration = 0 },
}
-- Server side: the client may ASK to cast; it never decides that a cast was legal.
local readyAt = cooldowns[plr][id]
if readyAt and os.clock() < readyAt then return end
if (resource[plr] or 0) < def.cost then
stateEvent:FireClient(plr, { kind = "denied", id = id, reason = "resource" })
return
endBuilding an ability system with cooldowns in Roblox
An ability system is two problems wearing one costume. The visible one is the hotbar: icons, keybinds, a cooldown that sweeps. The real one is trust — whether the numbers can be edited by the person they are meant to constrain.
Picoo splits it accordingly. ReplicatedStorage.AbilityConfig is the single balance table: id, key, kind, cooldown, cost, damage, range, power, duration. The hotbar builds its slots from it, the client binds its keys from it, and the server enforces it. Re-balancing is editing a number in one file; adding an ability is copying a row.
ServerScriptService.AbilityServer is the authority. It keeps per-player cooldown timestamps and mana, and a cast that arrives early or unaffordable is rejected — the client's sweeping veil is presentation, not permission. There is a flood guard too: no legitimate client casts twice inside 100ms.
Hits use GetPartBoundsInRadius and Raycast rather than .Touched. Touched fires once per touching part, which means a single contact can raise it 5-30 times — with .Touched damage, whether your fireball does 18 or 180 depends on how the character's limbs happened to overlap.
Dash is the one effect applied on the client, after the server approves it, because character physics is client-owned and a server-side velocity write on someone else's character rubber-bands. The pattern generalises: validate where the truth is, act where the ownership is.
Six kinds ship: projectile, dash, AoE slam, beam, buff and heal, themed across fire, water, ice, lightning, shadow, wind and nature. Two to six abilities, keys of your choosing.
See more on the Luau generator, the game builder, or browse the full blog.
Frequently asked
Where do I change damage or cooldown?+
One file: ReplicatedStorage.AbilityConfig. The hotbar, the keybinds and the server all read from that table, so editing a number there is the whole change. Copy a row to add an ability — it binds its key and casts with no new code.
Can a player fake a shorter cooldown?+
No. The client's cooldown veil is display only; the server keeps its own per-player timestamp and silently rejects an early cast. Same for mana — the balance lives server-side and a spammed remote just gets refused.
Why is the dash applied on the client?+
Character physics is client-owned. A server-side velocity write on a player's own character fights their simulation and rubber-bands. The server validates the cast and approves it; the client applies the impulse. Every damaging effect stays server-side.
Does this work on mobile?+
Yes. Each hotbar slot is a button, so a tap casts exactly like the keyboard shortcut. No separate mobile control set to maintain.
How does it detect hits?+
GetPartBoundsInRadius for projectiles and AoE, Raycast for beams — never .Touched. Touched fires once per touching part, so a single contact can raise it 5-30 times and multiply your damage by luck.
Related Picoo prompts
Roblox combat system
5 files · 140 lines · 42 seconds · 1 credit. Drop into your place and press Play.
Roblox boss fight
7 files · 420 lines · 2m 10s · 1 credit. Three phases out of the box, easily extended.
How to prevent exploits in Roblox
4 files · 160 lines · 44 seconds · 1 credit. Drop-in guards + a one-prompt audit of your existing scripts.