<p>The tutorial starts from scratch. If you did the <aclass="reference internal"href="../Part1/Starting-Part1.html"><spanclass="doc std std-doc">First Steps Coding</span></a> tutorial
<li><p>Have a “Power” score from 1 to 10 that measures how strong they are (stand-in for the stat
system).</p></li>
<li><p>Have a command (e.g. <codeclass="docutils literal notranslate"><spanclass="pre">+setpower</span><spanclass="pre">4</span></code>) that sets their power (stand-in for character generation
code).</p></li>
<li><p>Have a command (e.g. <codeclass="docutils literal notranslate"><spanclass="pre">+attack</span></code>) that lets them roll their power and produce a “Combat Score”
between <codeclass="docutils literal notranslate"><spanclass="pre">1</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">10*Power</span></code>, displaying the result and editing their object to record this number
(stand-in for <codeclass="docutils literal notranslate"><spanclass="pre">+actions</span></code> in the command code).</p></li>
<li><p>Have a command that displays everyone in the room and what their most recent “Combat Score” roll
<li><p>Have a command (e.g. <codeclass="docutils literal notranslate"><spanclass="pre">+createNPC</span><spanclass="pre">Jenkins</span></code>) that creates an NPC with full abilities.</p></li>
<li><p>Have a command to control NPCs, such as <codeclass="docutils literal notranslate"><spanclass="pre">+npc/cmd</span><spanclass="pre">(name)=(command)</span></code> (stand-in for the NPC
<p>To emulate a MUSH, the default <codeclass="docutils literal notranslate"><spanclass="pre">MULTISESSION_MODE=0</span></code> is enough (one unique session per
account/character). This is the default so you don’t need to change anything. You will still be able
to puppet/unpuppet objects you have permission to, but there is no character selection out of the
box in this mode.</p>
<p>We will assume our game folder is called <codeclass="docutils literal notranslate"><spanclass="pre">mygame</span></code> henceforth. You should be fine with the default
<p>We defined two new <aclass="reference internal"href="../../../Components/Attributes.html"><spanclass="doc std std-doc">Attributes</span></a><codeclass="docutils literal notranslate"><spanclass="pre">power</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">combat_score</span></code> and set them to default
values. Make sure to <codeclass="docutils literal notranslate"><spanclass="pre">@reload</span></code> the server if you had it already running (you need to reload every
time you update your python code, don’t worry, no accounts will be disconnected by the reload).</p>
<p>Note that only <em>new</em> characters will see your new Attributes (since the <codeclass="docutils literal notranslate"><spanclass="pre">at_object_creation</span></code> hook is
called when the object is first created, existing Characters won’t have it). To update yourself,
<p>This resets your own typeclass (the <codeclass="docutils literal notranslate"><spanclass="pre">/force</span></code> switch is a safety measure to not do this
accidentally), this means that <codeclass="docutils literal notranslate"><spanclass="pre">at_object_creation</span></code> is re-run.</p>
<p>Under the “Persistent attributes” heading you should now find the new Attributes <codeclass="docutils literal notranslate"><spanclass="pre">power</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">score</span></code>
set on yourself by <codeclass="docutils literal notranslate"><spanclass="pre">at_object_creation</span></code>. If you don’t, first make sure you <codeclass="docutils literal notranslate"><spanclass="pre">@reload</span></code>ed into the new
code, next look at your server log (in the terminal/console) to see if there were any syntax errors
in your code that may have stopped your new code from loading correctly.</p>
<p>We assume in this example that Accounts first connect into a “character generation area”. Evennia
also supports full OOC menu-driven character generation, but for this example, a simple start room
is enough. When in this room (or rooms) we allow character generation commands. In fact, character
generation commands will <em>only</em> be available in such rooms.</p>
<p>Note that this again is made so as to be easy to expand to a full-fledged game. With our simple
example, we could simply set an <codeclass="docutils literal notranslate"><spanclass="pre">is_in_chargen</span></code> flag on the account and have the <codeclass="docutils literal notranslate"><spanclass="pre">+setpower</span></code> command
check it. Using this method however will make it easy to add more functionality later.</p>
<li><p>One character generation <aclass="reference internal"href="../../../Components/Commands.html"><spanclass="doc std std-doc">Command</span></a> to set the “Power” on the <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code>.</p></li>
<li><p>A chargen <aclass="reference internal"href="../../../Components/Command-Sets.html"><spanclass="doc std std-doc">CmdSet</span></a> to hold this command. Lets call it <codeclass="docutils literal notranslate"><spanclass="pre">ChargenCmdset</span></code>.</p></li>
<li><p>A custom <codeclass="docutils literal notranslate"><spanclass="pre">ChargenRoom</span></code> type that makes this set of commands available to players in such rooms.</p></li>
<p>For this tutorial we will add all our new commands to <codeclass="docutils literal notranslate"><spanclass="pre">mygame/commands/command.py</span></code> but you could
split your commands into multiple module if you prefered.</p>
<p>For this tutorial character generation will only consist of one <aclass="reference internal"href="../../../Components/Commands.html"><spanclass="doc std std-doc">Command</span></a> to set the
<p>Open <codeclass="docutils literal notranslate"><spanclass="pre">command.py</span></code> file. It contains documented empty templates for the base command and the
“MuxCommand” type used by default in Evennia. We will use the plain <codeclass="docutils literal notranslate"><spanclass="pre">Command</span></code> type here, the
<codeclass="docutils literal notranslate"><spanclass="pre">MuxCommand</span></code> class offers some extra features like stripping whitespace that may be useful - if so,
<spanclass="kn">from</span><spanclass="nn">evennia</span><spanclass="kn">import</span><spanclass="n">Command</span><spanclass="c1"># just for clarity; already imported above</span>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"Your Power was set to </span><spanclass="si">{</span><spanclass="n">power</span><spanclass="si">}</span><spanclass="s2">."</span><spanclass="p">)</span>
<p>This is a pretty straightforward command. We do some error checking, then set the power on ourself.
We use a <codeclass="docutils literal notranslate"><spanclass="pre">help_category</span></code> of “mush” for all our commands, just so they are easy to find and separate
<p>Save the file. We will now add it to a new <aclass="reference internal"href="../../../Components/Command-Sets.html"><spanclass="doc std std-doc">CmdSet</span></a> so it can be accessed (in a full
chargen system you would of course have more than one command here).</p>
<p>Open <codeclass="docutils literal notranslate"><spanclass="pre">mygame/commands/default_cmdsets.py</span></code> and import your <codeclass="docutils literal notranslate"><spanclass="pre">command.py</span></code> module at the top. We also
import the default <codeclass="docutils literal notranslate"><spanclass="pre">CmdSet</span></code> class for the next step:</p>
<p>Next scroll down and define a new command set (based on the base <codeclass="docutils literal notranslate"><spanclass="pre">CmdSet</span></code> class we just imported at
the end of this file, to hold only our chargen-specific command(s):</p>
<p>Note how new rooms created with this typeclass will always start with <codeclass="docutils literal notranslate"><spanclass="pre">ChargenCmdset</span></code> on themselves.
Don’t forget the <codeclass="docutils literal notranslate"><spanclass="pre">persistent=True</span></code> keyword or you will lose the cmdset after a server reload. For
more information about <aclass="reference internal"href="../../../Components/Command-Sets.html"><spanclass="doc std std-doc">Command Sets</span></a> and <aclass="reference internal"href="../../../Components/Commands.html"><spanclass="doc std std-doc">Commands</span></a>, see the respective
<p>First, make sure you have <codeclass="docutils literal notranslate"><spanclass="pre">@reload</span></code>ed the server (or use <codeclass="docutils literal notranslate"><spanclass="pre">evennia</span><spanclass="pre">reload</span></code> from the terminal) to have
your new python code added to the game. Check your terminal and fix any errors you see - the error
traceback lists exactly where the error is found - look line numbers in files you have changed.</p>
<p>We can’t test things unless we have some chargen areas to test. Log into the game (you should at
this point be using the new, custom Character class). Let’s dig a chargen area to test.</p>
<p>If you read the help for <codeclass="docutils literal notranslate"><spanclass="pre">@dig</span></code> you will find that this will create a new room named <codeclass="docutils literal notranslate"><spanclass="pre">chargen</span></code>. The
part after the <codeclass="docutils literal notranslate"><spanclass="pre">:</span></code> is the python-path to the Typeclass you want to use. Since Evennia will
automatically try the <codeclass="docutils literal notranslate"><spanclass="pre">typeclasses</span></code> folder of our game directory, we just specify
<codeclass="docutils literal notranslate"><spanclass="pre">rooms.ChargenRoom</span></code>, meaning it will look inside the module <codeclass="docutils literal notranslate"><spanclass="pre">rooms.py</span></code> for a class named
<codeclass="docutils literal notranslate"><spanclass="pre">ChargenRoom</span></code> (which is what we created above). The names given after <codeclass="docutils literal notranslate"><spanclass="pre">=</span></code> are the names of exits to
and from the room from your current location. You could also append aliases to each one name, such
as <codeclass="docutils literal notranslate"><spanclass="pre">chargen;character</span><spanclass="pre">generation</span></code>.</p>
<p>So in summary, this will create a new room of type ChargenRoom and open an exit <codeclass="docutils literal notranslate"><spanclass="pre">chargen</span></code> to it and
an exit back here named <codeclass="docutils literal notranslate"><spanclass="pre">finish</span></code>. If you see errors at this stage, you must fix them in your code.
<p>This should bring you to the chargen room. Being in there you should now have the <codeclass="docutils literal notranslate"><spanclass="pre">+setpower</span></code>
command available, so test it out. When you leave (via the <codeclass="docutils literal notranslate"><spanclass="pre">finish</span></code> exit), the command will go away
and trying <codeclass="docutils literal notranslate"><spanclass="pre">+setpower</span></code> should now give you a command-not-found error. Use <codeclass="docutils literal notranslate"><spanclass="pre">ex</span><spanclass="pre">me</span></code> (as a privileged
user) to check so the <codeclass="docutils literal notranslate"><spanclass="pre">Power</span></code><aclass="reference internal"href="../../../Components/Attributes.html"><spanclass="doc std std-doc">Attribute</span></a> has been set correctly.</p>
<p>We will add our combat command to the default command set, meaning it will be available to everyone
at all times. The combat system consists of a <codeclass="docutils literal notranslate"><spanclass="pre">+attack</span></code> command to get how successful our attack is.
We also change the default <codeclass="docutils literal notranslate"><spanclass="pre">look</span></code> command to display the current combat score.</p>
<p>Attacking in this simple system means rolling a random “combat score” influenced by the <codeclass="docutils literal notranslate"><spanclass="pre">power</span></code> stat
<p>Go back to <codeclass="docutils literal notranslate"><spanclass="pre">mygame/commands/command.py</span></code> and add the command to the end like this:</p>
<spanclass="n">message_template</span><spanclass="o">=</span><spanclass="s2">"</span><spanclass="si">{attacker}</span><spanclass="s2"> +attack</span><spanclass="si">{s}</span><spanclass="s2"> with a combat score of </span><spanclass="si">{c_score}</span><spanclass="s2">!"</span>
<p>What we do here is simply to generate a “combat score” using Python’s inbuilt <codeclass="docutils literal notranslate"><spanclass="pre">random.randint()</span></code>
function. We then store that and echo the result to everyone involved.</p>
<p>To make the <codeclass="docutils literal notranslate"><spanclass="pre">+attack</span></code> command available to you in game, go back to
<codeclass="docutils literal notranslate"><spanclass="pre">mygame/commands/default_cmdsets.py</span></code> and scroll down to the <codeclass="docutils literal notranslate"><spanclass="pre">CharacterCmdSet</span></code> class. At the correct
<p><codeclass="docutils literal notranslate"><spanclass="pre">@reload</span></code> Evennia and the <codeclass="docutils literal notranslate"><spanclass="pre">+attack</span></code> command should be available to you. Run it and use e.g. <codeclass="docutils literal notranslate"><spanclass="pre">@ex</span></code> to
make sure the <codeclass="docutils literal notranslate"><spanclass="pre">combat_score</span></code> attribute is saved correctly.</p>
<p>Players should be able to view all current combat scores in the room. We could do this by simply
adding a second command named something like <codeclass="docutils literal notranslate"><spanclass="pre">+combatscores</span></code>, but we will instead let the default
<codeclass="docutils literal notranslate"><spanclass="pre">look</span></code> command do the heavy lifting for us and display our scores as part of its normal output, like
<p>We don’t actually have to modify the <codeclass="docutils literal notranslate"><spanclass="pre">look</span></code> command itself however. To understand why, take a look
at how the default <codeclass="docutils literal notranslate"><spanclass="pre">look</span></code> is actually defined. It sits in <codeclass="docutils literal notranslate"><spanclass="pre">evennia/commands/default/general.py</span></code> (or
You will find that the actual return text is done by the <codeclass="docutils literal notranslate"><spanclass="pre">look</span></code> command calling a <em>hook method</em>
named <codeclass="docutils literal notranslate"><spanclass="pre">return_appearance</span></code> on the object looked at. All the <codeclass="docutils literal notranslate"><spanclass="pre">look</span></code> does is to echo whatever this hook
returns. So what we need to do is to edit our custom Character typeclass and overload its
<codeclass="docutils literal notranslate"><spanclass="pre">return_appearance</span></code> to return what we want (this is where the advantage of having a custom typeclass
comes into play for real).</p>
<p>Go back to your custom Character typeclass in <codeclass="docutils literal notranslate"><spanclass="pre">mygame/typeclasses/characters.py</span></code>. The default
implementation of <codeclass="docutils literal notranslate"><spanclass="pre">return</span><spanclass="pre">appearance</span></code> is found in <codeclass="docutils literal notranslate"><spanclass="pre">evennia.DefaultCharacter</span></code> (or online
<aclass="reference external"href="https://github.com/evennia/evennia/blob/master/evennia/objects/objects.py#L1438">here</a>). If you
want to make bigger changes you could copy & paste the whole default thing into our overloading
method. In our case the change is small though:</p>
<p>What we do is to simply let the default <codeclass="docutils literal notranslate"><spanclass="pre">return_appearance</span></code> do its thing (<codeclass="docutils literal notranslate"><spanclass="pre">super</span></code> will call the
parent’s version of the same method). We then split out the first line of this text, append our
<codeclass="docutils literal notranslate"><spanclass="pre">combat_score</span></code> and put it back together again.</p>
<p><codeclass="docutils literal notranslate"><spanclass="pre">@reload</span></code> the server and you should be able to look at other Characters and see their current combat
<div><p>Note: A potentially more useful way to do this would be to overload the entire <codeclass="docutils literal notranslate"><spanclass="pre">return_appearance</span></code>
of the <codeclass="docutils literal notranslate"><spanclass="pre">Room</span></code>s of your mush and change how they list their contents; in that way one could see all
combat scores of all present Characters at the same time as looking at the room. We leave this as an
<spanclass="c1"># may not create npc when OOC</span>
<spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You must have a location to create an npc."</span><spanclass="p">)</span>
<spanclass="k">return</span>
<spanclass="c1"># make name always start with capital letter</span>
<spanclass="n">locks</span><spanclass="o">=</span><spanclass="sa">f</span><spanclass="s2">"edit:id(</span><spanclass="si">{</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">id</span><spanclass="si">}</span><spanclass="s2">) and perm(Builders);call:false()"</span><spanclass="p">)</span>
<spanclass="n">message_template</span><spanclass="o">=</span><spanclass="s2">"</span><spanclass="si">{creator}</span><spanclass="s2"> created the NPC '</span><spanclass="si">{npc}</span><spanclass="s2">'."</span>
<p>Here we define a <codeclass="docutils literal notranslate"><spanclass="pre">+createnpc</span></code> (<codeclass="docutils literal notranslate"><spanclass="pre">+createNPC</span></code> works too) that is callable by everyone <em>not</em> having the
<codeclass="docutils literal notranslate"><spanclass="pre">nonpcs</span></code> “<aclass="reference internal"href="../../../Components/Permissions.html"><spanclass="doc std std-doc">permission</span></a>” (in Evennia, a “permission” can just as well be used to
<aclass="reference internal"href="../../../Components/Locks.html"><spanclass="doc std std-doc">Locks</span></a> for more information about the lock system.</p>
<p>Note that we just give the object default permissions (by not specifying the <codeclass="docutils literal notranslate"><spanclass="pre">permissions</span></code> keyword
to the <codeclass="docutils literal notranslate"><spanclass="pre">create_object()</span></code> call). In some games one might want to give the NPC the same permissions
as the Character creating them, this might be a security risk though.</p>
<p>Add this command to your default cmdset the same way you did the <codeclass="docutils literal notranslate"><spanclass="pre">+attack</span></code> command earlier.
<codeclass="docutils literal notranslate"><spanclass="pre">@reload</span></code> and it will be available to test.</p>
<p>Since we re-used our custom character typeclass, our new NPC already has a <em>Power</em> value - it
defaults to 1. How do we change this?</p>
<p>There are a few ways we can do this. The easiest is to remember that the <codeclass="docutils literal notranslate"><spanclass="pre">power</span></code> attribute is just a
simple <aclass="reference internal"href="../../../Components/Attributes.html"><spanclass="doc std std-doc">Attribute</span></a> stored on the NPC object. So as a Builder or Admin we could set this
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">@set</span></code> command is too generally powerful though, and thus only available to staff. We will add a
custom command that only changes the things we want players to be allowed to change. We could in
principle re-work our old <codeclass="docutils literal notranslate"><spanclass="pre">+setpower</span></code> command, but let’s try something more useful. Let’s make a
<p>This is a slightly more complex command. It goes at the end of your <codeclass="docutils literal notranslate"><spanclass="pre">command.py</span></code> file as before.</p>
<spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You cannot change this NPC."</span><spanclass="p">)</span>
<spanclass="n">output</span><spanclass="o">=</span><spanclass="sa">f</span><spanclass="s2">"Properties of </span><spanclass="si">{</span><spanclass="n">npc</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2">:"</span>
<spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You may only change </span><spanclass="si">%s</span><spanclass="s2">."</span><spanclass="o">%</span>
<p><em>Note: If you wanted a player to use this command to change an on-object property like the NPC’s
name (the <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> property), you’d need to modify the command since “key” is not an Attribute (it is
not retrievable via <codeclass="docutils literal notranslate"><spanclass="pre">npc.attributes.get</span></code> but directly via <codeclass="docutils literal notranslate"><spanclass="pre">npc.key</span></code>). We leave this as an optional
<h3>Making the NPC do stuff - the +npc command<aclass="headerlink"href="#making-the-npc-do-stuff-the-npc-command"title="Permalink to this headline">¶</a></h3>
<spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You may not order this NPC to do anything."</span><spanclass="p">)</span>
<spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You told </span><spanclass="si">{</span><spanclass="n">npc</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2"> to do '</span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">cmdname</span><spanclass="si">}</span><spanclass="s2">'."</span><spanclass="p">)</span>
<p>Another thing to remember is however that this is a very simplistic way to control NPCs. Evennia
supports full puppeting very easily. An Account (assuming the “puppet” permission was set correctly)
could simply do <codeclass="docutils literal notranslate"><spanclass="pre">@ic</span><spanclass="pre">mynpc</span></code> and be able to play the game “as” that NPC. This is in fact just what
happens when an Account takes control of their normal Character as well.</p>
<p>This ends the tutorial. It looks like a lot of text but the amount of code you have to write is
actually relatively short. At this point you should have a basic skeleton of a game and a feel for
what is involved in coding your game.</p>
<p>From here on you could build a few more ChargenRooms and link that to a bigger grid. The <codeclass="docutils literal notranslate"><spanclass="pre">+setpower</span></code>
command can either be built upon or accompanied by many more to get a more elaborate character
generation.</p>
<p>The simple “Power” game mechanic should be easily expandable to something more full-fledged and
useful, same is true for the combat score principle. The <codeclass="docutils literal notranslate"><spanclass="pre">+attack</span></code> could be made to target a
specific player (or npc) and automatically compare their relevant attributes to determine a result.</p>
<p>To continue from here, you can take a look at the <aclass="reference internal"href="../Part1/Tutorial-World-Introduction.html"><spanclass="doc std std-doc">Tutorial World</span></a>. For
more specific ideas, see the <aclass="reference internal"href="../../Howto-Overview.html"><spanclass="doc std std-doc">other tutorials and hints</span></a> as well
as the <aclass="reference internal"href="../../../Components/Components-Overview.html"><spanclass="doc std std-doc">Evennia Component overview</span></a>.</p>