<liclass="nav-item nav-item-this"><ahref="">Crafting system contrib</a></li>
</ul>
<divclass="develop">develop branch</div>
</div>
<divclass="document">
<divclass="documentwrapper">
<divclass="bodywrapper">
<divclass="body"role="main">
<divclass="section"id="crafting-system-contrib">
<h1>Crafting system contrib<aclass="headerlink"href="#crafting-system-contrib"title="Permalink to this headline">¶</a></h1>
<p><em>Contrib by Griatch 2020</em></p>
<divclass="versionadded">
<p><spanclass="versionmodified added">New in version 1.0.</span></p>
</div>
<p>This contrib implements a full Crafting system that can be expanded and modified to fit your game.</p>
<ulclass="simple">
<li><p>See the <aclass="reference external"href="../api/evennia.contrib.crafting.crafting.html">evennia/contrib/crafting/crafting.py API</a> for installation
instructrions.</p></li>
<li><p>See the <aclass="reference external"href="../api/evennia.contrib.crafting.example_recipes.html">sword example</a> for an example of how to design
a crafting tree for crafting a sword from base elements.</p></li>
</ul>
<p>From in-game it uses the new <codeclass="docutils literal notranslate"><spanclass="pre">craft</span></code> command:</p>
2</pre></div></td><tdclass="code"><divclass="highlight"><pre><span></span>> craft bread from flour, eggs, salt, water, yeast using oven, roller
> craft bandage from cloth using scissors
</pre></div>
</td></tr></table></div>
<p>The syntax is <codeclass="docutils literal notranslate"><spanclass="pre">craft</span><spanclass="pre"><recipe></span><spanclass="pre">[from</span><spanclass="pre"><ingredient>,...][</span><spanclass="pre">using</span><spanclass="pre"><tool>,...]</span></code>.</p>
<p>The above example uses the <codeclass="docutils literal notranslate"><spanclass="pre">bread</span></code><em>recipe</em> and requires <codeclass="docutils literal notranslate"><spanclass="pre">flour</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">eggs</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">salt</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">water</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">yeast</span></code> objects
to be in your inventory. These will be consumed as part of crafting (baking) the bread.</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">oven</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">roller</span></code> are “tools” that can be either in your inventory or in your current location (you are not carrying an oven
around with you after all). Tools are <em>not</em> consumed in the crafting. If the added ingredients/tools matches
the requirements of the recipe, a new <codeclass="docutils literal notranslate"><spanclass="pre">bread</span></code> object will appear in the crafter’s inventory.</p>
<p>If you wanted, you could also picture recipes without any consumables:</p>
<p>With a little creativity, the ‘recipe’ concept could be adopted to all sorts of things, like puzzles or
magic systems.</p>
<p>In code, you can craft using the <codeclass="docutils literal notranslate"><spanclass="pre">evennia.contrib.crafting.crafting.craft</span></code> function:</p>
<p>Here, <codeclass="docutils literal notranslate"><spanclass="pre">caller</span></code> is the one doing the crafting and <codeclass="docutils literal notranslate"><spanclass="pre">*inputs</span></code> is any combination of consumables and/or tool
Objects. The system will identify which is which by the <aclass="reference internal"href="../Components/Tags.html"><spanclass="doc">Tags</span></a> on them (see below)
The <codeclass="docutils literal notranslate"><spanclass="pre">result</span></code> is always a list.</p>
<divclass="section"id="adding-new-recipes">
<h2>Adding new recipes<aclass="headerlink"href="#adding-new-recipes"title="Permalink to this headline">¶</a></h2>
<p>A <em>recipe</em> is a class inheriting from <codeclass="docutils literal notranslate"><spanclass="pre">evennia.contrib.crafting.crafting.CraftingRecipe</span></code>. This class
implements the most common form of crafting - that using in-game objects. Each recipe is a separate class
which gets initialized with the consumables/tools you provide.</p>
<p>For the <codeclass="docutils literal notranslate"><spanclass="pre">craft</span></code> command to find your custom recipes, you need to tell Evennia where they are. Add a new
line to your <codeclass="docutils literal notranslate"><spanclass="pre">mygame/server/conf/settings.py</span></code> file, with a list to any new modules with recipe classes.</p>
<p>(You need to reload after adding this). All global-level classes in these modules (whose names don’t start
with underscore) are considered by the system as viable recipes.</p>
<p>Here we assume you created <codeclass="docutils literal notranslate"><spanclass="pre">mygame/world/myrecipes.py</span></code> to match the above example setting:</p>
<spanclass="n">name</span><spanclass="o">=</span><spanclass="s2">"wooden puppet"</span><spanclass="c1"># name to refer to this recipe as</span>
<p>This specifies which tags to look for in the inputs. It defines a <aclass="reference internal"href="../Components/Prototypes.html"><spanclass="doc">Prototype</span></a>
for the recipe to use to spawn the result on the fly (a recipe could spawn more than one result if needed).
Instead of specifying the full prototype-dict, you could also just provide a list of <codeclass="docutils literal notranslate"><spanclass="pre">prototype_key</span></code>s to
create materials and tools to insert into the recipe.</p>
<p>The recipe analyzes inputs, looking for <aclass="reference internal"href="../Components/Tags.html"><spanclass="doc">Tags</span></a> with specific tag-categories.
The tag-category used can be set per-recipe using the (<codeclass="docutils literal notranslate"><spanclass="pre">.consumable_tag_category</span></code> and
<codeclass="docutils literal notranslate"><spanclass="pre">.tool_tag_category</span></code> respectively). The defaults are <codeclass="docutils literal notranslate"><spanclass="pre">crafting_material</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">crafting_tool</span></code>. For
the puppet we need one object with the <codeclass="docutils literal notranslate"><spanclass="pre">wood</span></code> tag and another with the <codeclass="docutils literal notranslate"><spanclass="pre">knife</span></code> tag:</p>
<spanclass="n">wood</span><spanclass="o">=</span><spanclass="n">create_object</span><spanclass="p">(</span><spanclass="n">key</span><spanclass="o">=</span><spanclass="s2">"Piece of wood"</span><spanclass="p">,</span><spanclass="n">tags</span><spanclass="p">[(</span><spanclass="s2">"wood"</span><spanclass="p">,</span><spanclass="s2">"crafting_material"</span><spanclass="p">)])</span>
</pre></div>
</td></tr></table></div>
<p>Note that the objects can have any name, all that matters is the tag/tag-category. This means if a
“bayonet” also had the “knife” crafting tag, it could also be used to carve a puppet. This is also
potentially interesting for use in puzzles and to allow users to experiment and find alternatives to
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">seed</span></code> class-method will create simple dummy objects that fulfills the recipe’s requirements. This
<p>Assuming these objects were put in our inventory, we could now craft using the in-game command:</p>
<divclass="highlight-bash notranslate"><tableclass="highlighttable"><tr><tdclass="linenos"><divclass="linenodiv"><pre>1</pre></div></td><tdclass="code"><divclass="highlight"><pre><span></span>> craft wooden puppet from wood using hobby knife
<p>In the call to <codeclass="docutils literal notranslate"><spanclass="pre">craft</span></code>, the order of <codeclass="docutils literal notranslate"><spanclass="pre">knife</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">wood</span></code> doesn’t matter - the recipe will sort out which
<p>Even without modifying more than the class properties, there are a lot of options to set on
the <codeclass="docutils literal notranslate"><spanclass="pre">CraftingRecipe</span></code> class. Easiest is to refer to the
<aclass="reference external"href="Contribs/evennia.contrib.crafting.crafting.html#evennia.contrib.crafting.crafting.CraftingRecipe">CraftingRecipe api documentation</a>.
For example, you can customize the validation-error messages, decide if the ingredients have
to be exactly right, if a failure still consumes the ingredients or not, and much more.</p>
<p>For even more control you can override hooks in your own class:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">pre_craft</span></code> - this should handle input validation and store its data in <codeclass="docutils literal notranslate"><spanclass="pre">.validated_consumables</span></code> and
<codeclass="docutils literal notranslate"><spanclass="pre">validated_tools</span></code> respectively. On error, this reports the error to the crafter and raises the
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">do_craft</span></code> - this will only be called if <codeclass="docutils literal notranslate"><spanclass="pre">pre_craft</span></code> finished without an exception. This should
return the result of the crafting, by spawnging the prototypes. Or the empty list if crafting
fails for some reason. This is the place to add skill-checks or random chance if you need it
for your game.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">post_craft</span></code> - this receives the result from <codeclass="docutils literal notranslate"><spanclass="pre">do_craft</span></code> and handles error messages and also deletes
any consumables as needed. It may also modify the result before returning it.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">msg</span></code> - this is a wrapper for <codeclass="docutils literal notranslate"><spanclass="pre">self.crafter.msg</span></code> and should be used to send messages to the
crafter. Centralizing this means you can also easily modify the sending style in one place later.</p></li>
</ul>
<p>The class constructor (and the <codeclass="docutils literal notranslate"><spanclass="pre">craft</span></code> access function) takes optional <codeclass="docutils literal notranslate"><spanclass="pre">**kwargs</span></code>. These are passed
into each crafting hook. These are unused by default but could be used to customize things per-call.</p>
<divclass="section"id="skilled-crafters">
<h3>Skilled crafters<aclass="headerlink"href="#skilled-crafters"title="Permalink to this headline">¶</a></h3>
<p>What the crafting system does not have out of the box is a ‘skill’ system - the notion of being able
to fail the craft if you are not skilled enough. Just how skills work is game-dependent, so to add
this you need to make your own recipe parent class and have your recipes inherit from this.</p>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You are not good enough to craft this. Better luck next time!"</span><spanclass="p">)</span>
<p>In this example we introduce a <codeclass="docutils literal notranslate"><spanclass="pre">.difficulty</span></code> for the recipe and makes a ‘dice roll’ to see
if we succed. We would of course make this a lot more immersive and detailed in a full game. In
principle you could customize each recipe just the way you want it, but you could also inherit from
a central parent like this to cut down on work.</p>
<p>The <aclass="reference external"href="../api/evennia.contrib.crafting.example_recipes.html">sword recipe example module</a> also shows an example
of a random skill-check being implemented in a parent and then inherited for multiple use.</p>
</div>
</div>
<divclass="section"id="even-more-customization">
<h2>Even more customization<aclass="headerlink"href="#even-more-customization"title="Permalink to this headline">¶</a></h2>
<p>If you want to build something even more custom (maybe using different input types of validation logic)
you could also look at the <codeclass="docutils literal notranslate"><spanclass="pre">CraftingRecipe</span></code> parent class <codeclass="docutils literal notranslate"><spanclass="pre">CraftingRecipeBase</span></code>.
It implements just the minimum needed to be a recipe and for big changes you may be better off starting
from this rather than the more opinionated <codeclass="docutils literal notranslate"><spanclass="pre">CraftingRecipe</span></code>.</p>