mirror of
https://github.com/evennia/evennia.git
synced 2026-03-19 06:16:31 +01:00
484 lines
No EOL
42 KiB
HTML
484 lines
No EOL
42 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||
|
||
<title>In-game Objects and items — Evennia 1.0-dev documentation</title>
|
||
<link rel="stylesheet" href="../../../_static/nature.css" type="text/css" />
|
||
<link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
|
||
<script id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script>
|
||
<script src="../../../_static/jquery.js"></script>
|
||
<script src="../../../_static/underscore.js"></script>
|
||
<script src="../../../_static/doctools.js"></script>
|
||
<script src="../../../_static/language_data.js"></script>
|
||
<link rel="shortcut 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="Handling Equipment" href="Beginner-Tutorial-Equipment.html" />
|
||
<link rel="prev" title="Player Characters" href="Beginner-Tutorial-Characters.html" />
|
||
</head><body>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<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="Beginner-Tutorial-Equipment.html" title="Handling Equipment"
|
||
accesskey="N">next</a> |</li>
|
||
<li class="right" >
|
||
<a href="Beginner-Tutorial-Characters.html" title="Player Characters"
|
||
accesskey="P">previous</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="../../../index.html">Evennia 1.0-dev</a> »</li>
|
||
<li class="nav-item nav-item-1"><a href="../../Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="../Beginner-Tutorial-Intro.html" >Beginner Tutorial</a> »</li>
|
||
<li class="nav-item nav-item-3"><a href="Beginner-Tutorial-Part3-Intro.html" accesskey="U">Part 3: How we get there</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">In-game Objects and items</a></li>
|
||
</ul>
|
||
<div class="develop">develop branch</div>
|
||
</div>
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<section class="tex2jax_ignore mathjax_ignore" id="in-game-objects-and-items">
|
||
<h1>In-game Objects and items<a class="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>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">size</span></code> - this is how many ‘slots’ the item uses in the character’s inventory.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">value</span></code> - a base value if we want to sell or buy the item.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="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><code class="docutils literal notranslate"><span class="pre">obj_type</span></code> - Which ‘type’ of item this is.</p></li>
|
||
</ul>
|
||
<section id="new-enums">
|
||
<h2>New Enums<a class="headerlink" href="#new-enums" title="Permalink to this headline">¶</a></h2>
|
||
<p>We added a few enumberations for Abilities back in the <a class="reference internal" href="Beginner-Tutorial-Utilities.html"><span class="doc std std-doc">Utilities tutorial</span></a>.
|
||
Before we continue, let’s expand with enums for use-slots and object types.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/evadventure/enums.py</span>
|
||
|
||
<span class="c1"># ...</span>
|
||
|
||
<span class="k">class</span> <span class="nc">WieldLocation</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||
|
||
<span class="n">BACKPACK</span> <span class="o">=</span> <span class="s2">"backpack"</span>
|
||
<span class="n">WEAPON_HAND</span> <span class="o">=</span> <span class="s2">"weapon_hand"</span>
|
||
<span class="n">SHIELD_HAND</span> <span class="o">=</span> <span class="s2">"shield_hand"</span>
|
||
<span class="n">TWO_HANDS</span> <span class="o">=</span> <span class="s2">"two_handed_weapons"</span>
|
||
<span class="n">BODY</span> <span class="o">=</span> <span class="s2">"body"</span> <span class="c1"># armor</span>
|
||
<span class="n">HEAD</span> <span class="o">=</span> <span class="s2">"head"</span> <span class="c1"># helmets</span>
|
||
|
||
<span class="k">class</span> <span class="nc">ObjType</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||
|
||
<span class="n">WEAPON</span> <span class="o">=</span> <span class="s2">"weapon"</span>
|
||
<span class="n">ARMOR</span> <span class="o">=</span> <span class="s2">"armor"</span>
|
||
<span class="n">SHIELD</span> <span class="o">=</span> <span class="s2">"shield"</span>
|
||
<span class="n">HELMET</span> <span class="o">=</span> <span class="s2">"helmet"</span>
|
||
<span class="n">CONSUMABLE</span> <span class="o">=</span> <span class="s2">"consumable"</span>
|
||
<span class="n">GEAR</span> <span class="o">=</span> <span class="s2">"gear"</span>
|
||
<span class="n">MAGIC</span> <span class="o">=</span> <span class="s2">"magic"</span>
|
||
<span class="n">QUEST</span> <span class="o">=</span> <span class="s2">"quest"</span>
|
||
<span class="n">TREASURE</span> <span class="o">=</span> <span class="s2">"treasure"</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Once we have these enums, we will use them for referencing things.</p>
|
||
</section>
|
||
<section id="the-base-object">
|
||
<h2>The base object<a class="headerlink" href="#the-base-object" title="Permalink to this headline">¶</a></h2>
|
||
<blockquote>
|
||
<div><p>Create a new module <code class="docutils literal notranslate"><span class="pre">mygame/evadventure/objects.py</span></code></p>
|
||
</div></blockquote>
|
||
<aside class="sidebar">
|
||
<p><a class="reference internal" href="../../../api/evennia.contrib.tutorials.evadventure.objects.html#evennia-contrib-tutorials-evadventure-objects"><span class="std std-ref">evennia/contrib/tutorials/evadventure/objects.py</span></a> has
|
||
a full set of objects implemented.</p>
|
||
</aside>
|
||
<div style="clear: right;"></div>
|
||
<p>We will make a base <code class="docutils literal notranslate"><span class="pre">EvAdventureObject</span></code> class off Evennia’s standard <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code>. We will then add
|
||
child classes to represent the relevant types:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/evadventure/objects.py</span>
|
||
|
||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">AttributeProperty</span><span class="p">,</span> <span class="n">DefaultObject</span>
|
||
<span class="kn">from</span> <span class="nn">evennia.utils.utils</span> <span class="kn">import</span> <span class="n">make_iter</span>
|
||
<span class="kn">from</span> <span class="nn">.utils</span> <span class="kn">import</span> <span class="n">get_obj_stats</span>
|
||
<span class="kn">from</span> <span class="nn">.enums</span> <span class="kn">import</span> <span class="n">WieldLocation</span><span class="p">,</span> <span class="n">ObjType</span>
|
||
|
||
|
||
<span class="k">class</span> <span class="nc">EvAdventureObject</span><span class="p">(</span><span class="n">DefaultObject</span><span class="p">):</span>
|
||
<span class="sd">""" </span>
|
||
<span class="sd"> Base for all evadventure objects. </span>
|
||
<span class="sd"> </span>
|
||
<span class="sd"> """</span>
|
||
<span class="n">inventory_use_slot</span> <span class="o">=</span> <span class="n">WieldLocation</span><span class="o">.</span><span class="n">BACKPACK</span>
|
||
<span class="n">size</span> <span class="o">=</span> <span class="n">AttributeProperty</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
<span class="n">value</span> <span class="o">=</span> <span class="n">AttributeProperty</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
|
||
<span class="c1"># this can be either a single type or a list of types (for objects able to be </span>
|
||
<span class="c1"># act as multiple). This is used to tag this object during creation.</span>
|
||
<span class="n">obj_type</span> <span class="o">=</span> <span class="n">ObjType</span><span class="o">.</span><span class="n">GEAR</span>
|
||
|
||
<span class="k">def</span> <span class="nf">at_object_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="sd">"""Called when this object is first created. We convert the .obj_type </span>
|
||
<span class="sd"> property to a database tag."""</span>
|
||
|
||
<span class="k">for</span> <span class="n">obj_type</span> <span class="ow">in</span> <span class="n">make_iter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">obj_type</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">obj_type</span><span class="o">.</span><span class="n">value</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">"obj_type"</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">get_help</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="sd">"""Get any help text for this item"""</span>
|
||
<span class="k">return</span> <span class="s2">"No help for this item"</span>
|
||
</pre></div>
|
||
</div>
|
||
<section id="using-attributes-or-not">
|
||
<h3>Using Attributes or not<a class="headerlink" href="#using-attributes-or-not" title="Permalink to this headline">¶</a></h3>
|
||
<p>In theory, <code class="docutils literal notranslate"><span class="pre">size</span></code> and <code class="docutils literal notranslate"><span class="pre">value</span></code> does not change and <em>could</em> also be just set as a regular Python
|
||
property on the class:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">EvAdventureObject</span><span class="p">(</span><span class="n">DefaultObject</span><span class="p">):</span>
|
||
<span class="n">inventory_use_slot</span> <span class="o">=</span> <span class="n">WieldLocation</span><span class="o">.</span><span class="n">BACKPACK</span>
|
||
<span class="n">size</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="n">value</span> <span class="o">=</span> <span class="mi">0</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The problem with this is that if we want to make a new object of <code class="docutils literal notranslate"><span class="pre">size</span> <span class="pre">3</span></code> and <code class="docutils literal notranslate"><span class="pre">value</span> <span class="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 <code class="docutils literal notranslate"><span class="pre">AttributeProperties</span></code>, we can set <code class="docutils literal notranslate"><span class="pre">size</span></code> and <code class="docutils literal notranslate"><span class="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 <code class="docutils literal notranslate"><span class="pre">autocreate=False</span></code>. Normally when you create a
|
||
new object with defined <code class="docutils literal notranslate"><span class="pre">AttributeProperties</span></code>, a matching <code class="docutils literal notranslate"><span class="pre">Attribute</span></code> is immediately created at
|
||
the same time. So normally, the object would be created along with two Attributes <code class="docutils literal notranslate"><span class="pre">size</span></code> and <code class="docutils literal notranslate"><span class="pre">value</span></code>.
|
||
With <code class="docutils literal notranslate"><span class="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 <code class="docutils literal notranslate"><span class="pre">size=1</span></code> no database <code class="docutils literal notranslate"><span class="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 <code class="docutils literal notranslate"><span class="pre">obj.db.size</span></code> or <code class="docutils literal notranslate"><span class="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 <code class="docutils literal notranslate"><span class="pre">size=1</span></code>, since most objects would not yet have an in-database
|
||
<code class="docutils literal notranslate"><span class="pre">size</span></code> Attribute to search for.</p>
|
||
<p>In our case, we’ll only refer to these properties as <code class="docutils literal notranslate"><span class="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>
|
||
<section id="creating-tags-in-at-object-creation">
|
||
<h3>Creating tags in <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code><a class="headerlink" href="#creating-tags-in-at-object-creation" title="Permalink to this headline">¶</a></h3>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code> is a method Evennia calls on every child of <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> whenever it is
|
||
first created.</p>
|
||
<p>We do a tricky thing here, converting our <code class="docutils literal notranslate"><span class="pre">.obj_type</span></code> to one or more <a class="reference internal" href="../../../Components/Tags.html"><span class="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
|
||
types) with Evennia’s search functions:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">.enums</span> <span class="kn">import</span> <span class="n">ObjType</span>
|
||
<span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">search</span>
|
||
|
||
<span class="c1"># get all shields in the game</span>
|
||
<span class="n">all_shields</span> <span class="o">=</span> <span class="n">search</span><span class="o">.</span><span class="n">search_object_by_tag</span><span class="p">(</span><span class="n">ObjType</span><span class="o">.</span><span class="n">SHIELD</span><span class="o">.</span><span class="n">value</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">"obj_type"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>We allow <code class="docutils literal notranslate"><span class="pre">.obj_type</span></code> to be given as a single value or a list of values. We use <code class="docutils literal notranslate"><span class="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>
|
||
<section id="other-object-types">
|
||
<h2>Other object types<a class="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>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/evadventure/objects.py </span>
|
||
|
||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">AttributeProperty</span><span class="p">,</span> <span class="n">DefaultObject</span>
|
||
<span class="kn">from</span> <span class="nn">.enums</span> <span class="kn">import</span> <span class="n">ObjType</span>
|
||
|
||
<span class="k">class</span> <span class="nc">EvAdventureObject</span><span class="p">(</span><span class="n">DefaultObject</span><span class="p">):</span>
|
||
<span class="c1"># ... </span>
|
||
|
||
|
||
<span class="k">class</span> <span class="nc">EvAdventureQuestObject</span><span class="p">(</span><span class="n">EvAdventureObject</span><span class="p">):</span>
|
||
<span class="sd">"""Quest objects should usually not be possible to sell or trade."""</span>
|
||
<span class="n">obj_type</span> <span class="o">=</span> <span class="n">ObjType</span><span class="o">.</span><span class="n">QUEST</span>
|
||
|
||
<span class="k">class</span> <span class="nc">EvAdventureTreasure</span><span class="p">(</span><span class="n">EvAdventureObject</span><span class="p">):</span>
|
||
<span class="sd">"""Treasure is usually just for selling for coin"""</span>
|
||
<span class="n">obj_type</span> <span class="o">=</span> <span class="n">ObjType</span><span class="o">.</span><span class="n">TREASURE</span>
|
||
<span class="n">value</span> <span class="o">=</span> <span class="n">AttributeProperty</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="consumables">
|
||
<h2>Consumables<a class="headerlink" href="#consumables" title="Permalink to this headline">¶</a></h2>
|
||
<p>A ‘consumable’ is an item that has a certain number of ‘uses’. Once fully consumed, it can’t be used
|
||
anymore. An example would be a health potion.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/evadventure/objects.py </span>
|
||
|
||
<span class="c1"># ... </span>
|
||
|
||
<span class="k">class</span> <span class="nc">EvAdventureConsumable</span><span class="p">(</span><span class="n">EvAdventureObject</span><span class="p">):</span>
|
||
<span class="sd">"""An item that can be used up"""</span>
|
||
|
||
<span class="n">obj_type</span> <span class="o">=</span> <span class="n">ObjType</span><span class="o">.</span><span class="n">CONSUMABLE</span>
|
||
<span class="n">value</span> <span class="o">=</span> <span class="n">AttributeProperty</span><span class="p">(</span><span class="mf">0.25</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
<span class="n">uses</span> <span class="o">=</span> <span class="n">AttributeProperty</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">at_pre_use</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">user</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="sd">"""Called before using. If returning False, abort use."""</span>
|
||
<span class="k">return</span> <span class="n">uses</span> <span class="o">></span> <span class="mi">0</span>
|
||
|
||
<span class="k">def</span> <span class="nf">at_use</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">user</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="sd">"""Called when using the item"""</span>
|
||
<span class="k">pass</span>
|
||
|
||
<span class="k">def</span> <span class="nf">at_post_use</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span> <span class="n">user</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="sd">"""Called after using the item"""</span>
|
||
<span class="c1"># detract a usage, deleting the item if used up.</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">uses</span> <span class="o">-=</span> <span class="mi">1</span>
|
||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">uses</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">:</span>
|
||
<span class="n">user</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> was used up."</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>What exactly each consumable does will vary - we will need to implement children of this class
|
||
later, overriding <code class="docutils literal notranslate"><span class="pre">at_use</span></code> with different effects.</p>
|
||
</section>
|
||
<section id="weapons">
|
||
<h2>Weapons<a class="headerlink" href="#weapons" title="Permalink to this headline">¶</a></h2>
|
||
<p>All weapons need properties that describe how efficient they are in battle.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/evadventure/objects.py </span>
|
||
|
||
<span class="kn">from</span> <span class="nn">.enums</span> <span class="kn">import</span> <span class="n">WieldLocation</span><span class="p">,</span> <span class="n">ObjType</span><span class="p">,</span> <span class="n">Ability</span>
|
||
|
||
<span class="c1"># ... </span>
|
||
|
||
<span class="k">class</span> <span class="nc">EvAdventureWeapon</span><span class="p">(</span><span class="n">EvAdventureObject</span><span class="p">):</span>
|
||
<span class="sd">"""Base class for all weapons"""</span>
|
||
|
||
<span class="n">obj_type</span> <span class="o">=</span> <span class="n">ObjType</span><span class="o">.</span><span class="n">WEAPON</span>
|
||
<span class="n">inventory_use_slot</span> <span class="o">=</span> <span class="n">AttributeProperty</span><span class="p">(</span><span class="n">WieldLocation</span><span class="o">.</span><span class="n">WEAPON_HAND</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
<span class="n">quality</span> <span class="o">=</span> <span class="n">AttributeProperty</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
|
||
<span class="n">attack_type</span> <span class="o">=</span> <span class="n">AttibuteProperty</span><span class="p">(</span><span class="n">Ability</span><span class="o">.</span><span class="n">STR</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
<span class="n">defend_type</span> <span class="o">=</span> <span class="n">AttibuteProperty</span><span class="p">(</span><span class="n">Ability</span><span class="o">.</span><span class="n">ARMOR</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
|
||
<span class="n">damage_roll</span> <span class="o">=</span> <span class="n">AttibuteProperty</span><span class="p">(</span><span class="s2">"1d6"</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="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 <code class="docutils literal notranslate"><span class="pre">roll</span> <span class="pre">+</span> <span class="pre">STR</span> <span class="pre">vs</span> <span class="pre">ARMOR</span> <span class="pre">+</span> <span class="pre">10</span></code>.</p>
|
||
</section>
|
||
<section id="magic">
|
||
<h2>Magic<a class="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’
|
||
that is also a ‘consumable’ of sorts.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/evadventure/objects.py </span>
|
||
|
||
<span class="c1"># ... </span>
|
||
<span class="k">class</span> <span class="nc">EvAdventureConsumable</span><span class="p">(</span><span class="n">EvAdventureObject</span><span class="p">):</span>
|
||
<span class="c1"># ... </span>
|
||
|
||
<span class="k">class</span> <span class="nc">EvAdventureWeapon</span><span class="p">(</span><span class="n">EvAdventureObject</span><span class="p">):</span>
|
||
<span class="c1"># ... </span>
|
||
|
||
<span class="k">class</span> <span class="nc">EvAdventureRuneStone</span><span class="p">(</span><span class="n">EvAdventureWeapon</span><span class="p">,</span> <span class="n">EvAdventureConsumable</span><span class="p">):</span>
|
||
<span class="sd">"""Base for all magical rune stones"""</span>
|
||
|
||
<span class="n">obj_type</span> <span class="o">=</span> <span class="p">(</span><span class="n">ObjType</span><span class="o">.</span><span class="n">WEAPON</span><span class="p">,</span> <span class="n">ObjType</span><span class="o">.</span><span class="n">MAGIC</span><span class="p">)</span>
|
||
<span class="n">inventory_use_slot</span> <span class="o">=</span> <span class="n">WieldLocation</span><span class="o">.</span><span class="n">TWO_HANDS</span> <span class="c1"># always two hands for magic</span>
|
||
<span class="n">quality</span> <span class="o">=</span> <span class="n">AttributeProperty</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
|
||
<span class="n">attack_type</span> <span class="o">=</span> <span class="n">AttibuteProperty</span><span class="p">(</span><span class="n">Ability</span><span class="o">.</span><span class="n">INT</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
<span class="n">defend_type</span> <span class="o">=</span> <span class="n">AttibuteProperty</span><span class="p">(</span><span class="n">Ability</span><span class="o">.</span><span class="n">DEX</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
|
||
<span class="n">damage_roll</span> <span class="o">=</span> <span class="n">AttibuteProperty</span><span class="p">(</span><span class="s2">"1d8"</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">at_post_use</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">user</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="sd">"""Called after usage/spell was cast"""</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">uses</span> <span class="o">-=</span> <span class="mi">1</span>
|
||
<span class="c1"># we don't delete the rune stone here, but </span>
|
||
<span class="c1"># it must be reset on next rest.</span>
|
||
|
||
<span class="k">def</span> <span class="nf">refresh</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="sd">"""Refresh the rune stone (normally after rest)"""</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">uses</span> <span class="o">=</span> <span class="mi">1</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>We make the rune stone a mix of weapon and consumable. Note that we don’t have to add <code class="docutils literal notranslate"><span class="pre">.uses</span></code>
|
||
again, it’s inherited from <code class="docutils literal notranslate"><span class="pre">EvAdventureConsumable</span></code> parent. The <code class="docutils literal notranslate"><span class="pre">at_pre_use</span></code> and <code class="docutils literal notranslate"><span class="pre">at_use</span></code> methods
|
||
are also inherited; we only override <code class="docutils literal notranslate"><span class="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 <code class="docutils literal notranslate"><span class="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 <code class="docutils literal notranslate"><span class="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>
|
||
<section id="armor">
|
||
<h2>Armor<a class="headerlink" href="#armor" title="Permalink to this headline">¶</a></h2>
|
||
<p>Armor, shields and helmets increase the <code class="docutils literal notranslate"><span class="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 <code class="docutils literal notranslate"><span class="pre">bonus</span> <span class="pre">+</span> <span class="pre">10</span></code>, so the result will be the same - this means
|
||
we can use <code class="docutils literal notranslate"><span class="pre">Ability.ARMOR</span></code> as any other defensive ability without worrying about a special case.</p>
|
||
<p>``</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/evadventure/objects.py </span>
|
||
|
||
<span class="c1"># ... </span>
|
||
|
||
<span class="k">class</span> <span class="nc">EvAdventureAmor</span><span class="p">(</span><span class="n">EvAdventureObject</span><span class="p">):</span>
|
||
<span class="n">obj_type</span> <span class="o">=</span> <span class="n">ObjType</span><span class="o">.</span><span class="n">ARMOR</span>
|
||
<span class="n">inventory_use_slot</span> <span class="o">=</span> <span class="n">WieldLocation</span><span class="o">.</span><span class="n">BODY</span>
|
||
|
||
<span class="n">armor</span> <span class="o">=</span> <span class="n">AttributeProperty</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
<span class="n">quality</span> <span class="o">=</span> <span class="n">AttributeProperty</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
|
||
|
||
<span class="k">class</span> <span class="nc">EvAdventureShield</span><span class="p">(</span><span class="n">EvAdventureArmor</span><span class="p">):</span>
|
||
<span class="n">obj_type</span> <span class="o">=</span> <span class="n">ObjType</span><span class="o">.</span><span class="n">SHIELD</span>
|
||
<span class="n">inventory_use_slot</span> <span class="o">=</span> <span class="n">WieldLocation</span><span class="o">.</span><span class="n">SHIELD_HAND</span>
|
||
|
||
|
||
<span class="k">class</span> <span class="nc">EvAdventureHelmet</span><span class="p">(</span><span class="n">EvAdventureArmor</span><span class="p">):</span>
|
||
<span class="n">obj_type</span> <span class="o">=</span> <span class="n">ObjType</span><span class="o">.</span><span class="n">HELMET</span>
|
||
<span class="n">inventory_use_slot</span> <span class="o">=</span> <span class="n">WieldLocation</span><span class="o">.</span><span class="n">HEAD</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="your-bare-hands">
|
||
<h2>Your Bare hands<a class="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
|
||
<a class="reference internal" href="Beginner-Tutorial-Equipment.html"><span class="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>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">WeaponEmptyHand</span><span class="p">:</span>
|
||
<span class="n">obj_type</span> <span class="o">=</span> <span class="n">ObjType</span><span class="o">.</span><span class="n">WEAPON</span>
|
||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"Empty Fists"</span>
|
||
<span class="n">inventory_use_slot</span> <span class="o">=</span> <span class="n">WieldLocation</span><span class="o">.</span><span class="n">WEAPON_HAND</span>
|
||
<span class="n">attack_type</span> <span class="o">=</span> <span class="n">Ability</span><span class="o">.</span><span class="n">STR</span>
|
||
<span class="n">defense_type</span> <span class="o">=</span> <span class="n">Ability</span><span class="o">.</span><span class="n">ARMOR</span>
|
||
<span class="n">damage_roll</span> <span class="o">=</span> <span class="s2">"1d4"</span>
|
||
<span class="n">quality</span> <span class="o">=</span> <span class="mi">100000</span> <span class="c1"># let's assume fists are always available ...</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="s2">"<WeaponEmptyHand>"</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="testing-and-extra-credits">
|
||
<h2>Testing and Extra credits<a class="headerlink" href="#testing-and-extra-credits" title="Permalink to this headline">¶</a></h2>
|
||
<p>Remember the <code class="docutils literal notranslate"><span class="pre">get_obj_stats</span></code> function from the <a class="reference internal" href="Beginner-Tutorial-Utilities.html"><span class="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 <code class="docutils literal notranslate"><span class="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 <code class="docutils literal notranslate"><span class="pre">get_obj_stats</span></code>.</p>
|
||
<p>Try it out yourself. If you need help, a finished utility example is found in <a class="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"><span class="xref myst py py-func">evennia/contrib/tutorials/evadventure/utils.py</span></a>.</p>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
<div class="clearer"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||
<div class="sphinxsidebarwrapper">
|
||
<p class="logo"><a href="../../../index.html">
|
||
<img class="logo" src="../../../_static/evennia_logo.png" alt="Logo"/>
|
||
</a></p>
|
||
<div 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" />
|
||
<input type="submit" value="Go" />
|
||
</form>
|
||
</div>
|
||
</div>
|
||
<script>$('#searchbox').show(0);</script>
|
||
<p><h3><a href="../../../index.html">Table of Contents</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#">In-game Objects and items</a><ul>
|
||
<li><a class="reference internal" href="#new-enums">New Enums</a></li>
|
||
<li><a class="reference internal" href="#the-base-object">The base object</a><ul>
|
||
<li><a class="reference internal" href="#using-attributes-or-not">Using Attributes or not</a></li>
|
||
<li><a class="reference internal" href="#creating-tags-in-at-object-creation">Creating tags in <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code></a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#other-object-types">Other object types</a></li>
|
||
<li><a class="reference internal" href="#consumables">Consumables</a></li>
|
||
<li><a class="reference internal" href="#weapons">Weapons</a></li>
|
||
<li><a class="reference internal" href="#magic">Magic</a></li>
|
||
<li><a class="reference internal" href="#armor">Armor</a></li>
|
||
<li><a class="reference internal" href="#your-bare-hands">Your Bare hands</a></li>
|
||
<li><a class="reference internal" href="#testing-and-extra-credits">Testing and Extra credits</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<h4>Previous topic</h4>
|
||
<p class="topless"><a href="Beginner-Tutorial-Characters.html"
|
||
title="previous chapter">Player Characters</a></p>
|
||
<h4>Next topic</h4>
|
||
<p class="topless"><a href="Beginner-Tutorial-Equipment.html"
|
||
title="next chapter">Handling Equipment</a></p>
|
||
<div role="note" aria-label="source link">
|
||
<!--h3>This Page</h3-->
|
||
<ul class="this-page-menu">
|
||
<li><a href="../../../_sources/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Objects.md.txt"
|
||
rel="nofollow">Show Page Source</a></li>
|
||
</ul>
|
||
</div><h3>Links</h3>
|
||
<ul>
|
||
<li><a href="https://www.evennia.com">Home page</a> </li>
|
||
<li><a href="https://github.com/evennia/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>Versions</h3>
|
||
<ul>
|
||
<li><a href="Beginner-Tutorial-Objects.html">1.0-dev (develop branch)</a></li>
|
||
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
|
||
</ul>
|
||
|
||
</div>
|
||
</div>
|
||
<div class="clearer"></div>
|
||
</div>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<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="Beginner-Tutorial-Equipment.html" title="Handling Equipment"
|
||
>next</a> |</li>
|
||
<li class="right" >
|
||
<a href="Beginner-Tutorial-Characters.html" title="Player Characters"
|
||
>previous</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="../../../index.html">Evennia 1.0-dev</a> »</li>
|
||
<li class="nav-item nav-item-1"><a href="../../Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="../Beginner-Tutorial-Intro.html" >Beginner Tutorial</a> »</li>
|
||
<li class="nav-item nav-item-3"><a href="Beginner-Tutorial-Part3-Intro.html" >Part 3: How we get there</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">In-game Objects and items</a></li>
|
||
</ul>
|
||
<div class="develop">develop branch</div>
|
||
</div>
|
||
<div class="footer" role="contentinfo">
|
||
© Copyright 2020, The Evennia developer community.
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
||
</div>
|
||
</body>
|
||
</html> |