evennia/docs/6.x/Contribs/Contrib-Crafting.html
2026-02-15 19:06:04 +01:00

452 lines
No EOL
34 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Crafting system &#8212; Evennia latest documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=d75fae25" />
<link rel="stylesheet" type="text/css" href="../_static/nature.css?v=279e0f84" />
<link rel="stylesheet" type="text/css" href="../_static/custom.css?v=e4a91a55" />
<script src="../_static/documentation_options.js?v=c6e86fd7"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Gendersub" href="Contrib-Gendersub.html" />
<link rel="prev" title="Cooldowns" href="Contrib-Cooldowns.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="Contrib-Gendersub.html" title="Gendersub"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Contrib-Cooldowns.html" title="Cooldowns"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="Contribs-Overview.html" accesskey="U">Contribs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Crafting system</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="crafting-system">
<h1>Crafting system<a class="headerlink" href="#crafting-system" title="Link to this heading"></a></h1>
<p>Contribution by Griatch 2020</p>
<p>This implements a full crafting system. The principle is that of a recipe,
where you combine items (tagged as ingredients) create something new. The recipe can also
require certain (non-consumed) tools. An example would be to use the bread recipe to
combine flour, water and yeast with an oven to bake a loaf of bread.</p>
<p>The recipe process can be understood like this:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>ingredient(s) + tool(s) + recipe -&gt; object(s)
</pre></div>
</div>
<p>Here, ingredients are consumed by the crafting process, whereas tools are
necessary for the process but will not be destroyed by it.</p>
<p>The included <code class="docutils literal notranslate"><span class="pre">craft</span></code> command works like this:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>craft &lt;recipe&gt; [from &lt;ingredient&gt;,...] [using &lt;tool&gt;, ...]
</pre></div>
</div>
<section id="examples">
<h2>Examples<a class="headerlink" href="#examples" title="Link to this heading"></a></h2>
<p>Using the <code class="docutils literal notranslate"><span class="pre">craft</span></code> command:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>craft toy car from plank, wooden wheels, nails using saw, hammer
</pre></div>
</div>
<p>A recipe does not have to use tools or even multiple ingredients:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>snow + snowball_recipe -&gt; snowball
</pre></div>
</div>
<p>Conversely one could also imagine using tools without consumables, like</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>spell_book + wand + fireball_recipe -&gt; fireball
</pre></div>
</div>
<p>The system is generic enough to be used also for adventure-like puzzles (but
one would need to change the command and determine the recipe on based on what
is being combined instead):</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>stick + string + hook -&gt; makeshift_fishing_rod
makeshift_fishing_rod + storm_drain -&gt; key
</pre></div>
</div>
<p>See the <a class="reference internal" href="../api/evennia.contrib.game_systems.crafting.example_recipes.html#evennia-contrib-game-systems-crafting-example-recipes"><span class="std std-ref">sword example</span></a> for an example
of how to design a recipe tree for crafting a sword from base elements.</p>
</section>
<section id="installation-and-usage">
<h2>Installation and Usage<a class="headerlink" href="#installation-and-usage" title="Link to this heading"></a></h2>
<p>Import the <code class="docutils literal notranslate"><span class="pre">CmdCraft</span></code> command from evennia/contrib/crafting/crafting.py and
add it to your Character cmdset. Reload and the <code class="docutils literal notranslate"><span class="pre">craft</span></code> command will be
available to you:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>craft &lt;recipe&gt; [from &lt;ingredient&gt;,...] [using &lt;tool&gt;, ...]
</pre></div>
</div>
<p>In code, you can craft using the
<code class="docutils literal notranslate"><span class="pre">evennia.contrib.game_systems.crafting.craft</span></code> function:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">evennia.contrib.game_systems.crafting</span><span class="w"> </span><span class="kn">import</span> <span class="n">craft</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">craft</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">&quot;recipename&quot;</span><span class="p">,</span> <span class="o">*</span><span class="n">inputs</span><span class="p">)</span>
</pre></div>
</div>
<p>Here, <code class="docutils literal notranslate"><span class="pre">caller</span></code> is the one doing the crafting and <code class="docutils literal notranslate"><span class="pre">*inputs</span></code> is any combination of
consumables and/or tool Objects. The system will identify which is which by the
<a class="reference internal" href="../Components/Tags.html"><span class="std std-doc">Tags</span></a> on them (see below) The <code class="docutils literal notranslate"><span class="pre">result</span></code> is always a list.</p>
<p>To use crafting you need recipes. Add a new variable to
<code class="docutils literal notranslate"><span class="pre">mygame/server/conf/settings.py</span></code>:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>CRAFT_RECIPE_MODULES = [&#39;world.recipes&#39;]
</pre></div>
</div>
<p>All top-level classes in these modules (whose name does not start with <code class="docutils literal notranslate"><span class="pre">_</span></code>) will
be parsed by Evennia as recipes to make available to the crafting system. Using
the above example, create <code class="docutils literal notranslate"><span class="pre">mygame/world/recipes.py</span></code> and add your recipies in
there:</p>
<p>A quick example (read on for more details):</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="kn">from</span><span class="w"> </span><span class="nn">evennia.contrib.game_systems.crafting</span><span class="w"> </span><span class="kn">import</span> <span class="n">CraftingRecipe</span><span class="p">,</span> <span class="n">CraftingValidationError</span>
<span class="k">class</span><span class="w"> </span><span class="nc">RecipeBread</span><span class="p">(</span><span class="n">CraftingRecipe</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Bread is good for making sandwitches!</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">name</span> <span class="o">=</span> <span class="s2">&quot;bread&quot;</span> <span class="c1"># used to identify this recipe in &#39;craft&#39; command</span>
<span class="n">tool_tags</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;bowl&quot;</span><span class="p">,</span> <span class="s2">&quot;oven&quot;</span><span class="p">]</span>
<span class="n">consumable_tags</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;flour&quot;</span><span class="p">,</span> <span class="s2">&quot;salt&quot;</span><span class="p">,</span> <span class="s2">&quot;yeast&quot;</span><span class="p">,</span> <span class="s2">&quot;water&quot;</span><span class="p">]</span>
<span class="n">output_prototypes</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">{</span><span class="s2">&quot;key&quot;</span><span class="p">:</span> <span class="s2">&quot;Loaf of Bread&quot;</span><span class="p">,</span>
<span class="s2">&quot;aliases&quot;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&quot;bread&quot;</span><span class="p">],</span>
<span class="s2">&quot;desc&quot;</span><span class="p">:</span> <span class="s2">&quot;A nice load of bread.&quot;</span><span class="p">,</span>
<span class="s2">&quot;typeclass&quot;</span><span class="p">:</span> <span class="s2">&quot;typeclasses.objects.Food&quot;</span><span class="p">,</span> <span class="c1"># assuming this exists</span>
<span class="s2">&quot;tags&quot;</span><span class="p">:</span> <span class="p">[(</span><span class="s2">&quot;bread&quot;</span><span class="p">,</span> <span class="s2">&quot;crafting_material&quot;</span><span class="p">)]</span> <span class="c1"># this makes it usable in other recipes ...</span>
<span class="p">}</span>
<span class="p">]</span>
<span class="k">def</span><span class="w"> </span><span class="nf">pre_craft</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="c1"># validates inputs etc. Raise `CraftingValidationError` if fails</span>
<span class="k">def</span><span class="w"> </span><span class="nf">do_craft</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="c1"># performs the craft - report errors directly to user and return None (if</span>
<span class="c1"># failed) and the created object(s) if successful.</span>
<span class="k">def</span><span class="w"> </span><span class="nf">post_craft</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">result</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="c1"># any post-crafting effects. Always called, even if do_craft failed (the</span>
<span class="c1"># result would be None then)</span>
</pre></div>
</div>
</section>
<section id="adding-new-recipes">
<h2>Adding new recipes<a class="headerlink" href="#adding-new-recipes" title="Link to this heading"></a></h2>
<p>A <em>recipe</em> is a class inheriting from
<code class="docutils literal notranslate"><span class="pre">evennia.contrib.game_systems.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 <code class="docutils literal notranslate"><span class="pre">craft</span></code> command to find your custom recipes, you need to tell Evennia
where they are. Add a new line to your <code class="docutils literal notranslate"><span class="pre">mygame/server/conf/settings.py</span></code> file,
with a list to any new modules with recipe classes.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">CRAFT_RECIPE_MODULES</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;world.myrecipes&quot;</span><span class="p">]</span>
</pre></div>
</div>
<p>(You need to reload after adding this). All global-level classes in these
modules (whose names dont start with underscore) are considered by the system
as viable recipes.</p>
<p>Here we assume you created <code class="docutils literal notranslate"><span class="pre">mygame/world/myrecipes.py</span></code> to match the above
example setting:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/world/myrecipes.py</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">evennia.contrib.game_systems.crafting</span><span class="w"> </span><span class="kn">import</span> <span class="n">CraftingRecipe</span>
<span class="k">class</span><span class="w"> </span><span class="nc">WoodenPuppetRecipe</span><span class="p">(</span><span class="n">CraftingRecipe</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;A puppet&quot;&quot;&quot;</span><span class="s2">&quot;</span>
<span class="n">name</span> <span class="o">=</span> <span class="s2">&quot;wooden puppet&quot;</span> <span class="c1"># name to refer to this recipe as</span>
<span class="n">tool_tags</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;knife&quot;</span><span class="p">]</span>
<span class="n">consumable_tags</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;wood&quot;</span><span class="p">]</span>
<span class="n">output_prototypes</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">{</span><span class="s2">&quot;key&quot;</span><span class="p">:</span> <span class="s2">&quot;A carved wooden doll&quot;</span><span class="p">,</span>
<span class="s2">&quot;typeclass&quot;</span><span class="p">:</span> <span class="s2">&quot;typeclasses.objects.decorations.Toys&quot;</span><span class="p">,</span>
<span class="s2">&quot;desc&quot;</span><span class="p">:</span> <span class="s2">&quot;A small carved doll&quot;</span><span class="p">}</span>
<span class="p">]</span>
</pre></div>
</div>
<p>This specifies which tags to look for in the inputs. It defines a
<a class="reference internal" href="../Components/Prototypes.html"><span class="std std-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 <code class="docutils literal notranslate"><span class="pre">prototype_key</span></code>s to existing prototypes you have.</p>
<p>After reloading the server, this recipe would now be available to use. To try it
we should create materials and tools to insert into the recipe.</p>
<p>The recipe analyzes inputs, looking for <a class="reference internal" href="../Components/Tags.html"><span class="std std-doc">Tags</span></a> with
specific tag-categories. The tag-category used can be set per-recipe using the
(<code class="docutils literal notranslate"><span class="pre">.consumable_tag_category</span></code> and <code class="docutils literal notranslate"><span class="pre">.tool_tag_category</span></code> respectively). The defaults
are <code class="docutils literal notranslate"><span class="pre">crafting_material</span></code> and <code class="docutils literal notranslate"><span class="pre">crafting_tool</span></code>. For
the puppet we need one object with the <code class="docutils literal notranslate"><span class="pre">wood</span></code> tag and another with the <code class="docutils literal notranslate"><span class="pre">knife</span></code>
tag:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">evennia</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_object</span>
<span class="n">knife</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="s2">&quot;Hobby knife&quot;</span><span class="p">,</span> <span class="n">tags</span><span class="o">=</span><span class="p">[(</span><span class="s2">&quot;knife&quot;</span><span class="p">,</span> <span class="s2">&quot;crafting_tool&quot;</span><span class="p">)])</span>
<span class="n">wood</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="s2">&quot;Piece of wood&quot;</span><span class="p">,</span> <span class="n">tags</span><span class="p">[(</span><span class="s2">&quot;wood&quot;</span><span class="p">,</span> <span class="s2">&quot;crafting_material&quot;</span><span class="p">)])</span>
</pre></div>
</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
know ingredients.</p>
<p>By the way, there is also a simple shortcut for doing this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">tools</span><span class="p">,</span> <span class="n">consumables</span> <span class="o">=</span> <span class="n">WoodenPuppetRecipe</span><span class="o">.</span><span class="n">seed</span><span class="p">()</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">seed</span></code> class-method will create simple dummy objects that fulfills the
recipes requirements. This is great for testing.</p>
<p>Assuming these objects were put in our inventory, we could now craft using the
in-game command:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>&gt;<span class="w"> </span>craft<span class="w"> </span>wooden<span class="w"> </span>puppet<span class="w"> </span>from<span class="w"> </span>wood<span class="w"> </span>using<span class="w"> </span>hobby<span class="w"> </span>knife
</pre></div>
</div>
<p>In code we would do</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">evennia.contrib.game_systems.crafting</span><span class="w"> </span><span class="kn">import</span> <span class="n">craft</span>
<span class="n">puppet</span> <span class="o">=</span> <span class="n">craft</span><span class="p">(</span><span class="n">crafter</span><span class="p">,</span> <span class="s2">&quot;wooden puppet&quot;</span><span class="p">,</span> <span class="n">knife</span><span class="p">,</span> <span class="n">wood</span><span class="p">)</span>
</pre></div>
</div>
<p>In the call to <code class="docutils literal notranslate"><span class="pre">craft</span></code>, the order of <code class="docutils literal notranslate"><span class="pre">knife</span></code> and <code class="docutils literal notranslate"><span class="pre">wood</span></code> doesnt matter - the
recipe will sort out which is which based on their tags.</p>
</section>
<section id="deeper-customization-of-recipes">
<h2>Deeper customization of recipes<a class="headerlink" href="#deeper-customization-of-recipes" title="Link to this heading"></a></h2>
<p>For customizing recipes further, it helps to understand how to use the
recipe-class directly:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">MyRecipe</span><span class="p">(</span><span class="n">CraftingRecipe</span><span class="p">):</span>
<span class="c1"># ...</span>
<span class="n">tools</span><span class="p">,</span> <span class="n">consumables</span> <span class="o">=</span> <span class="n">MyRecipe</span><span class="o">.</span><span class="n">seed</span><span class="p">()</span>
<span class="n">recipe</span> <span class="o">=</span> <span class="n">MyRecipe</span><span class="p">(</span><span class="n">crafter</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="n">tools</span> <span class="o">+</span> <span class="n">consumables</span><span class="p">))</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">recipe</span><span class="o">.</span><span class="n">craft</span><span class="p">()</span>
</pre></div>
</div>
<p>This is useful for testing and allows you to use the class directly without
adding it to a module in <code class="docutils literal notranslate"><span class="pre">settings.CRAFTING_RECIPE_MODULES</span></code>.</p>
<p>Even without modifying more than the class properties, there are a lot of
options to set on the <code class="docutils literal notranslate"><span class="pre">CraftingRecipe</span></code> class. Easiest is to refer to the
<a class="reference internal" href="../api/evennia.contrib.game_systems.crafting.crafting.html#evennia.contrib.game_systems.crafting.crafting.CraftingRecipe" title="evennia.contrib.game_systems.crafting.crafting.CraftingRecipe"><span class="xref myst py py-class">CraftingRecipe api
documentation</span></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>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">pre_craft</span></code> - this should handle input validation and store its data in <code class="docutils literal notranslate"><span class="pre">.validated_consumables</span></code> and
<code class="docutils literal notranslate"><span class="pre">validated_tools</span></code> respectively. On error, this reports the error to the crafter and raises the
<code class="docutils literal notranslate"><span class="pre">CraftingValidationError</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">craft</span></code> - this will only be called if <code class="docutils literal notranslate"><span class="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><code class="docutils literal notranslate"><span class="pre">post_craft</span></code> - this receives the result from <code class="docutils literal notranslate"><span class="pre">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><code class="docutils literal notranslate"><span class="pre">msg</span></code> - this is a wrapper for <code class="docutils literal notranslate"><span class="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 <code class="docutils literal notranslate"><span class="pre">craft</span></code> access function) takes optional <code class="docutils literal notranslate"><span class="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>
<section id="skilled-crafters">
<h3>Skilled crafters<a class="headerlink" href="#skilled-crafters" title="Link to this heading"></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>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">random</span><span class="w"> </span><span class="kn">import</span> <span class="n">randint</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">evennia.contrib.game_systems.crafting</span><span class="w"> </span><span class="kn">import</span> <span class="n">CraftingRecipe</span>
<span class="k">class</span><span class="w"> </span><span class="nc">SkillRecipe</span><span class="p">(</span><span class="n">CraftingRecipe</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;A recipe that considers skill&quot;&quot;&quot;</span>
<span class="n">difficulty</span> <span class="o">=</span> <span class="mi">20</span>
<span class="k">def</span><span class="w"> </span><span class="nf">craft</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;The input is ok. Determine if crafting succeeds&quot;&quot;&quot;</span>
<span class="c1"># this is set at initialization</span>
<span class="n">crafter</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">crafte</span>
<span class="c1"># let&#39;s assume the skill is stored directly on the crafter</span>
<span class="c1"># - the skill is 0..100.</span>
<span class="n">crafting_skill</span> <span class="o">=</span> <span class="n">crafter</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">skill_crafting</span>
<span class="c1"># roll for success:</span>
<span class="k">if</span> <span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="p">(</span><span class="n">crafting_skill</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">difficulty</span><span class="p">):</span>
<span class="c1"># all is good, craft away</span>
<span class="k">return</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">craft</span><span class="p">()</span>
<span class="k">else</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;You are not good enough to craft this. Better luck next time!&quot;</span><span class="p">)</span>
<span class="k">return</span> <span class="p">[]</span>
</pre></div>
</div>
<p>In this example we introduce a <code class="docutils literal notranslate"><span class="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 <a class="reference internal" href="../api/evennia.contrib.game_systems.crafting.example_recipes.html#evennia-contrib-game-systems-crafting-example-recipes"><span class="std std-ref">sword recipe example module</span></a> also shows an example
of a random skill-check being implemented in a parent and then inherited for multiple use.</p>
</section>
</section>
<section id="even-more-customization">
<h2>Even more customization<a class="headerlink" href="#even-more-customization" title="Link to this heading"></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 <code class="docutils literal notranslate"><span class="pre">CraftingRecipe</span></code> parent class <code class="docutils literal notranslate"><span class="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 <code class="docutils literal notranslate"><span class="pre">CraftingRecipe</span></code>.</p>
<hr class="docutils" />
<p><small>This document page is generated from <code class="docutils literal notranslate"><span class="pre">evennia/contrib/game_systems/crafting/README.md</span></code>. Changes to this
file will be overwritten, so edit that file rather than this one.</small></p>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/evennia_logo.png" alt="Logo of Evennia"/>
</a></p>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script>
<h3><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Crafting system</a><ul>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#installation-and-usage">Installation and Usage</a></li>
<li><a class="reference internal" href="#adding-new-recipes">Adding new recipes</a></li>
<li><a class="reference internal" href="#deeper-customization-of-recipes">Deeper customization of recipes</a><ul>
<li><a class="reference internal" href="#skilled-crafters">Skilled crafters</a></li>
</ul>
</li>
<li><a class="reference internal" href="#even-more-customization">Even more customization</a></li>
</ul>
</li>
</ul>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="Contrib-Cooldowns.html"
title="previous chapter">Cooldowns</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="Contrib-Gendersub.html"
title="next chapter">Gendersub</a></p>
</div>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Contribs/Contrib-Crafting.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com/docs/latest/index.html">Documentation Top</a> </li>
<li><a href="https://www.evennia.com">Evennia Home</a> </li>
<li><a href="https://github.com/evennia/evennia">Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Doc Versions</h3>
<ul>
<li>
<a href="https://www.evennia.com/docs/latest/index.html">latest (main branch)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/6.x/index.html">v6.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/5.x/index.html">v5.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/4.x/index.html">v4.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/3.x/index.html">v3.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/2.x/index.html">v2.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/1.x/index.html">v1.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/0.x/index.html">v0.9.5 branch (outdated)</a>
</li>
</ul>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="Contrib-Gendersub.html" title="Gendersub"
>next</a> |</li>
<li class="right" >
<a href="Contrib-Cooldowns.html" title="Cooldowns"
>previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="Contribs-Overview.html" >Contribs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Crafting system</a></li>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2024, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
</div>
</body>
</html>