<h1>Command Cooldown<aclass="headerlink"href="#command-cooldown"title="Permalink to this headline">¶</a></h1>
<p>Some types of games want to limit how often a command can be run. If a
character casts the spell <em>Firestorm</em>, you might not want them to spam that
command over and over. Or in an advanced combat system, a massive swing may
offer a chance of lots of damage at the cost of not being able to re-do it for
a while. Such effects are called <em>cooldowns</em>.</p>
<p>This page exemplifies a very resource-efficient way to do cooldowns. A more
‘active’ way is to use asynchronous delays as in the <aclass="reference internal"href="Command-Duration.html#blocking-commands"><spanclass="std std-doc">command duration
tutorial</span></a>, the two might be useful to
combine if you want to echo some message to the user after the cooldown ends.</p>
<sectionid="the-cooldown-contrib">
<h2>The Cooldown Contrib<aclass="headerlink"href="#the-cooldown-contrib"title="Permalink to this headline">¶</a></h2>
<p>The <aclass="reference internal"href="../Contribs/Contrib-Cooldowns.html"><spanclass="doc std std-doc">Cooldown contrib</span></a> is a ready-made solution for
command cooldowns you can use. It implements a <em>handler</em> on the object to
conveniently manage and store the cooldowns in a similar manner exemplified in
this tutorial.</p>
</section>
<sectionid="non-persistent-cooldown">
<h2>Non-persistent cooldown<aclass="headerlink"href="#non-persistent-cooldown"title="Permalink to this headline">¶</a></h2>
<p>This little recipe will limit how often a particular command can be run. Since
Commands are class instances, and those are cached in memory, a command
instance will remember things you store on it. So just store the current time
of execution! Next time the command is run, it just needs to check if it has
that time stored, and compare it with the current time to see if a desired
delay has passed.</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in, say, mygame/commands/spells.py</span>
<spanclass="n">last_cast</span><spanclass="o">=</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">ndb</span><spanclass="o">.</span><spanclass="n">firestorm_last_cast</span><spanclass="c1"># could be None</span>
<p>We specify <codeclass="docutils literal notranslate"><spanclass="pre">rate_of_fire</span></code> and then just check for a NAtrribute
<codeclass="docutils literal notranslate"><spanclass="pre">firestorm_last_cast</span></code> and update it if everything works out.</p>
<p>Simple and very effective since everything is just stored in memory. The
drawback of this simple scheme is that it’s non-persistent. If you do
<codeclass="docutils literal notranslate"><spanclass="pre">reload</span></code>, the cache is cleaned and all such ongoing cooldowns will be
forgotten.</p>
</section>
<sectionid="persistent-cooldown">
<h2>Persistent cooldown<aclass="headerlink"href="#persistent-cooldown"title="Permalink to this headline">¶</a></h2>
<p>To make a cooldown <em>persistent</em> (so it survives a server reload), just
use the same technique, but use <aclass="reference internal"href="../Components/Attributes.html"><spanclass="doc std std-doc">Attributes</span></a> (that is, <codeclass="docutils literal notranslate"><spanclass="pre">.db</span></code> instead
of <codeclass="docutils literal notranslate"><spanclass="pre">.ndb</span></code> storage to save the last-cast time.</p>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You cannot cast this spell again yet."</span><spanclass="p">)</span>
<p>So the same as before, we have just hidden away the cooldown checks and you can
reuse this mixin for all your cooldowns.</p>
<sectionid="command-crossover">
<h3>Command crossover<aclass="headerlink"href="#command-crossover"title="Permalink to this headline">¶</a></h3>
<p>This example of cooldown-checking also works <em>between</em> commands. For example,
you can have all fire-related spells store the cooldown with the same
<codeclass="docutils literal notranslate"><spanclass="pre">cooldown_storage_key</span></code> (like <codeclass="docutils literal notranslate"><spanclass="pre">fire_spell_last_used</span></code>). That would mean casting
of <em>Firestorm</em> would block all other fire-related spells for a while.</p>
<p>Similarly, when you take that that big sword swing, other types of attacks could
be blocked before you can recover your balance.</p>