Skip to content
Work in progress. These docs describe Spawnite at launch, and some parts are still being built.

Cooldowns

An entity keeps its cooldowns in the CooldownsTrait trait, by key. Each cooldown holds seconds, how long it runs, and left, how long it has left. The step counts every cooldown down and removes each as it ends.

Use the following four functions:

  • defineCooldown(name) defines a key, once, at module scope.
  • startCooldown(entity, { key, seconds }) starts one.
  • isCoolingDown(entity, key) says whether one runs.
  • readCooldown(entity, key) returns it, or undefined.

CooldownStart and Cooldown hold the fields.

defineCooldown(name) returns the key a cooldown runs under, a CooldownKey. A name is letters and digits starting with a lower case letter, such as "bolt". Whatever starts the same key on an entity shares that cooldown, and one name defined in two places is one key:

  • One thing alone. A skill defines its own key, such as defineCooldown("bolt").
  • A group. Three potions each start defineCooldown("drink"), so drinking one holds all three.
  • A global cooldown. Every ability starts globalCooldown for a second beside its own key, and checks both before it casts.
  • A buff or a ground effect. The system that lays a fire patch starts defineCooldown("firePatch") on the caster.
  • An item. The inventory starts item: and the item’s name, or the item’s cooldownGroup.

The engine keeps the keys with a colon, so a game’s key never shares a cooldown with the engine’s by accident. An ability runs its own under ability: and its name, which nameAbilityCooldown("bolt") returns, so a game’s "bolt" and an ability named "bolt" stay apart. defineCooldown refuses "global": import globalCooldown to start or read the abilities’ shared cooldown. A plain string is not a key: the type refuses it.

A cooldown started under a key that already runs keeps the longer of the two, so a short cooldown never cuts a long one.

A cooldown belongs to an entity. For a cooldown the whole world shares, such as a boss’s summon that any player triggers, keep it on the entity that stands for the thing: the boss, or the round.

useCooldown(entity, key) reads a cooldown in a view. It returns the cooldown while one runs and undefined otherwise. left / seconds is the share left, which a button’s rim draws.

Unreal’s ability system keeps a cooldown as a timed effect that grants a tag, and an ability checks the tag: two abilities share a cooldown by sharing the tag. Minecraft’s use_cooldown component has a cooldown_group that items share. A Roblox game keeps a cooldown as a debounce, and a Godot game as a Timer node.

This engine takes Unreal’s and Minecraft’s shape, a key on the entity, because a timer by hand is what every game in this repository wrote for itself, each with its own name and its own way to end.

A bolt that holds for two and a half seconds, and holds every skill for one:

import {
defineCooldown,
globalCooldown,
isCoolingDown,
startCooldown,
} from "@spawnite/engine";
import type { Entity } from "koota";
const boltCooldown = defineCooldown("bolt");
export function castBolt(caster: Entity) {
if (
isCoolingDown(caster, boltCooldown) ||
isCoolingDown(caster, globalCooldown)
)
return;
startCooldown(caster, { key: boltCooldown, seconds: 2.5 });
startCooldown(caster, { key: globalCooldown, seconds: 1 });
// The bolt itself.
}

Both, for a player’s character. CooldownsTrait is a predicted trait: her page counts her cooldowns down on every step as the room does, so her buttons drain smoothly between the room’s sends, and the room’s word corrects her page where the two differ, such as on a cooldown the room started. A system starts a cooldown where the simulation has the say. Every other entity’s cooldowns count down on the room alone, and no page receives them. A page whose room is from before the predicted declaration counts nothing down and shows what the room sends.