<pclass="last">You are reading an old version of the Evennia documentation. <ahref="https://www.evennia.com/docs/latest/index.html">The latest version is here</a></p>.
<h1>Adding Command Cooldowns<aclass="headerlink"href="#adding-command-cooldowns"title="Permalink to this headline">¶</a></h1>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>> hit goblin with sword
You strike goblin with the sword. It dodges!
> hit goblin with sword
You are off-balance and can't attack again yet.
</pre></div>
</div>
<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. 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.</p>
<p>Such effects are called <em>command cooldowns</em>.</p>
<asideclass="sidebar">
<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. It is based on this howto and implements a <spanclass="xref myst">handler</span> on the object to conveniently manage and store the cooldowns.</p>
</aside>
<p>This howto exemplifies a very resource-efficient way to do cooldowns. A more
‘active’ way is to use asynchronous delays as in the <spanclass="xref myst">Command-Duration howto</span> suggests. The two howto’s might be useful to combine if you want to echo some message to the user after the cooldown ends.</p>
<sectionid="an-efficient-cooldown">
<h2>An efficient cooldown<aclass="headerlink"href="#an-efficient-cooldown"title="Permalink to this headline">¶</a></h2>
<p>The idea is that when a <aclass="reference internal"href="../Components/Commands.html"><spanclass="doc std std-doc">Command</span></a> runs, we store the time it runs. When it next runs, we check again the current time. The command is only allowed to run if enough time passed since now and the previous run. This is a <em>very</em> efficient implementation that only checks on-demand.</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">db</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 an <aclass="reference internal"href="../Components/Attributes.html"><spanclass="doc std std-doc">Attribute</span></a><codeclass="docutils literal notranslate"><spanclass="pre">firestorm_last_cast</span></code> on the <codeclass="docutils literal notranslate"><spanclass="pre">caller.</span></code> It is either <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> (because the spell was never cast before) or an timestamp representing the last time the spell was cast.</p>
<sectionid="non-persistent-cooldown">
<h3>Non-Persistent cooldown<aclass="headerlink"href="#non-persistent-cooldown"title="Permalink to this headline">¶</a></h3>
<p>The above implementation will survive a reload. If you don’t want that, you can just switch to let <codeclass="docutils literal notranslate"><spanclass="pre">firestorm_last_cast</span></code> be a <aclass="reference internal"href="../Components/Attributes.html#in-memory-attributes-nattributes"><spanclass="std std-doc">NAtrribute</span></a> instead. For example:</p>
<p>That is, use <codeclass="docutils literal notranslate"><spanclass="pre">.ndb</span></code> instead of <codeclass="docutils literal notranslate"><spanclass="pre">.db</span></code>. Since a <codeclass="docutils literal notranslate"><spanclass="pre">NAttribute</span></code>s are purely in-memory, they can be faster to read and write to than an <codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code>. So this can be more optimal if your intervals are short and need to change often. The drawback is that they’ll reset if the server reloads.</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 big sword swing, other types of attacks could
be blocked before you can recover your balance.</p>
<pclass="last">You are reading an old version of the Evennia documentation. <ahref="https://www.evennia.com/docs/latest/index.html">The latest version is here</a></p>.