profectus-docs/assets/guide_important-concepts_formulas.md.2f6575d6.js

8 lines
9.8 KiB
JavaScript
Raw Normal View History

import{_ as e,c as a,o as s,N as o}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Formulas","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/formulas.md","lastUpdated":1684302845000}'),t={name:"guide/important-concepts/formulas.md"},n=o(`<h1 id="formulas" tabindex="-1">Formulas <a class="header-anchor" href="#formulas" aria-label="Permalink to &quot;Formulas&quot;"></a></h1><p>Profectus utilizes formulas for various features, such as increasing requirements for repeatables and challenges or determining resource gains in conversions. These formulas often need to be inverted or integrated to enable features like buying multiple levels of a repeatable at once or determining when a conversion will increase resource gains. The Formula class can handle these operations, supporting every function Decimal does, while tracking the operations internally.</p><p>For example, a cost function like <code>Decimal.pow(this.amount, 1.05).times(100)</code> can be represented using a Formula: <code>Formula.variable(this.amount).pow(1.05).times(100)</code>.</p><div class="language-ts"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> myRepeatable </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">createRepeatable</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> (</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">requirements</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">createCostRequirement</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> (</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">resource</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> points</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">cost</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> Formula</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">variable</span><span style="color:#A6ACCD;">(myRepeatable</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">amount)</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">pow_base</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">1.05</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">times</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">100</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">))</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">maximize</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">true</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">))</span><span style="color:#89DDFF;">;</span></span></code></pre></div><h2 id="softcaps" tabindex="-1">Softcaps <a class="header-anchor" href="#softcaps" aria-label="Permalink to &quot;Softcaps&quot;"></a></h2><p>Often games incorporate &quot;softcaps&quot; on formulas - that means making the formula step-wise, where everything above a certain value has an additional operation on it that makes it scale differently. Formulas support this via <code>Formula.step</code>, which takes a threshold value and a function to modify the formula appropriately. The function gets a formula that will contain a variable for the amount <em>above</em> the threshold of the original value. Whatever result is returned will then be added back onto the threshold to achieve the softcapped value. Take, for example, a formula <code>Formula.variable().div(10).sqrt()</code> that we want to apply a softcap to - let&#39;s say it should square root everything after 1e100. The softcapped formula will look like this: <code>Formula.variable().div(10).sqrt().step(1e100, f =&gt; f.sqrt())</code>.</p><h2 id="limitations" tabindex="-1">Limitations <a class="header-anchor" href="#limitations" aria-label="Permalink to &quot;Limitations&quot;"></a></h2><h3 id="single-variable" tabindex="-1">Single Variable <a class="header-anchor" href="#single-variable" aria-label="Permalink to &quot;Single Variable&quot;"></a></h3><p>For inverting and integrating, formulas should have a single variable, which serves as the input. Although other parts of the formula can be computed values, they must not be dependent on the input variable for inverting or integrating purposes. Formulas work correctly as long as changing other parts of the formula doesn&#39;t affect the input variable.</p><p>The variable is defined by wrapping the input to the formula in <code>Formula.variable</code>. In the cost requirement example above, the repeatable&#39;s <code>amount</code> is the input to the variable. That means inverting the function would calculate the amount based on the cost, and integrating would be finding the area under the curve where the repeatable&#39;s <code>amount</code> is the x axis and the output of the formula is the y axis.</p><p>If the cost formula had not marked a variable, e.g. <code>Formula.pow(1.05, myRepeatable.amount).times(100)</code> then the formula would not be invertible or integrable, and would throw an error if either operation was tried. While <code>evaluate()</code> will work as expected, passing a value to <code>evaluate()</code> will not, as it will not know what value to override.</p><h3 id="invertibility-and-integrability" tabindex="-1">Invertibility and Integrability <a class="header-anchor" href="#invertibility-and-integrability" aria-label="Permalink to &quot;Invertibility and Integrability&quot;"></a></h3><p>Certain operations may not support inverting or integrating. Functions such as rounding or clamping are non-invertible, while others like super-log are non-integrable. You may only use a single complex operation in addition to add, sub, mult, and div operations. For formulas with two complex operations, a <a href="#custom-formulas">custom formula</a> is required.</p><h3 id="spending-resources" tabindex="-1">Spending Resources <a class="header-anchor" href="#spending-resources" aria-label="Permalink to &quot;Spending Resources&quot;"></a></h3><p>When working with formulas, the <code>spendResources</code> property determines whether the formula needs to be invertible or integrable. The property is used in two utilities: <a href="/api/modules/game/formulas/formulas#calculatemaxaffordable">calculateMaxAffordable</a> and <a href="/api/modules/game/formulas/formulas#calculatecost">calculateCost</a>. These utilities are ultimately employed wherever formulas are used, such as in cost requirements or conversions.</p><p>Spending resources refers to whether max affordability and cost calculations should account for resources spent. If spending resources i