Updated HTML docs

This commit is contained in:
Evennia docbuilder action 2022-08-28 12:07:13 +00:00
parent 3e1506b2c2
commit ec6c28db95
58 changed files with 743 additions and 318 deletions

View file

@ -126,6 +126,9 @@ values on the cache.</p>
buffs after application, they are very useful. The handlers <code class="docutils literal notranslate"><span class="pre">check</span></code>/<code class="docutils literal notranslate"><span class="pre">trigger</span></code> methods utilize some of these getters, while others are just for developer convenience.</p>
<p><code class="docutils literal notranslate"><span class="pre">get(key)</span></code> is the most basic getter. It returns a single buff instance, or <code class="docutils literal notranslate"><span class="pre">None</span></code> if the buff doesnt exist on the handler. It is also the only getter
that returns a single buff instance, rather than a dictionary.</p>
<blockquote>
<div><p><strong>Note</strong>: The handler method <code class="docutils literal notranslate"><span class="pre">has(buff)</span></code> allows you to check if a matching key (if a string) or buff class (if a class) is present on the handler cache, without actually instantiating the buff. You should use this method for basic “is this buff present?” checks.</p>
</div></blockquote>
<p>Group getters, listed below, return a dictionary of values in the format <code class="docutils literal notranslate"><span class="pre">{buffkey:</span> <span class="pre">instance}</span></code>. If you want to iterate over all of these buffs,
you should do so via the <code class="docutils literal notranslate"><span class="pre">dict.values()</span></code> method.</p>
<ul class="simple">
@ -183,6 +186,38 @@ buffs that are reactive to being checked; for example, removing themselves, alte
<blockquote>
<div><p><strong>Note</strong>: You can also trigger relevant buffs at the same time as you check them by ensuring the optional argument <code class="docutils literal notranslate"><span class="pre">trigger</span></code> is True in the <code class="docutils literal notranslate"><span class="pre">check</span></code> method.</p>
</div></blockquote>
<p>Modifiers are calculated additively - that is, all modifiers of the same type are added together before being applied. They are then
applied through the following formula.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">base</span> <span class="o">+</span> <span class="n">total_add</span><span class="p">)</span> <span class="o">/</span> <span class="nb">max</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mf">1.0</span> <span class="o">+</span> <span class="n">total_div</span><span class="p">)</span> <span class="o">*</span> <span class="nb">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mf">1.0</span> <span class="o">+</span> <span class="n">total_mult</span><span class="p">)</span>
</pre></div>
</div>
<section id="multiplicative-buffs-advanced">
<h4>Multiplicative Buffs (Advanced)<a class="headerlink" href="#multiplicative-buffs-advanced" title="Permalink to this headline"></a></h4>
<p>Multiply/divide modifiers in this buff system are additive by default. This means that two +50% modifiers will equal a +100% modifier. But what if you want to apply mods multiplicatively?</p>
<p>First, you should carefully consider if you truly want multiplicative modifiers. Heres some things to consider.</p>
<ul class="simple">
<li><p>They are unintuitive to the average user, as two +50% damage buffs equal +125% instead of +100%.</p></li>
<li><p>They lead to “power explosion”, where stacking buffs in the right way can turn characters into unstoppable forces</p></li>
</ul>
<p>Doing purely-additive multipliers allows you to better control the balance of your game. Conversely, doing multiplicative multipliers enables very fun build-crafting where smart usage of buffs and skills can turn you into a one-shot powerhouse. Each has its place.</p>
<p>The best design practice for multiplicative buffs is to divide your multipliers into “tiers”, where each tier is applied separately. You can easily do this with multiple <code class="docutils literal notranslate"><span class="pre">check</span></code> calls.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">damage</span> <span class="o">=</span> <span class="n">damage</span>
<span class="n">damage</span> <span class="o">=</span> <span class="n">handler</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="n">damage</span><span class="p">,</span> <span class="s1">&#39;damage&#39;</span><span class="p">)</span>
<span class="n">damage</span> <span class="o">=</span> <span class="n">handler</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="n">damage</span><span class="p">,</span> <span class="s1">&#39;empower&#39;</span><span class="p">)</span>
<span class="n">damage</span> <span class="o">=</span> <span class="n">handler</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="n">damage</span><span class="p">,</span> <span class="s1">&#39;radiant&#39;</span><span class="p">)</span>
<span class="n">damage</span> <span class="o">=</span> <span class="n">handler</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="n">damage</span><span class="p">,</span> <span class="s1">&#39;overpower&#39;</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="buff-strength-priority-advanced">
<h4>Buff Strength Priority (Advanced)<a class="headerlink" href="#buff-strength-priority-advanced" title="Permalink to this headline"></a></h4>
<p>Sometimes you only want to apply the strongest modifier to a stat. This is supported by the optional <code class="docutils literal notranslate"><span class="pre">strongest</span></code> bool arg in the handlers check method</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">take_damage</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">source</span><span class="p">,</span> <span class="n">damage</span><span class="p">):</span>
<span class="n">_damage</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">buffs</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="n">damage</span><span class="p">,</span> <span class="s1">&#39;taken_damage&#39;</span><span class="p">,</span> <span class="n">strongest</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">health</span> <span class="o">-=</span> <span class="n">_damage</span>
</pre></div>
</div>
</section>
</section>
<section id="trigger-buffs">
<h3>Trigger Buffs<a class="headerlink" href="#trigger-buffs" title="Permalink to this headline"></a></h3>
@ -255,6 +290,15 @@ and add a context to the mix.</p>
</div>
<p>Apply the buff, take damage, and watch the thorns buff do its work!</p>
</section>
<section id="viewing">
<h3>Viewing<a class="headerlink" href="#viewing" title="Permalink to this headline"></a></h3>
<p>There are two helper methods on the handler that allow you to get useful buff information back.</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">view</span></code>: Returns a dictionary of tuples in the format <code class="docutils literal notranslate"><span class="pre">{buffkey:</span> <span class="pre">(buff.name,</span> <span class="pre">buff.flavor)}</span></code>. Finds all buffs by default, but optionally accepts a dictionary of buffs to filter as well. Useful for basic buff readouts.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">view_modifiers(stat)</span></code>: Returns a nested dictionary of information on modifiers that affect the specified stat. The first layer is the modifier type (<code class="docutils literal notranslate"><span class="pre">add/mult/div</span></code>) and the second layer is the value type (<code class="docutils literal notranslate"><span class="pre">total/strongest</span></code>). Does not return the buffs that cause these modifiers, just the modifiers themselves (akin to using <code class="docutils literal notranslate"><span class="pre">handler.check</span></code> but without actually modifying a value). Useful for stat sheets.</p></li>
</ul>
<p>You can also create your own custom viewing methods through the various handler getters, which will always return the entire buff object.</p>
</section>
</section>
<section id="creating-new-buffs">
<h2>Creating New Buffs<a class="headerlink" href="#creating-new-buffs" title="Permalink to this headline"></a></h2>
@ -266,24 +310,46 @@ However, there are a lot of individual moving parts to a buff. Heres a step-t
<ul class="simple">
<li><p>They have customizable <code class="docutils literal notranslate"><span class="pre">key</span></code>, <code class="docutils literal notranslate"><span class="pre">name</span></code>, and <code class="docutils literal notranslate"><span class="pre">flavor</span></code> strings.</p></li>
<li><p>They have a <code class="docutils literal notranslate"><span class="pre">duration</span></code> (float), and automatically clean-up at the end. Use -1 for infinite duration, and 0 to clean-up immediately. (default: -1)</p></li>
<li><p>They have a <code class="docutils literal notranslate"><span class="pre">tickrate</span></code> (float), and automatically tick if it is greater than 1 (default: 0)</p></li>
<li><p>They can stack, if <code class="docutils literal notranslate"><span class="pre">maxstacks</span></code> (int) is not equal to 1. If its 0, the buff stacks forever. (default: 1)</p></li>
<li><p>They can be <code class="docutils literal notranslate"><span class="pre">unique</span></code> (bool), which determines if they have a unique namespace or not. (default: True)</p></li>
<li><p>They can <code class="docutils literal notranslate"><span class="pre">refresh</span></code> (bool), which resets the duration when stacked or reapplied. (default: True)</p></li>
<li><p>They can be <code class="docutils literal notranslate"><span class="pre">playtime</span></code> (bool) buffs, where duration only counts down during active play. (default: False)</p></li>
</ul>
<p>They also always store some useful mutable information about themselves in the cache:</p>
<p>Buffs also have a few useful properties:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">owner</span></code>: The object this buff is attached to</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ticknum</span></code>: How many ticks the buff has gone through</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">timeleft</span></code>: How much time is remaining on the buff</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ticking</span></code>/<code class="docutils literal notranslate"><span class="pre">stacking</span></code>: If this buff ticks/stacks (checks <code class="docutils literal notranslate"><span class="pre">tickrate</span></code> and <code class="docutils literal notranslate"><span class="pre">maxstacks</span></code>)</p></li>
</ul>
<section id="buff-cache-advanced">
<h4>Buff Cache (Advanced)<a class="headerlink" href="#buff-cache-advanced" title="Permalink to this headline"></a></h4>
<p>Buffs always store some useful mutable information about themselves in the cache (what is stored on the owning objects database attribute). A buffs cache corresponds to <code class="docutils literal notranslate"><span class="pre">{buffkey:</span> <span class="pre">buffcache}</span></code>, where <code class="docutils literal notranslate"><span class="pre">buffcache</span></code> is a dictionary containing <strong>at least</strong> the information below:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">ref</span></code> (class): The buff class path we use to construct the buff.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">start</span></code> (float): The timestamp of when the buff was applied.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">source</span></code> (Object): If specified; this allows you to track who or what applied the buff.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">prevtick</span></code> (float): The timestamp of the previous tick.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">duration</span></code> (float): The cached duration. This can vary from the class duration, depending on if the duration has been modified (paused, extended, shortened, etc).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">tickrate</span></code> (float): The buffs tick rate. Cannot go below 0. Altering the tickrate on an applied buff will not cause it to start ticking if it wasnt ticking before. (<code class="docutils literal notranslate"><span class="pre">pause</span></code> and <code class="docutils literal notranslate"><span class="pre">unpause</span></code> to start/stop ticking on existing buffs)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">stacks</span></code> (int): How many stacks they have.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">paused</span></code> (bool): Paused buffs do not clean up, modify values, tick, or fire any hook methods.</p></li>
</ul>
<p>You can always access the raw cache dictionary through the <code class="docutils literal notranslate"><span class="pre">cache</span></code> attribute on an instanced buff. This is grabbed when you get the buff through
a handler method, so it may not always reflect recent changes youve made, depending on how you structure your buff calls. All of the above
mutable information can be found in this cache, as well as any arbitrary information you pass through the handler <code class="docutils literal notranslate"><span class="pre">add</span></code> method (via <code class="docutils literal notranslate"><span class="pre">to_cache</span></code>).</p>
<p>Sometimes you will want to dynamically update a buffs cache at runtime, such as changing a tickrate in a hook method, or altering a buffs duration.
You can do so by using the interface <code class="docutils literal notranslate"><span class="pre">buff.cachekey</span></code>. As long as the attribute name matches a key in the cache dictionary, it will update the stored
cache with the new value.</p>
<p>If there is no matching key, it will do nothing. If you wish to add a new key to the cache, you must use the <code class="docutils literal notranslate"><span class="pre">buff.update_cache(dict)</span></code> method,
which will properly update the cache (including adding new keys) using the dictionary provided.</p>
<blockquote>
<div><p><strong>Example</strong>: You want to increase a buffs duration by 30 seconds. You use <code class="docutils literal notranslate"><span class="pre">buff.duration</span> <span class="pre">+=</span> <span class="pre">30</span></code>. This new duration is now reflected on both the instance and the cache.</p>
</div></blockquote>
<p>The buff cache can also store arbitrary information. To do so, pass a dictionary through the handler <code class="docutils literal notranslate"><span class="pre">add</span></code> method (<code class="docutils literal notranslate"><span class="pre">handler.add(BuffClass,</span> <span class="pre">to_cache=dict)</span></code>),
set the <code class="docutils literal notranslate"><span class="pre">cache</span></code> dictionary attribute on your buff class, or use the aforementioned <code class="docutils literal notranslate"><span class="pre">buff.update_cache(dict)</span></code> method.</p>
<blockquote>
<div><p><strong>Example</strong>: You store <code class="docutils literal notranslate"><span class="pre">damage</span></code> as a value in the buff cache and use it for your poison buff. You want to increase it over time, so you use <code class="docutils literal notranslate"><span class="pre">buff.damage</span> <span class="pre">+=</span> <span class="pre">1</span></code> in the tick method.</p>
</div></blockquote>
</section>
</section>
<section id="modifiers">
<h3>Modifiers<a class="headerlink" href="#modifiers" title="Permalink to this headline"></a></h3>
@ -292,9 +358,9 @@ mods of a specific stat string and apply their modifications to the value; howev
<p>Mod objects consist of only four values, assigned by the constructor in this order:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">stat</span></code>: The stat you want to modify. When <code class="docutils literal notranslate"><span class="pre">check</span></code> is called, this string is used to find all the mods that are to be collected.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">mod</span></code>: The modifier. Defaults are add and mult. Modifiers are calculated additively, and in standard arithmetic order (see <code class="docutils literal notranslate"><span class="pre">_calculate_mods</span></code> for more)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">mod</span></code>: The modifier. Defaults are <code class="docutils literal notranslate"><span class="pre">add</span></code> (addition/subtraction), <code class="docutils literal notranslate"><span class="pre">mult</span></code> (multiply), and <code class="docutils literal notranslate"><span class="pre">div</span></code> (divide). Modifiers are calculated additively (see <code class="docutils literal notranslate"><span class="pre">_calculate_mods</span></code> for more)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">value</span></code>: How much value the modifier gives regardless of stacks</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">perstack</span></code>: How much value the modifier grants per stack, INCLUDING the first. (default: 0)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">perstack</span></code>: How much value the modifier grants per stack, <strong>INCLUDING</strong> the first. (default: 0)</p></li>
</ul>
<p>The most basic way to add a Mod to a buff is to do so in the buff class definition, like this:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">DamageBuff</span><span class="p">(</span><span class="n">BaseBuff</span><span class="p">):</span>
@ -312,8 +378,7 @@ never permanently change a stat modified by a buff. To remove the modification,
<p>An advanced way to do mods is to generate them when the buff is initialized. This lets you create mods on the fly that are reactive to the game state.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">GeneratedStatBuff</span><span class="p">(</span><span class="n">BaseBuff</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">,</span> <span class="n">buffkey</span><span class="p">,</span> <span class="n">cache</span><span class="o">=</span><span class="p">{})</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">handler</span><span class="p">,</span> <span class="n">buffkey</span><span class="p">,</span> <span class="n">cache</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">at_init</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="c1"># Finds our &quot;modgen&quot; cache value, and generates a mod from it</span>
<span class="n">modgen</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">cache</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;modgen&quot;</span><span class="p">))</span>
<span class="k">if</span> <span class="n">modgen</span><span class="p">:</span>
@ -367,7 +432,7 @@ example, if you want a buff that makes the player take more damage when they are
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">FireSick</span><span class="p">(</span><span class="n">BaseBuff</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">conditional</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">owner</span><span class="o">.</span><span class="n">buffs</span><span class="o">.</span><span class="n">get_by_type</span><span class="p">(</span><span class="n">FireBuff</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">owner</span><span class="o">.</span><span class="n">buffs</span><span class="o">.</span><span class="n">has</span><span class="p">(</span><span class="n">FireBuff</span><span class="p">):</span>
<span class="k">return</span> <span class="kc">True</span>
<span class="k">return</span> <span class="kc">False</span>
</pre></div>
@ -382,6 +447,7 @@ conditionals are checked each tick.</p>
<li><p><code class="docutils literal notranslate"><span class="pre">remove</span></code>/<code class="docutils literal notranslate"><span class="pre">dispel</span></code>: Allows you to remove or dispel the buff. Calls <code class="docutils literal notranslate"><span class="pre">at_remove</span></code>/<code class="docutils literal notranslate"><span class="pre">at_dispel</span></code>, depending on optional arguments.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">pause</span></code>/<code class="docutils literal notranslate"><span class="pre">unpause</span></code>: Pauses and unpauses the buff. Calls <code class="docutils literal notranslate"><span class="pre">at_pause</span></code>/<code class="docutils literal notranslate"><span class="pre">at_unpause</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">reset</span></code>: Resets the buffs start to the current time; same as “refreshing” it.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">alter_cache</span></code>: Updates the buffs cache with the <code class="docutils literal notranslate"><span class="pre">{key:value}</span></code> pairs in the provided dictionary. Can overwrite default values, so be careful!</p></li>
</ul>
</section>
<section id="playtime-duration">
@ -432,14 +498,22 @@ file will be overwritten, so edit that file rather than this one.</small></p>
<li><a class="reference internal" href="#apply-a-buff">Apply a Buff</a></li>
<li><a class="reference internal" href="#get-buffs">Get Buffs</a></li>
<li><a class="reference internal" href="#remove-buffs">Remove Buffs</a></li>
<li><a class="reference internal" href="#check-modifiers">Check Modifiers</a></li>
<li><a class="reference internal" href="#check-modifiers">Check Modifiers</a><ul>
<li><a class="reference internal" href="#multiplicative-buffs-advanced">Multiplicative Buffs (Advanced)</a></li>
<li><a class="reference internal" href="#buff-strength-priority-advanced">Buff Strength Priority (Advanced)</a></li>
</ul>
</li>
<li><a class="reference internal" href="#trigger-buffs">Trigger Buffs</a></li>
<li><a class="reference internal" href="#ticking">Ticking</a></li>
<li><a class="reference internal" href="#context">Context</a></li>
<li><a class="reference internal" href="#viewing">Viewing</a></li>
</ul>
</li>
<li><a class="reference internal" href="#creating-new-buffs">Creating New Buffs</a><ul>
<li><a class="reference internal" href="#basics">Basics</a></li>
<li><a class="reference internal" href="#basics">Basics</a><ul>
<li><a class="reference internal" href="#buff-cache-advanced">Buff Cache (Advanced)</a></li>
</ul>
</li>
<li><a class="reference internal" href="#modifiers">Modifiers</a><ul>
<li><a class="reference internal" href="#generating-mods-advanced">Generating Mods (Advanced)</a></li>
</ul>