<pclass="last">You are reading an old version of the Evennia documentation. <ahref="https://www.evennia.com/docs/latest/index.html">The latest version is here</a></p>.
<h1><spanclass="section-number">4. </span>In-game Objects and items<aclass="headerlink"href="#in-game-objects-and-items"title="Permalink to this headline">¶</a></h1>
<p>In the previous lesson we established what a ‘Character’ is in our game. Before we continue
we also need to have a notion what an ‘item’ or ‘object’ is.</p>
<p>Looking at <em>Knave</em>’s item lists, we can get some ideas of what we need to track:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">size</span></code> - this is how many ‘slots’ the item uses in the character’s inventory.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">value</span></code> - a base value if we want to sell or buy the item.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">inventory_use_slot</span></code> - some items can be worn or wielded. For example, a helmet needs to be
worn on the head and a shield in the shield hand. Some items can’t be used this way at all, but
only belong in the backpack.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">obj_type</span></code> - Which ‘type’ of item this is.</p></li>
</ul>
<sectionid="new-enums">
<h2><spanclass="section-number">4.1. </span>New Enums<aclass="headerlink"href="#new-enums"title="Permalink to this headline">¶</a></h2>
<p>We added a few enumberations for Abilities back in the <aclass="reference internal"href="Beginner-Tutorial-Utilities.html"><spanclass="doc std std-doc">Utilities tutorial</span></a>.
Before we continue, let’s expand with enums for use-slots and object types.</p>
<p>Once we have these enums, we will use them for referencing things.</p>
</section>
<sectionid="the-base-object">
<h2><spanclass="section-number">4.2. </span>The base object<aclass="headerlink"href="#the-base-object"title="Permalink to this headline">¶</a></h2>
<blockquote>
<div><p>Create a new module <codeclass="docutils literal notranslate"><spanclass="pre">mygame/evadventure/objects.py</span></code></p>
</div></blockquote>
<asideclass="sidebar">
<p><aclass="reference internal"href="../../../api/evennia.contrib.tutorials.evadventure.objects.html"><spanclass="doc std std-doc">evennia/contrib/tutorials/evadventure/objects.py</span></a> has
a full set of objects implemented.</p>
</aside>
<divstyle="clear: right;"></div>
<p>We will make a base <codeclass="docutils literal notranslate"><spanclass="pre">EvAdventureObject</span></code> class off Evennia’s standard <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code>. We will then add
child classes to represent the relevant types:</p>
<spanclass="w"></span><spanclass="sd">"""Get any help text for this item"""</span>
<spanclass="k">return</span><spanclass="s2">"No help for this item"</span>
</pre></div>
</div>
<sectionid="using-attributes-or-not">
<h3><spanclass="section-number">4.2.1. </span>Using Attributes or not<aclass="headerlink"href="#using-attributes-or-not"title="Permalink to this headline">¶</a></h3>
<p>In theory, <codeclass="docutils literal notranslate"><spanclass="pre">size</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">value</span></code> does not change and <em>could</em> also be just set as a regular Python
<p>The problem with this is that if we want to make a new object of <codeclass="docutils literal notranslate"><spanclass="pre">size</span><spanclass="pre">3</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">value</span><spanclass="pre">20</span></code>, we have to
make a new class for it. We can’t change it on the fly because the change would only be in memory and
be lost on next server reload.</p>
<p>Because we use <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperties</span></code>, we can set <codeclass="docutils literal notranslate"><spanclass="pre">size</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">value</span></code> to whatever we like when we
create the object (or later), and the Attributes will remember our changes to that object indefinitely.</p>
<p>To make this a little more efficient, we use <codeclass="docutils literal notranslate"><spanclass="pre">autocreate=False</span></code>. Normally when you create a
new object with defined <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperties</span></code>, a matching <codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code> is immediately created at
the same time. So normally, the object would be created along with two Attributes <codeclass="docutils literal notranslate"><spanclass="pre">size</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">value</span></code>.
With <codeclass="docutils literal notranslate"><spanclass="pre">autocreate=False</span></code>, no Attribute will be created <em>unless the default is changed</em>. That is, as
long as your object has <codeclass="docutils literal notranslate"><spanclass="pre">size=1</span></code> no database <codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code> will be created at all. This saves time and
resources when creating large number of objects.</p>
<p>The drawback is that since no Attribute is created you can’t refer to it
with <codeclass="docutils literal notranslate"><spanclass="pre">obj.db.size</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">obj.attributes.get("size")</span></code><em>unless you change its default</em>. You also can’t query
the database for all objects with <codeclass="docutils literal notranslate"><spanclass="pre">size=1</span></code>, since most objects would not yet have an in-database
<codeclass="docutils literal notranslate"><spanclass="pre">size</span></code> Attribute to search for.</p>
<p>In our case, we’ll only refer to these properties as <codeclass="docutils literal notranslate"><spanclass="pre">obj.size</span></code> etc, and have no need to find
all objects of a particular size. So we should be safe.</p>
</section>
<sectionid="creating-tags-in-at-object-creation">
<h3><spanclass="section-number">4.2.2. </span>Creating tags in <codeclass="docutils literal notranslate"><spanclass="pre">at_object_creation</span></code><aclass="headerlink"href="#creating-tags-in-at-object-creation"title="Permalink to this headline">¶</a></h3>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">at_object_creation</span></code> is a method Evennia calls on every child of <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code> whenever it is
first created.</p>
<p>We do a tricky thing here, converting our <codeclass="docutils literal notranslate"><spanclass="pre">.obj_type</span></code> to one or more <aclass="reference internal"href="../../../Components/Tags.html"><spanclass="doc std std-doc">Tags</span></a>. Tagging the
object like this means you can later efficiently find all objects of a given type (or combination of
<p>We allow <codeclass="docutils literal notranslate"><spanclass="pre">.obj_type</span></code> to be given as a single value or a list of values. We use <codeclass="docutils literal notranslate"><spanclass="pre">make_iter</span></code> from the
evennia utility library to make sure we don’t balk at either. This means you could have a Shield that
is also Magical, for example.</p>
</section>
</section>
<sectionid="other-object-types">
<h2><spanclass="section-number">4.3. </span>Other object types<aclass="headerlink"href="#other-object-types"title="Permalink to this headline">¶</a></h2>
<p>Some of the other object types are very simple so far.</p>
<spanclass="n">user</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"</span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2"> was used up."</span><spanclass="p">)</span>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">quality</span></code> is something we need to track in <em>Knave</em>. When getting critical failures on attacks,
a weapon’s quality will go down. When it reaches 0, it will break.</p>
<p>The attack/defend type tracks how we resolve attacks with the weapon, like <codeclass="docutils literal notranslate"><spanclass="pre">roll</span><spanclass="pre">+</span><spanclass="pre">STR</span><spanclass="pre">vs</span><spanclass="pre">ARMOR</span><spanclass="pre">+</span><spanclass="pre">10</span></code>.</p>
</section>
<sectionid="magic">
<h2><spanclass="section-number">4.6. </span>Magic<aclass="headerlink"href="#magic"title="Permalink to this headline">¶</a></h2>
<p>In <em>Knave</em>, anyone can use magic if they are wielding a rune stone (our name for spell books) in both
hands. You can only use a rune stone once per rest. So a rune stone is an example of a ‘magical weapon’
<spanclass="n">inventory_use_slot</span><spanclass="o">=</span><spanclass="n">WieldLocation</span><spanclass="o">.</span><spanclass="n">TWO_HANDS</span><spanclass="c1"># always two hands for magic</span>
<p>We make the rune stone a mix of weapon and consumable. Note that we don’t have to add <codeclass="docutils literal notranslate"><spanclass="pre">.uses</span></code>
again, it’s inherited from <codeclass="docutils literal notranslate"><spanclass="pre">EvAdventureConsumable</span></code> parent. The <codeclass="docutils literal notranslate"><spanclass="pre">at_pre_use</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">at_use</span></code> methods
are also inherited; we only override <codeclass="docutils literal notranslate"><spanclass="pre">at_post_use</span></code> since we don’t want the runestone to be deleted
when it runs out of uses.</p>
<p>We add a little convenience method <codeclass="docutils literal notranslate"><spanclass="pre">refresh</span></code> - we should call this when the character rests, to
make the runestone active again.</p>
<p>Exactly what rune stones <em>do</em> will be implemented in the <codeclass="docutils literal notranslate"><spanclass="pre">at_use</span></code> methods of subclasses to this
base class. Since magic in <em>Knave</em> tends to be pretty custom, it makes sense that it will lead to a lot
of custom code.</p>
</section>
<sectionid="armor">
<h2><spanclass="section-number">4.7. </span>Armor<aclass="headerlink"href="#armor"title="Permalink to this headline">¶</a></h2>
<p>Armor, shields and helmets increase the <codeclass="docutils literal notranslate"><spanclass="pre">ARMOR</span></code> stat of the character. In <em>Knave</em>, what is stored is the
defense value of the armor (values 11-20). We will instead store the ‘armor bonus’ (1-10). As we know,
defending is always <codeclass="docutils literal notranslate"><spanclass="pre">bonus</span><spanclass="pre">+</span><spanclass="pre">10</span></code>, so the result will be the same - this means
we can use <codeclass="docutils literal notranslate"><spanclass="pre">Ability.ARMOR</span></code> as any other defensive ability without worrying about a special case.</p>
<h2><spanclass="section-number">4.8. </span>Your Bare hands<aclass="headerlink"href="#your-bare-hands"title="Permalink to this headline">¶</a></h2>
<p>This is a ‘dummy’ object that is not stored in the database. We will use this in the upcoming
<aclass="reference internal"href="Beginner-Tutorial-Equipment.html"><spanclass="doc std std-doc">Equipment tutorial lesson</span></a> to represent when you have ‘nothing’
in your hands. This way we don’t need to add any special case for this.</p>
<spanclass="n">quality</span><spanclass="o">=</span><spanclass="mi">100000</span><spanclass="c1"># let's assume fists are always available ...</span>
<h2><spanclass="section-number">4.9. </span>Testing and Extra credits<aclass="headerlink"href="#testing-and-extra-credits"title="Permalink to this headline">¶</a></h2>
<p>Remember the <codeclass="docutils literal notranslate"><spanclass="pre">get_obj_stats</span></code> function from the <aclass="reference internal"href="Beginner-Tutorial-Utilities.html"><spanclass="doc std std-doc">Utility Tutorial</span></a> earlier?
We had to use dummy-values since we didn’t yet know how we would store properties on Objects in the game.</p>
<p>Well, we just figured out all we need! You can go back and update <codeclass="docutils literal notranslate"><spanclass="pre">get_obj_stats</span></code> to properly read the data
from the object it receives.</p>
<p>When you change this function you must also update the related unit test - so your existing test becomes a
nice way to test your new Objects as well! Add more tests showing the output of feeding different object-types
to <codeclass="docutils literal notranslate"><spanclass="pre">get_obj_stats</span></code>.</p>
<p>Try it out yourself. If you need help, a finished utility example is found in <aclass="reference internal"href="../../../api/evennia.contrib.tutorials.evadventure.utils.html#evennia.contrib.tutorials.evadventure.utils.get_obj_stats"title="evennia.contrib.tutorials.evadventure.utils.get_obj_stats"><spanclass="xref myst py py-func">evennia/contrib/tutorials/evadventure/utils.py</span></a>.</p>
<pclass="last">You are reading an old version of the Evennia documentation. <ahref="https://www.evennia.com/docs/latest/index.html">The latest version is here</a></p>.