Updated HTML docs.

This commit is contained in:
Evennia docbuilder action 2026-01-12 16:26:53 +00:00
parent dbae67275a
commit 76d95c253e
87 changed files with 922 additions and 850 deletions

View file

@ -297,7 +297,7 @@ a given combatant has advantage.</p>
<span class="linenos">37</span>
<span class="linenos">38</span><span class="sd"> &quot;&quot;&quot;</span>
<span class="linenos">39</span> <span class="k">if</span> <span class="n">action_dict</span><span class="p">[</span><span class="s2">&quot;key&quot;</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">action_classes</span><span class="p">:</span>
<span class="linenos">40</span> <span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;This is an unkown action!&quot;</span><span class="p">)</span>
<span class="linenos">40</span> <span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;This is an unknown action!&quot;</span><span class="p">)</span>
<span class="linenos">41</span> <span class="k">return</span>
<span class="linenos">42</span>
<span class="hll"><span class="linenos">43</span> <span class="c1"># store action dict and schedule it to run in dt time</span>
@ -323,7 +323,7 @@ a given combatant has advantage.</p>
<li><p><strong>Line 43</strong>: We simply store the given action dict in the Attribute <code class="docutils literal notranslate"><span class="pre">action_dict</span></code> on the handler. Simple and effective!</p></li>
<li><p><strong>Line 44</strong>: When you enter e.g. <code class="docutils literal notranslate"><span class="pre">attack</span></code>, you expect in this type of combat to see the <code class="docutils literal notranslate"><span class="pre">attack</span></code> command repeat automatically even if you dont enter anything more. To this end we are looking for a new key in action dicts, indicating that this action should <em>repeat</em> with a certain rate (<code class="docutils literal notranslate"><span class="pre">dt</span></code>, given in seconds). We make this compatible with all action dicts by simply assuming its zero if not specified.</p></li>
</ul>
<p><a class="reference internal" href="../../../api/evennia.utils.utils.html#evennia.utils.utils.repeat" title="evennia.utils.utils.repeat"><span class="xref myst py py-func">evennia.utils.utils.repeat</span></a> and <a class="reference internal" href="../../../api/evennia.utils.utils.html#evennia.utils.utils.unrepeat" title="evennia.utils.utils.unrepeat"><span class="xref myst py py-func">evennia.utils.utils.unrepeat</span></a> are convenient shortcuts to the <a class="reference internal" href="../../../Components/TickerHandler.html"><span class="std std-doc">TickerHandler</span></a>. You tell <code class="docutils literal notranslate"><span class="pre">repeat</span></code> to call a given method/function at a certain rate. What you get back is a reference that you can then later use to un-repeat (stop the repeating) later. We make sure to store this reference (we dont care exactly how it looks, just that we need to store it) in <code class="docutils literal notranslate"><span class="pre">the</span> <span class="pre">current_ticket_ref</span></code> Attribute (<strong>Line 26</strong>).</p>
<p><a class="reference internal" href="../../../api/evennia.utils.utils.html#evennia.utils.utils.repeat" title="evennia.utils.utils.repeat"><span class="xref myst py py-func">evennia.utils.utils.repeat</span></a> and <a class="reference internal" href="../../../api/evennia.utils.utils.html#evennia.utils.utils.unrepeat" title="evennia.utils.utils.unrepeat"><span class="xref myst py py-func">evennia.utils.utils.unrepeat</span></a> are convenient shortcuts to the <a class="reference internal" href="../../../Components/TickerHandler.html"><span class="std std-doc">TickerHandler</span></a>. You tell <code class="docutils literal notranslate"><span class="pre">repeat</span></code> to call a given method/function at a certain rate. What you get back is a reference that you can then later use to un-repeat (stop the repeating) later. We make sure to store this reference (we dont care exactly how it looks, just that we need to store it) in the <code class="docutils literal notranslate"><span class="pre">current_ticker_ref</span></code> Attribute (<strong>Line 26</strong>).</p>
<ul class="simple">
<li><p><strong>Line 48</strong>: Whenever we queue a new action (it may replace an existing one) we must make sure to kill (un-repeat) any old repeats that are ongoing. Otherwise we would get old actions firing over and over and new ones starting alongside them.</p></li>
<li><p><strong>Line 49</strong>: If <code class="docutils literal notranslate"><span class="pre">dt</span></code> is set, we call <code class="docutils literal notranslate"><span class="pre">repeat</span></code> to set up a new repeat action at the given rate. We store this new reference. After <code class="docutils literal notranslate"><span class="pre">dt</span></code> seconds, the <code class="docutils literal notranslate"><span class="pre">.execute_next_action</span></code> method will fire (well create that in the next section).</p></li>
@ -340,30 +340,30 @@ a given combatant has advantage.</p>
<span class="linenos"> 7</span> <span class="c1"># ... </span>
<span class="linenos"> 8</span>
<span class="linenos"> 9</span> <span class="k">def</span><span class="w"> </span><span class="nf">execute_next_action</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="linenos">10</span><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="linenos">11</span><span class="sd"> Triggered after a delay by the command</span>
<span class="linenos">12</span><span class="sd"> &quot;&quot;&quot;</span>
<span class="linenos">13</span> <span class="n">combatant</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">obj</span>
<span class="linenos">14</span> <span class="n">action_dict</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">action_dict</span>
<span class="hll"><span class="linenos">15</span> <span class="n">action_class</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">action_classes</span><span class="p">[</span><span class="n">action_dict</span><span class="p">[</span><span class="s2">&quot;key&quot;</span><span class="p">]]</span>
</span><span class="hll"><span class="linenos">16</span> <span class="n">action</span> <span class="o">=</span> <span class="n">action_class</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">combatant</span><span class="p">,</span> <span class="n">action_dict</span><span class="p">)</span>
</span><span class="linenos">17</span>
<span class="hll"><span class="linenos">18</span> <span class="k">if</span> <span class="n">action</span><span class="o">.</span><span class="n">can_use</span><span class="p">():</span>
</span><span class="linenos">19</span> <span class="n">action</span><span class="o">.</span><span class="n">execute</span><span class="p">()</span>
<span class="linenos">20</span> <span class="n">action</span><span class="o">.</span><span class="n">post_execute</span><span class="p">()</span>
<span class="linenos">21</span>
<span class="hll"><span class="linenos">22</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">action_dict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;repeat&quot;</span><span class="p">,</span> <span class="kc">True</span><span class="p">):</span>
</span><span class="linenos">23</span> <span class="c1"># not a repeating action, use the fallback (normally the original attack)</span>
<span class="linenos">24</span> <span class="bp">self</span><span class="o">.</span><span class="n">action_dict</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">fallback_action_dict</span>
<span class="linenos">25</span> <span class="bp">self</span><span class="o">.</span><span class="n">queue_action</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">fallback_action_dict</span><span class="p">)</span>
<span class="linenos">26</span>
<span class="hll"><span class="linenos">27</span> <span class="bp">self</span><span class="o">.</span><span class="n">check_stop_combat</span><span class="p">()</span>
<span class="linenos">10</span><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="linenos">11</span><span class="sd"> Triggered after a delay by the command</span>
<span class="linenos">12</span><span class="sd"> &quot;&quot;&quot;</span>
<span class="linenos">13</span> <span class="n">combatant</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">obj</span>
<span class="linenos">14</span> <span class="n">action_dict</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">action_dict</span>
<span class="hll"><span class="linenos">15</span> <span class="n">action_class</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">action_classes</span><span class="p">[</span><span class="n">action_dict</span><span class="p">[</span><span class="s2">&quot;key&quot;</span><span class="p">]]</span>
</span><span class="hll"><span class="linenos">16</span> <span class="n">action</span> <span class="o">=</span> <span class="n">action_class</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">combatant</span><span class="p">,</span> <span class="n">action_dict</span><span class="p">)</span>
</span><span class="linenos">17</span>
<span class="hll"><span class="linenos">18</span> <span class="k">if</span> <span class="n">action</span><span class="o">.</span><span class="n">can_use</span><span class="p">():</span>
</span><span class="linenos">19</span> <span class="n">action</span><span class="o">.</span><span class="n">execute</span><span class="p">()</span>
<span class="linenos">20</span> <span class="n">action</span><span class="o">.</span><span class="n">post_execute</span><span class="p">()</span>
<span class="linenos">21</span>
<span class="hll"><span class="linenos">22</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">action_dict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;repeat&quot;</span><span class="p">,</span> <span class="kc">True</span><span class="p">):</span>
</span><span class="linenos">23</span> <span class="c1"># not a repeating action, use the fallback (normally the original attack)</span>
<span class="linenos">24</span> <span class="bp">self</span><span class="o">.</span><span class="n">action_dict</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">fallback_action_dict</span>
<span class="linenos">25</span> <span class="bp">self</span><span class="o">.</span><span class="n">queue_action</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">fallback_action_dict</span><span class="p">)</span>
<span class="linenos">26</span>
<span class="hll"><span class="linenos">27</span> <span class="bp">self</span><span class="o">.</span><span class="n">check_stop_combat</span><span class="p">()</span>
</span></pre></div>
</div>
<p>This is the method called after <code class="docutils literal notranslate"><span class="pre">dt</span></code> seconds in <code class="docutils literal notranslate"><span class="pre">queue_action</span></code>.</p>
<ul class="simple">
<li><p><strong>Line 5</strong>: We defined a fallback action. This is used after a one-time action (one that should not repeat) has completed.</p></li>
<li><p><strong>Line 15</strong>: We take the <code class="docutils literal notranslate"><span class="pre">'key'</span></code> from the <code class="docutils literal notranslate"><span class="pre">action-dict</span></code> and use the <code class="docutils literal notranslate"><span class="pre">action_classes</span></code> mapping to get an action class (e.g. <code class="docutils literal notranslate"><span class="pre">ACtionAttack</span></code> we defined <a class="reference internal" href="Beginner-Tutorial-Combat-Base.html#attack-action"><span class="std std-ref">here</span></a>).</p></li>
<li><p><strong>Line 15</strong>: We take the <code class="docutils literal notranslate"><span class="pre">'key'</span></code> from the <code class="docutils literal notranslate"><span class="pre">action_dict</span></code> and use the <code class="docutils literal notranslate"><span class="pre">action_classes</span></code> mapping to get an action class (e.g. <code class="docutils literal notranslate"><span class="pre">ActionAttack</span></code> we defined <a class="reference internal" href="Beginner-Tutorial-Combat-Base.html#attack-action"><span class="std std-ref">here</span></a>).</p></li>
<li><p><strong>Line 16</strong>: Here we initialize the action class with the actual current data - the combatant and the <code class="docutils literal notranslate"><span class="pre">action_dict</span></code>. This calls the <code class="docutils literal notranslate"><span class="pre">__init__</span></code> method on the class and makes the action ready to use.</p></li>
</ul>
<aside class="sidebar">
@ -402,7 +402,7 @@ a given combatant has advantage.</p>
<span class="hll"><span class="linenos">18</span> <span class="n">enemies</span> <span class="o">=</span> <span class="p">[</span><span class="n">comb</span> <span class="k">for</span> <span class="n">comb</span> <span class="ow">in</span> <span class="n">enemies</span> <span class="k">if</span> <span class="n">comb</span><span class="o">.</span><span class="n">hp</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">comb</span><span class="o">.</span><span class="n">location</span> <span class="o">==</span> <span class="n">location</span><span class="p">]</span>
</span><span class="hll"><span class="linenos">19</span>
</span><span class="linenos">20</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">allies</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">enemies</span><span class="p">:</span>
<span class="linenos">21</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;The combat is over. Noone stands.&quot;</span><span class="p">,</span> <span class="n">broadcast</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="linenos">21</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;The combat is over. No one stands.&quot;</span><span class="p">,</span> <span class="n">broadcast</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="linenos">22</span> <span class="bp">self</span><span class="o">.</span><span class="n">stop_combat</span><span class="p">()</span>
<span class="linenos">23</span> <span class="k">return</span>
<span class="linenos">24</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">allies</span><span class="p">:</span>
@ -421,7 +421,7 @@ a given combatant has advantage.</p>
<li><p><strong>Line 12</strong>: With our <code class="docutils literal notranslate"><span class="pre">.get_sides()</span></code> method we can easily get the two sides of the conflict.</p></li>
<li><p><strong>Lines 18, 19</strong>: We get everyone still alive <em>and still in the same room</em>. The latter condition is important in case we move away from the battle - you cant hit your enemy from another room.</p></li>
</ul>
<p>In the <code class="docutils literal notranslate"><span class="pre">stop_method</span></code> well need to do a bunch of cleanup. Well hold off on implementing this until we have the Commands written out. Read on.</p>
<p>In the <code class="docutils literal notranslate"><span class="pre">stop_combat</span></code> method well need to do a bunch of cleanup. Well hold off on implementing this until we have the Commands written out. Read on.</p>
</section>
</section>
<section id="commands">
@ -448,7 +448,7 @@ a given combatant has advantage.</p>
<span class="linenos"> 9</span>
<span class="linenos">10</span><span class="k">class</span><span class="w"> </span><span class="nc">_BaseTwitchCombatCommand</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="linenos">11</span><span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="linenos">12</span><span class="sd"> Parent class for all twitch-combat commnads.</span>
<span class="linenos">12</span><span class="sd"> Parent class for all twitch-combat commands.</span>
<span class="linenos">13</span>
<span class="linenos">14</span><span class="sd"> &quot;&quot;&quot;</span>
<span class="linenos">15</span>
@ -668,7 +668,7 @@ You<span class="w"> </span><span class="o">(</span>Wounded<span class="o">)</spa
<span class="c1"># something like `boost str target`</span>
<span class="n">target</span> <span class="o">=</span> <span class="n">recipient</span> <span class="k">if</span> <span class="n">advantage</span> <span class="k">else</span> <span class="s2">&quot;me&quot;</span>
<span class="n">recipient</span> <span class="o">=</span> <span class="s2">&quot;me&quot;</span> <span class="k">if</span> <span class="n">advantage</span> <span class="k">else</span> <span class="n">recipient</span>
<span class="n">we</span> <span class="n">still</span> <span class="n">have</span> <span class="kc">None</span><span class="p">:</span><span class="n">s</span> <span class="n">at</span> <span class="n">this</span> <span class="n">point</span><span class="p">,</span> <span class="n">we</span> <span class="n">can</span><span class="s1">&#39;t continue</span>
<span class="c1"># if any values are still None at this point, we can&#39;t continue</span>
<span class="k">if</span> <span class="kc">None</span> <span class="ow">in</span> <span class="p">(</span><span class="n">stunt_type</span><span class="p">,</span> <span class="n">recipient</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Both ability, recipient and target of stunt must be given.&quot;</span><span class="p">)</span>
<span class="k">raise</span> <span class="n">InterruptCommand</span><span class="p">()</span>
@ -704,7 +704,7 @@ You<span class="w"> </span><span class="o">(</span>Wounded<span class="o">)</spa
</pre></div>
</div>
<p>This looks much longer, but that is only because the stunt command should understand many different input structures depending on if you are trying to create a advantage or disadvantage, and if an ally or enemy should receive the effect of the stunt.</p>
<p>This looks much longer, but that is only because the stunt command should understand many different input structures depending on if you are trying to create an advantage or disadvantage, and if an ally or enemy should receive the effect of the stunt.</p>
<p>Note the <code class="docutils literal notranslate"><span class="pre">enums.ABILITY_REVERSE_MAP</span></code> (created in the <a class="reference internal" href="Beginner-Tutorial-Utilities.html"><span class="std std-doc">Utilities lesson</span></a>) being useful to convert your input of str into <code class="docutils literal notranslate"><span class="pre">Ability.STR</span></code> needed by the action dict.</p>
<p>Once weve sorted out the string parsing, the <code class="docutils literal notranslate"><span class="pre">func</span></code> is simple - we find the target and recipient and use them to build the needed action-dict to queue.</p>
</section>
@ -777,8 +777,8 @@ You<span class="w"> </span><span class="o">(</span>Wounded<span class="o">)</spa
<span class="k">class</span><span class="w"> </span><span class="nc">CmdWield</span><span class="p">(</span><span class="n">_BaseTwitchCombatCommand</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Wield a weapon or spell-rune. You will the wield the item, </span>
<span class="sd"> swapping with any other item(s) you were wielded before.</span>
<span class="sd"> Wield a weapon or spell-rune. You wield the item,</span>
<span class="sd"> swapping with any other item(s) you were wielding before.</span>
<span class="sd"> Usage:</span>
<span class="sd"> wield &lt;weapon or spell&gt;</span>
@ -906,7 +906,7 @@ You<span class="w"> </span><span class="o">(</span>Wounded<span class="o">)</spa
<span class="c1"># ...</span>
<span class="k">class</span><span class="w"> </span><span class="nc">TestEvAdventureTwitchCombat</span><span class="p">(</span><span class="n">EvenniaCommandTestMixin</span><span class="p">)</span>
<span class="k">class</span><span class="w"> </span><span class="nc">TestEvAdventureTwitchCombat</span><span class="p">(</span><span class="n">EvenniaCommandTestMixin</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="nf">setUp</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">combathandler</span> <span class="o">=</span> <span class="p">(</span>
@ -917,12 +917,12 @@ You<span class="w"> </span><span class="o">(</span>Wounded<span class="o">)</spa
<span class="nd">@patch</span><span class="p">(</span><span class="s2">&quot;evadventure.combat_twitch.unrepeat&quot;</span><span class="p">,</span> <span class="n">new</span><span class="o">=</span><span class="n">Mock</span><span class="p">())</span>
<span class="nd">@patch</span><span class="p">(</span><span class="s2">&quot;evadventure.combat_twitch.repeat&quot;</span><span class="p">,</span> <span class="n">new</span><span class="o">=</span><span class="n">Mock</span><span class="p">())</span>
<span class="k">def</span><span class="w"> </span><span class="nf">test_hold_command</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="n">combat_twitch</span><span class="p">,</span> <span class="n">CmdHold</span><span class="p">(),</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;You hold back, doing nothing&quot;</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="n">combat_twitch</span><span class="p">,</span> <span class="n">CmdHold</span><span class="p">(),</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;You hold back, doing nothing.&quot;</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">combathandler</span><span class="o">.</span><span class="n">action_dict</span><span class="p">,</span> <span class="p">{</span><span class="s2">&quot;key&quot;</span><span class="p">:</span> <span class="s2">&quot;hold&quot;</span><span class="p">})</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">EvenniaCommandTestMixin</span></code> as a few default objects, including <code class="docutils literal notranslate"><span class="pre">self.char1</span></code>, which we make use of here.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">EvenniaCommandTestMixin</span></code> has a few default objects, including <code class="docutils literal notranslate"><span class="pre">self.char1</span></code>, which we make use of here.</p>
<p>The two <code class="docutils literal notranslate"><span class="pre">&#64;patch</span></code> lines are Python <a class="reference external" href="https://realpython.com/primer-on-python-decorators/">decorators</a> that patch the <code class="docutils literal notranslate"><span class="pre">test_hold_command</span></code> method. What they do is basically saying “in the following method, whenever any code tries to access <code class="docutils literal notranslate"><span class="pre">evadventure.combat_twitch.un/repeat</span></code>, just return a Mocked object instead”.</p>
<p>We do this patching as an easy way to avoid creating timers in the unit test - these timers would finish after the test finished (which includes deleting its objects) and thus fail.</p>
<p>Inside the test, we use the <code class="docutils literal notranslate"><span class="pre">self.call()</span></code> method to explicitly fire the Command (with no argument) and check that the output is what we expect. Lastly we check that the combathandler is set up correctly, having stored the action-dict on itself.</p>