Cooldowns

A lot of games these days have embraced a real-time style of fighting involving powers or other special abilities that, once activated, can’t be used again for a specific amount of time. They have to “cool down”, so to speak, leading the waiting period to be called a cooldown. FPS, RTS, MOBA…this particular style of play transcends genres. It’s not only for battles, either. Some mobile games have taken it to the extreme, putting even basic gameplay on a cooldown timer. Of course, if you don’t mind dropping a little cash, they’ll gladly let you cut out the waiting.

A bit of history

The whole idea of cooldowns in gaming probably goes back to role-playing games. In RPGs, combat typically works by rounds. Newer editions of D&D, for example, use rounds of 6 seconds. A few longer actions can be done, resulting in your “turn” being skipped in the following round, but the general ratio is one action to one round. This creates a turn-based style of play that usually isn’t time-sensitive. (It can be, though. Games such as Baldur’s Gate turn this system into one supporting real-time action.)

A more fast-paced, interactive style comes from the “Active Time” battles in some of the Final Fantasy games. This might be considered the beginning of cooldowns, at least in popular gaming. Here, a character’s turn comes around after a set period of time, which can change based on items, spells, or a speed stat. Slower characters take longer to fill up their “charge time”, and Haste spells make it fill faster.

Over the past couple of decades, developers have refined and evolved this system into the one we have today. Along the way, some of them have largely discarded the suspension of disbelief and story reasoning for cooldowns. Especially in competitive gaming, they’re nothing more than another mechanic like DPS or area of effect. But they are pretty much everywhere these days, in whatever guise, because they serve a useful purpose: forcing resource management based on time.

Using cooldowns

At the most basic level, that’s what cooldowns are all about. They’re there for game balance. Requiring you to wait between uses of your “ultimate” ability means you have to learn to use the smaller ones. Limiting healing powers to one use every X seconds gives players a reason to back off from a bigger foe; it also frees you from the need to place (and plan for) disposable items like potions. Conversely, if you use cooldowns extensively in your game, you have to make sure that the scenarios where they come into play are written for them.

On the programming side, cooldown timers are fairly easy to implement. Most game engines have some sort of timer functionality, and that’s a good base to build from. When an ability is used, set the timer to the cooldown period and start it. When it signals that it’s finished, that means that the ability is ready to go again.

But to better illustrate how they work—and because not every game engine likes having dozens or hundreds of timers running at once—here’s a different approach. We’ll start with a kind of “cooldown object”:

class CooldownAbility {
    // ...

    void activateAbility();

    void updateTimer(int timeDelta);

    int defaultCooldown;
    int cooldown;
    int coolingTime;
    bool isCoolingDown;
};

(This is C++-like pseudocode made to illustrate the point. I wouldn’t write a real game like this.)

activateAbility should be self-explanatory. It would probably have a structure like this:

void activateAbility() {
    // do flashy stuff
    // ...

    // start the cooldown period
    coolingTime = 0;
    isCoolingDown = true;
}

The updateTimer method here does just that. Each time it’s called, it adds the timeDelta value (this should be the time since the last update) to the coolingTime, and checks to see if it reached the cooldown limit:

void updateTimer(int timeDelta) {
    coolingTime += timeDelta;

    isCoolingDown = (coolingTime < coolDown);
}

Most games have a nice timer built right in: the game loop. And there’s likely already code in there for keeping track of the time since the last run of the loop. It’s simple enough to hook that in to a kind of “cooldown manager”, which runs through all of the “unusable” abilities and updates the time since last use. That might look something like this:

for (auto&& cd : allCooldowns) {
    cd.updateTimer(timeThisFrame);

    if (!cd.isCoolingDown) {
        // tell the game that the ability is ready
    }
}

(Also, the reason I gave this object both a cooldown and a defaultCooldown is so that, if we wanted, we could implement power-ups that reduce cooldown or penalties that increase it.)

Implementing this same thing in an entity-component engine can work almost the same way. Abilities could be entities with cooldown components, and you could add in a system that does the updating, cooldown reduction/increase, etc.

For a certain style of game, timed resource use makes sense. It makes gameplay better. It opens up new tactics, new strategies, especially in multiplayer gaming. And while it takes a lot of design effort to keep a cooldown-based game balanced and fun, the code isn’t that hard at all. That’s especially good news for indie devs, because they get more time to spend on the balancing part.

Leave a Reply

Your email address will not be published. Required fields are marked *