Quick answer: Cooldown bugs come from timer state: when a cooldown started, how long it should run, what reductions modify it, and whether client and server agree. Abilities that spam, lock up, or flicker between ready and not ready all trace to that state. Capture each ability's cooldown start time, base duration, applied reduction, and remaining time at the moment of the report and the timing fault becomes clear.

Cooldowns are a promise: press the button now, wait this long, press it again. When that promise breaks, players notice instantly, whether it is an ability that fires twice in a row, a button that stays grey forever, or a skill that flickers between ready and locked. Underneath, every cooldown is a small piece of timer state, a start time and a duration, modified by reductions and sometimes reconciled between client and server. The bugs live in how that state is set, reduced, reset, and synced. This post is about capturing cooldown state so a report about an ability acting up tells you which part of the timing went wrong.

Cooldowns are timer state, and timers drift

A cooldown is usually stored as a start timestamp plus a duration, or as a remaining time that you decrement each frame. Both representations have failure modes. A start timestamp compared against a clock that resets, pauses, or runs at a different rate produces a cooldown that ends too early or never. A decrementing remaining time depends on consistent frame updates, so a hitch, a background tab, or a paused simulation can leave it stuck. The player just sees the ability misbehave, so the report describes the symptom while the cause is which clock the timer trusted.

Reductions complicate this further. Cooldown reduction can apply as a flat subtraction, a percentage, or a haste style rate multiplier, and it can be recomputed when gear changes mid cooldown. If a reduction recalculates the remaining time incorrectly, the cooldown can jump backward to ready or forward to stuck. Capturing both the base duration and the effective duration after reductions lets you separate a reduction bug from a raw timer bug, which are fixed in completely different places in your code.

The cooldown state worth capturing

For each relevant ability, capture the cooldown start time, the base duration, the total reduction applied and how it was applied, the resulting effective duration, and the remaining time at the moment of the report. Also capture the clock value you are comparing against, because a cooldown bug is frequently a clock bug in disguise. With those fields you can compute whether the remaining time is internally consistent: does start plus effective duration minus now actually equal the remaining time the game is showing? When it does not, you have caught the timer lying.

Add the recent ability use events: each cast attempt, whether it was allowed or blocked, and why. An ability that fires twice will show two allowed casts within a window shorter than the cooldown, which points at a check that ran before the cooldown was committed. A button stuck grey will show blocked casts with a remaining time that never reaches zero, pointing at a timer that stopped advancing. The event log turns the static snapshot into a sequence you can reason about, and most cooldown reports resolve the moment you can see that sequence.

Reset and reduction bugs

Many abilities reset cooldowns under conditions: a kill resets a skill, an item refreshes a charge, a passive reduces the timer on a crit. Each reset is a write to the timer, and writes race. If a reset fires on the same frame as a cast, you can end up with a cooldown that is set and then immediately cleared, letting the ability fire again instantly. Capturing the reset events alongside the cast events shows the collision directly, where a reset timestamp lands right between a cast and the cooldown commit, which is impossible to spot from the player description alone.

Reduction bugs are subtler and often appear only with specific gear. A percentage reduction applied twice, or applied to an already reduced value, compounds into a cooldown far shorter than intended, which reads as spammable to players and as broken to your balance. Capturing the base duration, each reduction source, and the final effective duration lets you see compounding immediately: the effective duration is smaller than the base minus the sum of reductions should allow. From there the fix is recomputing reductions from the base each time rather than from the current value.

Client and server desync

In networked games the worst cooldown bugs come from client and server disagreeing. The client predicts the cooldown so the UI feels responsive, while the server is authoritative over whether a cast is allowed. If their clocks or durations differ even slightly, the player sees an ability flicker ready while the server rejects the cast, or sees it greyed while the server would have allowed it. Capturing both the client remaining time and the server remaining time in the same report, with the round trip latency, makes the gap measurable instead of mysterious.

These reports are easy to misread as a single bug when they are really a mismatch between two correct systems. The client might be perfectly consistent and the server perfectly consistent, but their effective durations differ because a reduction was applied on one side and not the other. Capturing both sides side by side is the only way to see that, and it is exactly the data players cannot provide on their own. Once you can see client says ready, server says one second left, you know to reconcile the reduction calculation across the boundary.

Setting it up with Bugnet

Bugnet's in-game report button captures game state automatically, so a cooldown report arrives with the timer state already attached rather than a player typing my dash felt broken. Serialize the relevant abilities into custom fields: per ability cooldown start, base duration, reduction breakdown, effective duration, and remaining time, plus the game clock and recent cast and reset events. When a report says ability fires twice, you open it and the cast event log shows two allowed casts inside one cooldown window, with the reset event that cleared the timer in between.

Occurrence grouping folds repeated cooldown reports into one issue with a count, so a widely abused reset exploit becomes a single prioritized entry instead of a stream of clips. You can filter by the ability id custom field to gather every report touching one skill, and in networked games capture both client and server remaining time so the desync is visible at a glance. Having the timer state, the clock, and the event log in one dashboard turns cooldown triage into reading numbers rather than chasing a feeling players struggle to describe.

Testing cooldown timing

The reliable way to keep cooldowns honest is to test them against the same captured state you collect from reports. Write tests that advance a controlled clock and assert the remaining time tracks correctly through pauses, frame hitches, and gear swaps mid cooldown. Test that resets and reductions never produce a negative or instantly ready timer, and that reductions compute from the base rather than the current value. Because your report format already serializes the timer, any odd report replays directly into a test as a regression case.

For networked titles, add tests that simulate latency and assert the client prediction and server authority converge within a tolerance, so the flicker bugs cannot regress silently. The teams that ship tight cooldowns are the ones who can observe the timer state at any moment and replay it deterministically. When the start time, durations, reductions, and clock are all captured and testable, the ability that fires twice stops being a recurring mystery and becomes a quick, permanent fix.

A cooldown is a clock plus a duration plus reductions. Capture all three and the spam, lock, and flicker reports each name their own fault.