mirror of
https://github.com/evennia/evennia.git
synced 2026-03-17 21:36:30 +01:00
799 lines
No EOL
84 KiB
HTML
799 lines
No EOL
84 KiB
HTML
<!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>6. Character Generation — 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="7. In-game Rooms" href="Beginner-Tutorial-Rooms.html" />
|
||
<link rel="prev" title="5. Handling Equipment" href="Beginner-Tutorial-Equipment.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="Beginner-Tutorial-Rooms.html" title="7. In-game Rooms"
|
||
accesskey="N">next</a> |</li>
|
||
<li class="right" >
|
||
<a href="Beginner-Tutorial-Equipment.html" title="5. Handling Equipment"
|
||
accesskey="P">previous</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="../../../index.html">Evennia</a> »</li>
|
||
<li class="nav-item nav-item-1"><a href="../../Howtos-Overview.html" >Tutorials and How-To’s</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="../Beginner-Tutorial-Overview.html" >Beginner Tutorial</a> »</li>
|
||
<li class="nav-item nav-item-3"><a href="Beginner-Tutorial-Part3-Overview.html" accesskey="U">Part 3: How We Get There (Example Game)</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href=""><span class="section-number">6. </span>Character Generation</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="character-generation">
|
||
<h1><span class="section-number">6. </span>Character Generation<a class="headerlink" href="#character-generation" title="Link to this heading">¶</a></h1>
|
||
<p>In previous lessons we have established how a character looks. Now we need to give the player a chance to create one.</p>
|
||
<section id="how-it-will-work">
|
||
<h2><span class="section-number">6.1. </span>How it will work<a class="headerlink" href="#how-it-will-work" title="Link to this heading">¶</a></h2>
|
||
<p>A fresh Evennia install will automatically create a new Character with the same name as your Account when you log in. This is quick and simple and mimics older MUD styles. You could picture doing this, and then customizing the Character in-place.</p>
|
||
<p>We will be a little more sophisticated though. We want the user to be able to create a character using a menu when they log in.</p>
|
||
<p>We do this by editing <code class="docutils literal notranslate"><span class="pre">mygame/server/conf/settings.py</span></code> and adding the line</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>AUTO_CREATE_CHARACTER_WITH_ACCOUNT = False
|
||
</pre></div>
|
||
</div>
|
||
<p>When doing this, connecting with the game with a new account will land you in “OOC” mode. The ooc-version of <code class="docutils literal notranslate"><span class="pre">look</span></code> (sitting in the Account cmdset) will show a list of available characters if you have any. You can also enter <code class="docutils literal notranslate"><span class="pre">charcreate</span></code> to make a new character. The <code class="docutils literal notranslate"><span class="pre">charcreate</span></code> is a simple command coming with Evennia that just lets you make a new character with a given name and description. We will later modify that to kick off our chargen. For now we’ll just keep in mind that’s how we’ll start off the menu.</p>
|
||
<p>In <em>Knave</em>, most of the character-generation is random. This means this tutorial can be pretty
|
||
compact while still showing the basic idea. What we will create is a menu looking like this:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Silas</span>
|
||
|
||
<span class="n">STR</span> <span class="o">+</span><span class="mi">1</span>
|
||
<span class="n">DEX</span> <span class="o">+</span><span class="mi">2</span>
|
||
<span class="n">CON</span> <span class="o">+</span><span class="mi">1</span>
|
||
<span class="n">INT</span> <span class="o">+</span><span class="mi">3</span>
|
||
<span class="n">WIS</span> <span class="o">+</span><span class="mi">1</span>
|
||
<span class="n">CHA</span> <span class="o">+</span><span class="mi">2</span>
|
||
|
||
<span class="n">You</span> <span class="n">are</span> <span class="n">lanky</span> <span class="k">with</span> <span class="n">a</span> <span class="n">sunken</span> <span class="n">face</span> <span class="ow">and</span> <span class="n">filthy</span> <span class="n">hair</span><span class="p">,</span> <span class="n">breathy</span> <span class="n">speech</span><span class="p">,</span> <span class="ow">and</span> <span class="n">foreign</span> <span class="n">clothing</span><span class="o">.</span>
|
||
<span class="n">You</span> <span class="n">were</span> <span class="n">a</span> <span class="n">herbalist</span><span class="p">,</span> <span class="n">but</span> <span class="n">you</span> <span class="n">were</span> <span class="n">pursued</span> <span class="ow">and</span> <span class="n">ended</span> <span class="n">up</span> <span class="n">a</span> <span class="n">knave</span><span class="o">.</span> <span class="n">You</span> <span class="n">are</span> <span class="n">honest</span> <span class="n">but</span> <span class="n">also</span>
|
||
<span class="n">suspicious</span><span class="o">.</span> <span class="n">You</span> <span class="n">are</span> <span class="n">of</span> <span class="n">the</span> <span class="n">neutral</span> <span class="n">alignment</span><span class="o">.</span>
|
||
|
||
<span class="n">Your</span> <span class="n">belongings</span><span class="p">:</span>
|
||
<span class="n">Brigandine</span> <span class="n">armor</span><span class="p">,</span> <span class="n">ration</span><span class="p">,</span> <span class="n">ration</span><span class="p">,</span> <span class="n">sword</span><span class="p">,</span> <span class="n">torch</span><span class="p">,</span> <span class="n">torch</span><span class="p">,</span> <span class="n">torch</span><span class="p">,</span> <span class="n">torch</span><span class="p">,</span> <span class="n">torch</span><span class="p">,</span>
|
||
<span class="n">tinderbox</span><span class="p">,</span> <span class="n">chisel</span><span class="p">,</span> <span class="n">whistle</span>
|
||
|
||
<span class="o">----------------------------------------------------------------------------------------</span>
|
||
<span class="mf">1.</span> <span class="n">Change</span> <span class="n">your</span> <span class="n">name</span>
|
||
<span class="mf">2.</span> <span class="n">Swap</span> <span class="n">two</span> <span class="n">of</span> <span class="n">your</span> <span class="n">ability</span> <span class="n">scores</span> <span class="p">(</span><span class="n">once</span><span class="p">)</span>
|
||
<span class="mf">3.</span> <span class="n">Accept</span> <span class="ow">and</span> <span class="n">create</span> <span class="n">character</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>If you select 1, you get a new menu node:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Your</span> <span class="n">current</span> <span class="n">name</span> <span class="ow">is</span> <span class="n">Silas</span><span class="o">.</span> <span class="n">Enter</span> <span class="n">a</span> <span class="n">new</span> <span class="n">name</span> <span class="ow">or</span> <span class="n">leave</span> <span class="n">empty</span> <span class="n">to</span> <span class="n">abort</span><span class="o">.</span>
|
||
<span class="o">-----------------------------------------------------------------------------------------</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>You can now enter a new name. When pressing return you’ll get back to the first menu node
|
||
showing your character, now with the new name.</p>
|
||
<p>If you select 2, you go to another menu node:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>Your current abilities:
|
||
|
||
STR +1
|
||
DEX +2
|
||
CON +1
|
||
INT +3
|
||
WIS +1
|
||
CHA +2
|
||
|
||
You can swap the values of two abilities around.
|
||
You can only do this once, so choose carefully!
|
||
|
||
To swap the values of e.g. STR and INT, write 'STR INT'. Empty to abort.
|
||
------------------------------------------------------------------------------------------
|
||
</pre></div>
|
||
</div>
|
||
<p>If you enter <code class="docutils literal notranslate"><span class="pre">WIS</span> <span class="pre">CHA</span></code> here, WIS will become <code class="docutils literal notranslate"><span class="pre">+2</span></code> and <code class="docutils literal notranslate"><span class="pre">CHA</span></code> <code class="docutils literal notranslate"><span class="pre">+1</span></code>. You will then again go back to the main node to see your new character, but this time the option to swap will no longer be available (you can only do it once).</p>
|
||
<p>If you finally select the <code class="docutils literal notranslate"><span class="pre">Accept</span> <span class="pre">and</span> <span class="pre">create</span> <span class="pre">character</span></code> option, the character will be created and you’ll leave the menu;</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Character was created!
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="random-tables">
|
||
<h2><span class="section-number">6.2. </span>Random tables<a class="headerlink" href="#random-tables" title="Link to this heading">¶</a></h2>
|
||
<aside class="sidebar">
|
||
<p>Full Knave random tables are found in
|
||
<a class="reference internal" href="../../../api/evennia.contrib.tutorials.evadventure.random_tables.html"><span class="std std-doc">evennia/contrib/tutorials/evadventure/random_tables.py</span></a>.</p>
|
||
</aside>
|
||
<blockquote>
|
||
<div><p>Make a new module <code class="docutils literal notranslate"><span class="pre">mygame/evadventure/random_tables.py</span></code>.</p>
|
||
</div></blockquote>
|
||
<p>Since most of <em>Knave</em>’s character generation is random we will need to roll on random tables
|
||
from the <em>Knave</em> rulebook. While we added the ability to roll on a random table back in the
|
||
<a class="reference internal" href="Beginner-Tutorial-Rules.html"><span class="std std-doc">Rules Tutorial</span></a>, we haven’t added the relevant tables yet.</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/evadventure/random_tables.py</span>
|
||
|
||
<span class="n">chargen_tables</span> <span class="o">=</span> <span class="p">{</span>
|
||
<span class="s2">"physique"</span><span class="p">:</span> <span class="p">[</span>
|
||
<span class="s2">"athletic"</span><span class="p">,</span> <span class="s2">"brawny"</span><span class="p">,</span> <span class="s2">"corpulent"</span><span class="p">,</span> <span class="s2">"delicate"</span><span class="p">,</span> <span class="s2">"gaunt"</span><span class="p">,</span> <span class="s2">"hulking"</span><span class="p">,</span> <span class="s2">"lanky"</span><span class="p">,</span>
|
||
<span class="s2">"ripped"</span><span class="p">,</span> <span class="s2">"rugged"</span><span class="p">,</span> <span class="s2">"scrawny"</span><span class="p">,</span> <span class="s2">"short"</span><span class="p">,</span> <span class="s2">"sinewy"</span><span class="p">,</span> <span class="s2">"slender"</span><span class="p">,</span> <span class="s2">"flabby"</span><span class="p">,</span>
|
||
<span class="s2">"statuesque"</span><span class="p">,</span> <span class="s2">"stout"</span><span class="p">,</span> <span class="s2">"tiny"</span><span class="p">,</span> <span class="s2">"towering"</span><span class="p">,</span> <span class="s2">"willowy"</span><span class="p">,</span> <span class="s2">"wiry"</span><span class="p">,</span>
|
||
<span class="p">],</span>
|
||
<span class="s2">"face"</span><span class="p">:</span> <span class="p">[</span>
|
||
<span class="s2">"bloated"</span><span class="p">,</span> <span class="s2">"blunt"</span><span class="p">,</span> <span class="s2">"bony"</span><span class="p">,</span> <span class="c1"># ...</span>
|
||
<span class="p">],</span> <span class="c1"># ...</span>
|
||
<span class="p">}</span>
|
||
|
||
</pre></div>
|
||
</div>
|
||
<p>The tables are just copied from the <em>Knave</em> rules. We group the aspects in a dict
|
||
<code class="docutils literal notranslate"><span class="pre">character_generation</span></code> to separate chargen-only tables from other random tables we’ll also
|
||
keep in here.</p>
|
||
</section>
|
||
<section id="storing-state-of-the-menu">
|
||
<h2><span class="section-number">6.3. </span>Storing state of the menu<a class="headerlink" href="#storing-state-of-the-menu" title="Link to this heading">¶</a></h2>
|
||
<aside class="sidebar">
|
||
<p>There is a full implementation of the chargen in
|
||
<a class="reference internal" href="../../../api/evennia.contrib.tutorials.evadventure.chargen.html"><span class="std std-doc">evennia/contrib/tutorials/evadventure/chargen.py</span></a>.</p>
|
||
</aside>
|
||
<blockquote>
|
||
<div><p>create a new module <code class="docutils literal notranslate"><span class="pre">mygame/evadventure/chargen.py</span></code>.</p>
|
||
</div></blockquote>
|
||
<p>During character generation we will need an entity to store/retain the changes, like a
|
||
‘temporary character sheet’.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/evadventure/chargen.py</span>
|
||
|
||
<span class="kn">from</span><span class="w"> </span><span class="nn">.random_tables</span><span class="w"> </span><span class="kn">import</span> <span class="n">chargen_tables</span>
|
||
<span class="kn">from</span><span class="w"> </span><span class="nn">.rules</span><span class="w"> </span><span class="kn">import</span> <span class="n">dice</span>
|
||
|
||
<span class="k">class</span><span class="w"> </span><span class="nc">TemporaryCharacterSheet</span><span class="p">:</span>
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">_random_ability</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="nb">min</span><span class="p">(</span><span class="n">dice</span><span class="o">.</span><span class="n">roll</span><span class="p">(</span><span class="s2">"1d6"</span><span class="p">),</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll</span><span class="p">(</span><span class="s2">"1d6"</span><span class="p">),</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll</span><span class="p">(</span><span class="s2">"1d6"</span><span class="p">))</span>
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">ability_changes</span> <span class="o">=</span> <span class="mi">0</span> <span class="c1"># how many times we tried swap abilities</span>
|
||
|
||
<span class="c1"># name will likely be modified later</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d282"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"name"</span><span class="p">])</span>
|
||
|
||
<span class="c1"># base attribute values</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">strength</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_random_ability</span><span class="p">()</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">dexterity</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_random_ability</span><span class="p">()</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">constitution</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_random_ability</span><span class="p">()</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">intelligence</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_random_ability</span><span class="p">()</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">wisdom</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_random_ability</span><span class="p">()</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">charisma</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_random_ability</span><span class="p">()</span>
|
||
|
||
<span class="c1"># physical attributes (only for rp purposes)</span>
|
||
<span class="n">physique</span> <span class="o">=</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"physique"</span><span class="p">])</span>
|
||
<span class="n">face</span> <span class="o">=</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"face"</span><span class="p">])</span>
|
||
<span class="n">skin</span> <span class="o">=</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"skin"</span><span class="p">])</span>
|
||
<span class="n">hair</span> <span class="o">=</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"hair"</span><span class="p">])</span>
|
||
<span class="n">clothing</span> <span class="o">=</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"clothing"</span><span class="p">])</span>
|
||
<span class="n">speech</span> <span class="o">=</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"speech"</span><span class="p">])</span>
|
||
<span class="n">virtue</span> <span class="o">=</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"virtue"</span><span class="p">])</span>
|
||
<span class="n">vice</span> <span class="o">=</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"vice"</span><span class="p">])</span>
|
||
<span class="n">background</span> <span class="o">=</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"background"</span><span class="p">])</span>
|
||
<span class="n">misfortune</span> <span class="o">=</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"misfortune"</span><span class="p">])</span>
|
||
<span class="n">alignment</span> <span class="o">=</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"alignment"</span><span class="p">])</span>
|
||
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">desc</span> <span class="o">=</span> <span class="p">(</span>
|
||
<span class="sa">f</span><span class="s2">"You are </span><span class="si">{</span><span class="n">physique</span><span class="si">}</span><span class="s2"> with a </span><span class="si">{</span><span class="n">face</span><span class="si">}</span><span class="s2"> face, </span><span class="si">{</span><span class="n">skin</span><span class="si">}</span><span class="s2"> skin, </span><span class="si">{</span><span class="n">hair</span><span class="si">}</span><span class="s2"> hair, </span><span class="si">{</span><span class="n">speech</span><span class="si">}</span><span class="s2"> speech,"</span>
|
||
<span class="sa">f</span><span class="s2">" and </span><span class="si">{</span><span class="n">clothing</span><span class="si">}</span><span class="s2"> clothing. You were a </span><span class="si">{</span><span class="n">background</span><span class="o">.</span><span class="n">title</span><span class="p">()</span><span class="si">}</span><span class="s2">, but you were"</span>
|
||
<span class="sa">f</span><span class="s2">" </span><span class="si">{</span><span class="n">misfortune</span><span class="si">}</span><span class="s2"> and ended up a knave. You are </span><span class="si">{</span><span class="n">virtue</span><span class="si">}</span><span class="s2"> but also </span><span class="si">{</span><span class="n">vice</span><span class="si">}</span><span class="s2">. You are of the"</span>
|
||
<span class="sa">f</span><span class="s2">" </span><span class="si">{</span><span class="n">alignment</span><span class="si">}</span><span class="s2"> alignment."</span>
|
||
<span class="p">)</span>
|
||
|
||
<span class="c1">#</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">hp_max</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll</span><span class="p">(</span><span class="s2">"1d8"</span><span class="p">))</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">hp</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">hp_max</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">xp</span> <span class="o">=</span> <span class="mi">0</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">level</span> <span class="o">=</span> <span class="mi">1</span>
|
||
|
||
<span class="c1"># random equipment</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">armor</span> <span class="o">=</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"armor"</span><span class="p">])</span>
|
||
|
||
<span class="n">_helmet_and_shield</span> <span class="o">=</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"helmets and shields"</span><span class="p">])</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">helmet</span> <span class="o">=</span> <span class="s2">"helmet"</span> <span class="k">if</span> <span class="s2">"helmet"</span> <span class="ow">in</span> <span class="n">_helmet_and_shield</span> <span class="k">else</span> <span class="s2">"none"</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">shield</span> <span class="o">=</span> <span class="s2">"shield"</span> <span class="k">if</span> <span class="s2">"shield"</span> <span class="ow">in</span> <span class="n">_helmet_and_shield</span> <span class="k">else</span> <span class="s2">"none"</span>
|
||
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">weapon</span> <span class="o">=</span> <span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"starting weapon"</span><span class="p">])</span>
|
||
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">backpack</span> <span class="o">=</span> <span class="p">[</span>
|
||
<span class="s2">"ration"</span><span class="p">,</span>
|
||
<span class="s2">"ration"</span><span class="p">,</span>
|
||
<span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"dungeoning gear"</span><span class="p">]),</span>
|
||
<span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"dungeoning gear"</span><span class="p">]),</span>
|
||
<span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"general gear 1"</span><span class="p">]),</span>
|
||
<span class="n">dice</span><span class="o">.</span><span class="n">roll_random_table</span><span class="p">(</span><span class="s2">"1d20"</span><span class="p">,</span> <span class="n">chargen_tables</span><span class="p">[</span><span class="s2">"general gear 2"</span><span class="p">]),</span>
|
||
<span class="p">]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Here we have followed the <em>Knave</em> rulebook to randomize abilities, description and equipment. The <code class="docutils literal notranslate"><span class="pre">dice.roll()</span></code> and <code class="docutils literal notranslate"><span class="pre">dice.roll_random_table</span></code> methods now become very useful! Everything here should be easy to follow.</p>
|
||
<p>The main difference from baseline <em>Knave</em> is that we make a table of “starting weapon” (in Knave you can pick whatever you like).</p>
|
||
<p>We also initialize <code class="docutils literal notranslate"><span class="pre">.ability_changes</span> <span class="pre">=</span> <span class="pre">0</span></code>. Knave only allows us to swap the values of two
|
||
Abilities <em>once</em>. We will use this to know if it has been done or not.</p>
|
||
<section id="showing-the-sheet">
|
||
<h3><span class="section-number">6.3.1. </span>Showing the sheet<a class="headerlink" href="#showing-the-sheet" title="Link to this heading">¶</a></h3>
|
||
<p>Now that we have our temporary character sheet, we should make it easy to visualize it.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/evadventure/chargen.py</span>
|
||
|
||
<span class="n">_TEMP_SHEET</span> <span class="o">=</span> <span class="s2">"""</span>
|
||
<span class="si">{name}</span>
|
||
|
||
<span class="s2">STR +</span><span class="si">{strength}</span>
|
||
<span class="s2">DEX +</span><span class="si">{dexterity}</span>
|
||
<span class="s2">CON +</span><span class="si">{constitution}</span>
|
||
<span class="s2">INT +</span><span class="si">{intelligence}</span>
|
||
<span class="s2">WIS +</span><span class="si">{wisdom}</span>
|
||
<span class="s2">CHA +</span><span class="si">{charisma}</span>
|
||
|
||
<span class="si">{description}</span>
|
||
|
||
<span class="s2">Your belongings:</span>
|
||
<span class="si">{equipment}</span>
|
||
<span class="s2">"""</span>
|
||
|
||
<span class="k">class</span><span class="w"> </span><span class="nc">TemporaryCharacterSheet</span><span class="p">:</span>
|
||
|
||
<span class="c1"># ...</span>
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">show_sheet</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="n">equipment</span> <span class="o">=</span> <span class="p">(</span>
|
||
<span class="nb">str</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
|
||
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">armor</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">helmet</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">shield</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">weapon</span><span class="p">]</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">backpack</span>
|
||
<span class="k">if</span> <span class="n">item</span>
|
||
<span class="p">)</span>
|
||
|
||
<span class="k">return</span> <span class="n">_TEMP_SHEET</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
|
||
<span class="n">name</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
||
<span class="n">strength</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">strength</span><span class="p">,</span>
|
||
<span class="n">dexterity</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">dexterity</span><span class="p">,</span>
|
||
<span class="n">constitution</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">constitution</span><span class="p">,</span>
|
||
<span class="n">intelligence</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">intelligence</span><span class="p">,</span>
|
||
<span class="n">wisdom</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">wisdom</span><span class="p">,</span>
|
||
<span class="n">charisma</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">charisma</span><span class="p">,</span>
|
||
<span class="n">description</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">desc</span><span class="p">,</span>
|
||
<span class="n">equipment</span><span class="o">=</span><span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">equipment</span><span class="p">),</span>
|
||
<span class="p">)</span>
|
||
|
||
</pre></div>
|
||
</div>
|
||
<p>The new <code class="docutils literal notranslate"><span class="pre">show_sheet</span></code> method collect the data from the temporary sheet and return it in a pretty form. Making a ‘template’ string like <code class="docutils literal notranslate"><span class="pre">_TEMP_SHEET</span></code> makes it easier to change things later if you want to change how things look.</p>
|
||
</section>
|
||
<section id="apply-character">
|
||
<h3><span class="section-number">6.3.2. </span>Apply character<a class="headerlink" href="#apply-character" title="Link to this heading">¶</a></h3>
|
||
<p>Once we are happy with our character, we need to actually create it with the stats we chose.
|
||
This is a bit more involved.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/evadventure/chargen.py</span>
|
||
|
||
<span class="c1"># ...</span>
|
||
|
||
<span class="kn">from</span><span class="w"> </span><span class="nn">.characters</span><span class="w"> </span><span class="kn">import</span> <span class="n">EvAdventureCharacter</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="kn">from</span><span class="w"> </span><span class="nn">evennia.prototypes.spawner</span><span class="w"> </span><span class="kn">import</span> <span class="n">spawn</span>
|
||
|
||
|
||
<span class="k">class</span><span class="w"> </span><span class="nc">TemporaryCharacterSheet</span><span class="p">:</span>
|
||
|
||
<span class="c1"># ...</span>
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">apply</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="c1"># create character object with given abilities</span>
|
||
<span class="n">new_character</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span>
|
||
<span class="n">EvAdventureCharacter</span><span class="p">,</span>
|
||
<span class="n">key</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
||
<span class="n">attrs</span><span class="o">=</span><span class="p">(</span>
|
||
<span class="p">(</span><span class="s2">"strength"</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">strength</span><span class="p">),</span>
|
||
<span class="p">(</span><span class="s2">"dexterity"</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dexterity</span><span class="p">),</span>
|
||
<span class="p">(</span><span class="s2">"constitution"</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">constitution</span><span class="p">),</span>
|
||
<span class="p">(</span><span class="s2">"intelligence"</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">intelligence</span><span class="p">),</span>
|
||
<span class="p">(</span><span class="s2">"wisdom"</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">wisdom</span><span class="p">),</span>
|
||
<span class="p">(</span><span class="s2">"charisma"</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">wisdom</span><span class="p">),</span>
|
||
<span class="p">(</span><span class="s2">"hp"</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">hp</span><span class="p">),</span>
|
||
<span class="p">(</span><span class="s2">"hp_max"</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">hp_max</span><span class="p">),</span>
|
||
<span class="p">(</span><span class="s2">"desc"</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">desc</span><span class="p">),</span>
|
||
<span class="p">),</span>
|
||
<span class="p">)</span>
|
||
<span class="c1"># spawn equipment (will require prototypes created before it works)</span>
|
||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">weapon</span><span class="p">:</span>
|
||
<span class="n">weapon</span> <span class="o">=</span> <span class="n">spawn</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">weapon</span><span class="p">)</span>
|
||
<span class="n">new_character</span><span class="o">.</span><span class="n">equipment</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">weapon</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">shield</span><span class="p">:</span>
|
||
<span class="n">shield</span> <span class="o">=</span> <span class="n">spawn</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">shield</span><span class="p">)</span>
|
||
<span class="n">new_character</span><span class="o">.</span><span class="n">equipment</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">shield</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">armor</span><span class="p">:</span>
|
||
<span class="n">armor</span> <span class="o">=</span> <span class="n">spawn</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">armor</span><span class="p">)</span>
|
||
<span class="n">new_character</span><span class="o">.</span><span class="n">equipment</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">armor</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">helmet</span><span class="p">:</span>
|
||
<span class="n">helmet</span> <span class="o">=</span> <span class="n">spawn</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">helmet</span><span class="p">)</span>
|
||
<span class="n">new_character</span><span class="o">.</span><span class="n">equipment</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">helmet</span><span class="p">)</span>
|
||
|
||
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">backpack</span><span class="p">:</span>
|
||
<span class="n">item</span> <span class="o">=</span> <span class="n">spawn</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
|
||
<span class="n">new_character</span><span class="o">.</span><span class="n">equipment</span><span class="o">.</span><span class="n">store</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
|
||
|
||
<span class="k">return</span> <span class="n">new_character</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>We use <code class="docutils literal notranslate"><span class="pre">create_object</span></code> to create a new <code class="docutils literal notranslate"><span class="pre">EvAdventureCharacter</span></code>. We feed it with all relevant data from the temporary character sheet. This is when these become an actual character.</p>
|
||
<aside class="sidebar">
|
||
<p>A prototype is basically a <code class="docutils literal notranslate"><span class="pre">dict</span></code> describing how the object should be created. Since
|
||
it’s just a piece of code, it can stored in a Python module and used to quickly <em>spawn</em> (create)
|
||
things from those prototypes.</p>
|
||
</aside>
|
||
<p>Each piece of equipment is an object in in its own right. We will here assume that all game
|
||
items are defined as <a class="reference internal" href="../../../Components/Prototypes.html"><span class="std std-doc">Prototypes</span></a> keyed to its name, such as “sword”, “brigandine
|
||
armor” etc.</p>
|
||
<p>We haven’t actually created those prototypes yet, so for now we’ll need to assume they are there. Once a piece of equipment has been spawned, we make sure to move it into the <code class="docutils literal notranslate"><span class="pre">EquipmentHandler</span></code> we created in the <a class="reference internal" href="Beginner-Tutorial-Equipment.html"><span class="std std-doc">Equipment lesson</span></a>.</p>
|
||
</section>
|
||
</section>
|
||
<section id="initializing-evmenu">
|
||
<h2><span class="section-number">6.4. </span>Initializing EvMenu<a class="headerlink" href="#initializing-evmenu" title="Link to this heading">¶</a></h2>
|
||
<p>Evennia comes with a full menu-generation system based on <a class="reference internal" href="../../../Components/Command-Sets.html"><span class="std std-doc">Command sets</span></a>, called
|
||
<a class="reference internal" href="../../../Components/EvMenu.html"><span class="std std-doc">EvMenu</span></a>.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/evadventure/chargen.py</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">EvMenu</span>
|
||
|
||
<span class="c1"># ...</span>
|
||
|
||
<span class="c1"># chargen menu</span>
|
||
|
||
|
||
<span class="c1"># this goes to the bottom of the module</span>
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">start_chargen</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">session</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""</span>
|
||
<span class="sd"> This is a start point for spinning up the chargen from a command later.</span>
|
||
|
||
<span class="sd"> """</span>
|
||
|
||
<span class="n">menutree</span> <span class="o">=</span> <span class="p">{}</span> <span class="c1"># TODO!</span>
|
||
|
||
<span class="c1"># this generates all random components of the character</span>
|
||
<span class="n">tmp_character</span> <span class="o">=</span> <span class="n">TemporaryCharacterSheet</span><span class="p">()</span>
|
||
|
||
<span class="n">EvMenu</span><span class="p">(</span>
|
||
<span class="n">caller</span><span class="p">,</span>
|
||
<span class="n">menutree</span><span class="p">,</span>
|
||
<span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span>
|
||
<span class="n">startnode</span><span class="o">=</span><span class="s2">"node_chargen"</span><span class="p">,</span>
|
||
<span class="n">startnode_input</span><span class="o">=</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="p">{</span><span class="s2">"tmp_character"</span><span class="p">:</span> <span class="n">tmp_character</span><span class="p">}),</span>
|
||
<span class="p">)</span>
|
||
|
||
</pre></div>
|
||
</div>
|
||
<p>This first function is what we will call from elsewhere (for example from a custom <code class="docutils literal notranslate"><span class="pre">charcreate</span></code> command) to kick the menu into gear.</p>
|
||
<p>It takes the <code class="docutils literal notranslate"><span class="pre">caller</span></code> (the one to want to start the menu) and a <code class="docutils literal notranslate"><span class="pre">session</span></code> argument. The latter will help track just which client-connection we are using (depending on Evennia settings, you could be connecting with multiple clients).</p>
|
||
<p>We create a <code class="docutils literal notranslate"><span class="pre">TemporaryCharacterSheet</span></code> and feed all this into <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code>. The <code class="docutils literal notranslate"><span class="pre">startnode</span></code> and <code class="docutils literal notranslate"><span class="pre">startnode_input</span></code> keywords makes sure to enter the menu at the “node_chargen” node (which we will create below) and call it with with the provided arguments.</p>
|
||
<p>The moment this happens, the user will be in the menu, there are no further steps needed.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">menutree</span></code> is what we’ll create next. It describes which menu ‘nodes’ are available to jump between.</p>
|
||
</section>
|
||
<section id="main-node-choosing-what-to-do">
|
||
<h2><span class="section-number">6.5. </span>Main Node: Choosing what to do<a class="headerlink" href="#main-node-choosing-what-to-do" title="Link to this heading">¶</a></h2>
|
||
<p>This is the first menu node. It will act as a central hub, from which one can choose different
|
||
actions.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/evadventure/chargen.py</span>
|
||
|
||
<span class="c1"># ...</span>
|
||
|
||
<span class="c1"># at the end of the module, but before the `start_chargen` function</span>
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">node_chargen</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
|
||
<span class="n">tmp_character</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s2">"tmp_character"</span><span class="p">]</span>
|
||
|
||
<span class="n">text</span> <span class="o">=</span> <span class="n">tmp_character</span><span class="o">.</span><span class="n">show_sheet</span><span class="p">()</span>
|
||
|
||
<span class="n">options</span> <span class="o">=</span> <span class="p">[</span>
|
||
<span class="p">{</span>
|
||
<span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"Change your name"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span><span class="s2">"node_change_name"</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
<span class="p">]</span>
|
||
<span class="k">if</span> <span class="n">tmp_character</span><span class="o">.</span><span class="n">ability_changes</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">:</span>
|
||
<span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
||
<span class="p">{</span>
|
||
<span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"Swap two of your ability scores (once)"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span><span class="s2">"node_swap_abilities"</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">),</span>
|
||
<span class="p">}</span>
|
||
<span class="p">)</span>
|
||
<span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
||
<span class="p">{</span>
|
||
<span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"Accept and create character"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span><span class="s2">"node_apply_character"</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">)</span>
|
||
<span class="p">},</span>
|
||
<span class="p">)</span>
|
||
|
||
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
|
||
|
||
<span class="c1"># ...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>A lot to unpack here! In Evennia, it’s convention to name your node-functions <code class="docutils literal notranslate"><span class="pre">node_*</span></code>. While
|
||
not required, it helps you track what is a node and not.</p>
|
||
<p>Every menu-node, should accept <code class="docutils literal notranslate"><span class="pre">caller,</span> <span class="pre">raw_string,</span> <span class="pre">**kwargs</span></code> as arguments. Here <code class="docutils literal notranslate"><span class="pre">caller</span></code> is the <code class="docutils literal notranslate"><span class="pre">caller</span></code> you passed into the <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> call. <code class="docutils literal notranslate"><span class="pre">raw_string</span></code> is the input given by the user in order to <em>get to this node</em>, so currently empty. The <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> are all extra keyword arguments passed into <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code>. They can also be passed between nodes. In this case, we passed the keyword <code class="docutils literal notranslate"><span class="pre">tmp_character</span></code> to <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code>. We now have the temporary character sheet available in the node!</p>
|
||
<blockquote>
|
||
<div><p>Note that above we created the menu with the <code class="docutils literal notranslate"><span class="pre">startnode="node_chargen"</span></code> and the tuple <code class="docutils literal notranslate"><span class="pre">startnode_input=("",</span> <span class="pre">{"tmp_character":</span> <span class="pre">tmp_character})</span></code>. Assuming we register the above function as the node <code class="docutils literal notranslate"><span class="pre">"node_chargen"</span></code>, it will start out being called as <code class="docutils literal notranslate"><span class="pre">node_chargen(caller,</span> <span class="pre">"",</span> <span class="pre">tmp_character=tmp_character)</span></code> (EvMenu will add <code class="docutils literal notranslate"><span class="pre">caller</span></code> on its own). This is one way we can pass outside data into the menu as it starts.</p>
|
||
</div></blockquote>
|
||
<p>An <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> node must always return two things - <code class="docutils literal notranslate"><span class="pre">text</span></code> and <code class="docutils literal notranslate"><span class="pre">options</span></code>. The <code class="docutils literal notranslate"><span class="pre">text</span></code> is what will
|
||
show to the user when looking at this node. The <code class="docutils literal notranslate"><span class="pre">options</span></code> are, well, what options should be
|
||
presented to move on from here to some other place.</p>
|
||
<p>For the text, we simply get a pretty-print of the temporary character sheet. A single option is defined as a <code class="docutils literal notranslate"><span class="pre">dict</span></code> like this:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="p">{</span>
|
||
<span class="s2">"key"</span><span class="p">:</span> <span class="p">(</span><span class="s2">"name"</span><span class="o">.</span> <span class="s2">"alias1"</span><span class="p">,</span> <span class="s2">"alias2"</span><span class="p">,</span> <span class="o">...</span><span class="p">),</span> <span class="c1"># if skipped, auto-show a number</span>
|
||
<span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"text to describe what happens when selecting option"</span><span class="p">,</span><span class="o">.</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span><span class="s2">"name of node or a callable"</span><span class="p">,</span> <span class="n">kwargs_to_pass_into_next_node_or_callable</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Multiple option-dicts are returned in a list or tuple. The <code class="docutils literal notranslate"><span class="pre">goto</span></code> option-key is important to
|
||
understand. The job of this is to either point directly to another node (by giving its name), or
|
||
by pointing to a Python callable (like a function) <em>that then returns that name</em>. You can also
|
||
pass kwargs (as a dict). This will be made available as <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> in the callable or next node.</p>
|
||
<p>While an option can have a <code class="docutils literal notranslate"><span class="pre">key</span></code>, you can also skip it to just get a running number.</p>
|
||
<p>In our <code class="docutils literal notranslate"><span class="pre">node_chargen</span></code> node, we point to three nodes by name: <code class="docutils literal notranslate"><span class="pre">node_change_name</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">node_swap_abilities</span></code>, and <code class="docutils literal notranslate"><span class="pre">node_apply_character</span></code>. We also make sure to pass along <code class="docutils literal notranslate"><span class="pre">kwargs</span></code>
|
||
to each node, since that contains our temporary character sheet.</p>
|
||
<p>The middle of these options only appear if we haven’t already switched two abilities around - to know this, we check the <code class="docutils literal notranslate"><span class="pre">.ability_changes</span></code> property to make sure it’s still 0.</p>
|
||
</section>
|
||
<section id="node-changing-your-name">
|
||
<h2><span class="section-number">6.6. </span>Node: Changing your name<a class="headerlink" href="#node-changing-your-name" title="Link to this heading">¶</a></h2>
|
||
<p>This is where you end up if you opted to change your name in <code class="docutils literal notranslate"><span class="pre">node_chargen</span></code>.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/evadventure/chargen.py</span>
|
||
|
||
<span class="c1"># ...</span>
|
||
|
||
<span class="c1"># after previous node</span>
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">_update_name</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</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">"""</span>
|
||
<span class="sd"> Used by node_change_name below to check what user</span>
|
||
<span class="sd"> entered and update the name if appropriate.</span>
|
||
|
||
<span class="sd"> """</span>
|
||
<span class="k">if</span> <span class="n">raw_string</span><span class="p">:</span>
|
||
<span class="n">tmp_character</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s2">"tmp_character"</span><span class="p">]</span>
|
||
<span class="n">tmp_character</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">raw_string</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">.</span><span class="n">capitalize</span><span class="p">()</span>
|
||
|
||
<span class="k">return</span> <span class="s2">"node_chargen"</span><span class="p">,</span> <span class="n">kwargs</span>
|
||
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">node_change_name</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</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">"""</span>
|
||
<span class="sd"> Change the random name of the character.</span>
|
||
|
||
<span class="sd"> """</span>
|
||
<span class="n">tmp_character</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s2">"tmp_character"</span><span class="p">]</span>
|
||
|
||
<span class="n">text</span> <span class="o">=</span> <span class="p">(</span>
|
||
<span class="sa">f</span><span class="s2">"Your current name is |w</span><span class="si">{</span><span class="n">tmp_character</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">|n. "</span>
|
||
<span class="s2">"Enter a new name or leave empty to abort."</span>
|
||
<span class="p">)</span>
|
||
|
||
<span class="n">options</span> <span class="o">=</span> <span class="p">{</span>
|
||
<span class="s2">"key"</span><span class="p">:</span> <span class="s2">"_default"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span><span class="n">_update_name</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>There are two functions here - the menu node itself (<code class="docutils literal notranslate"><span class="pre">node_change_name</span></code>) and a
|
||
helper <em>goto_function</em> (<code class="docutils literal notranslate"><span class="pre">_update_name</span></code>) to handle the user’s input.</p>
|
||
<p>For the (single) option, we use a special <code class="docutils literal notranslate"><span class="pre">key</span></code> named <code class="docutils literal notranslate"><span class="pre">_default</span></code>. This makes this option
|
||
a catch-all: If the user enters something that does not match any other option, this is
|
||
the option that will be used. Since we have no other options here, we will always use this option no matter what the user enters.</p>
|
||
<p>Also note that the <code class="docutils literal notranslate"><span class="pre">goto</span></code> part of the option points to the <code class="docutils literal notranslate"><span class="pre">_update_name</span></code> callable rather than to
|
||
the name of a node. It’s important we keep passing <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> along to it!</p>
|
||
<p>When a user writes anything at this node, the <code class="docutils literal notranslate"><span class="pre">_update_name</span></code> callable will be called. This has
|
||
the same arguments as a node, but it is <em>not</em> a node - we will only use it to <em>figure out</em> which
|
||
node to go to next.</p>
|
||
<p>In <code class="docutils literal notranslate"><span class="pre">_update_name</span></code> we now have a use for the <code class="docutils literal notranslate"><span class="pre">raw_string</span></code> argument - this is what was written by the user on the previous node, remember? This is now either an empty string (meaning to ignore it) or the new name of the character.</p>
|
||
<p>A goto-function like <code class="docutils literal notranslate"><span class="pre">_update_name</span></code> must return the name of the next node to use. It can also
|
||
optionally return the <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> to pass into that node - we want to always do this, so we don’t
|
||
loose our temporary character sheet. Here we will always go back to the <code class="docutils literal notranslate"><span class="pre">node_chargen</span></code>.</p>
|
||
<blockquote>
|
||
<div><p>Hint: If returning <code class="docutils literal notranslate"><span class="pre">None</span></code> from a goto-callable, you will always return to the last node you
|
||
were at.</p>
|
||
</div></blockquote>
|
||
</section>
|
||
<section id="node-swapping-abilities-around">
|
||
<h2><span class="section-number">6.7. </span>Node: Swapping Abilities around<a class="headerlink" href="#node-swapping-abilities-around" title="Link to this heading">¶</a></h2>
|
||
<p>You get here by selecting the second option from the <code class="docutils literal notranslate"><span class="pre">node_chargen</span></code> node.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/evadventure/chargen.py</span>
|
||
|
||
<span class="c1"># ...</span>
|
||
|
||
<span class="c1"># after previous node</span>
|
||
|
||
<span class="n">_ABILITIES</span> <span class="o">=</span> <span class="p">{</span>
|
||
<span class="s2">"STR"</span><span class="p">:</span> <span class="s2">"strength"</span><span class="p">,</span>
|
||
<span class="s2">"DEX"</span><span class="p">:</span> <span class="s2">"dexterity"</span><span class="p">,</span>
|
||
<span class="s2">"CON"</span><span class="p">:</span> <span class="s2">"constitution"</span><span class="p">,</span>
|
||
<span class="s2">"INT"</span><span class="p">:</span> <span class="s2">"intelligence"</span><span class="p">,</span>
|
||
<span class="s2">"WIS"</span><span class="p">:</span> <span class="s2">"wisdom"</span><span class="p">,</span>
|
||
<span class="s2">"CHA"</span><span class="p">:</span> <span class="s2">"charisma"</span><span class="p">,</span>
|
||
<span class="p">}</span>
|
||
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">_swap_abilities</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</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">"""</span>
|
||
<span class="sd"> Used by node_swap_abilities to parse the user's input and swap ability</span>
|
||
<span class="sd"> values.</span>
|
||
|
||
<span class="sd"> """</span>
|
||
<span class="k">if</span> <span class="n">raw_string</span><span class="p">:</span>
|
||
<span class="n">abi1</span><span class="p">,</span> <span class="o">*</span><span class="n">abi2</span> <span class="o">=</span> <span class="n">raw_string</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">" "</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">abi2</span><span class="p">:</span>
|
||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"That doesn't look right."</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="kc">None</span><span class="p">,</span> <span class="n">kwargs</span>
|
||
<span class="n">abi2</span> <span class="o">=</span> <span class="n">abi2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||
<span class="n">abi1</span><span class="p">,</span> <span class="n">abi2</span> <span class="o">=</span> <span class="n">abi1</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span><span class="o">.</span><span class="n">strip</span><span class="p">(),</span> <span class="n">abi2</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
|
||
<span class="k">if</span> <span class="n">abi1</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">_ABILITIES</span> <span class="ow">or</span> <span class="n">abi2</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">_ABILITIES</span><span class="p">:</span>
|
||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Not a familiar set of abilites."</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="kc">None</span><span class="p">,</span> <span class="n">kwargs</span>
|
||
|
||
<span class="c1"># looks okay = swap values. We need to convert STR to strength etc</span>
|
||
<span class="n">tmp_character</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s2">"tmp_character"</span><span class="p">]</span>
|
||
<span class="n">abi1</span> <span class="o">=</span> <span class="n">_ABILITIES</span><span class="p">[</span><span class="n">abi1</span><span class="p">]</span>
|
||
<span class="n">abi2</span> <span class="o">=</span> <span class="n">_ABILITIES</span><span class="p">[</span><span class="n">abi2</span><span class="p">]</span>
|
||
<span class="n">abival1</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">tmp_character</span><span class="p">,</span> <span class="n">abi1</span><span class="p">)</span>
|
||
<span class="n">abival2</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">tmp_character</span><span class="p">,</span> <span class="n">abi2</span><span class="p">)</span>
|
||
|
||
<span class="nb">setattr</span><span class="p">(</span><span class="n">tmp_character</span><span class="p">,</span> <span class="n">abi1</span><span class="p">,</span> <span class="n">abival2</span><span class="p">)</span>
|
||
<span class="nb">setattr</span><span class="p">(</span><span class="n">tmp_character</span><span class="p">,</span> <span class="n">abi2</span><span class="p">,</span> <span class="n">abival1</span><span class="p">)</span>
|
||
|
||
<span class="n">tmp_character</span><span class="o">.</span><span class="n">ability_changes</span> <span class="o">+=</span> <span class="mi">1</span>
|
||
|
||
<span class="k">return</span> <span class="s2">"node_chargen"</span><span class="p">,</span> <span class="n">kwargs</span>
|
||
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">node_swap_abilities</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</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">"""</span>
|
||
<span class="sd"> One is allowed to swap the values of two abilities around, once.</span>
|
||
|
||
<span class="sd"> """</span>
|
||
<span class="n">tmp_character</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s2">"tmp_character"</span><span class="p">]</span>
|
||
|
||
<span class="n">text</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"""</span>
|
||
<span class="s2">Your current abilities:</span>
|
||
|
||
<span class="s2">STR +</span><span class="si">{</span><span class="n">tmp_character</span><span class="o">.</span><span class="n">strength</span><span class="si">}</span>
|
||
<span class="s2">DEX +</span><span class="si">{</span><span class="n">tmp_character</span><span class="o">.</span><span class="n">dexterity</span><span class="si">}</span>
|
||
<span class="s2">CON +</span><span class="si">{</span><span class="n">tmp_character</span><span class="o">.</span><span class="n">constitution</span><span class="si">}</span>
|
||
<span class="s2">INT +</span><span class="si">{</span><span class="n">tmp_character</span><span class="o">.</span><span class="n">intelligence</span><span class="si">}</span>
|
||
<span class="s2">WIS +</span><span class="si">{</span><span class="n">tmp_character</span><span class="o">.</span><span class="n">wisdom</span><span class="si">}</span>
|
||
<span class="s2">CHA +</span><span class="si">{</span><span class="n">tmp_character</span><span class="o">.</span><span class="n">charisma</span><span class="si">}</span>
|
||
|
||
<span class="s2">You can swap the values of two abilities around.</span>
|
||
<span class="s2">You can only do this once, so choose carefully!</span>
|
||
|
||
<span class="s2">To swap the values of e.g. STR and INT, write |wSTR INT|n. Empty to abort.</span>
|
||
<span class="s2">"""</span>
|
||
|
||
<span class="n">options</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"key"</span><span class="p">:</span> <span class="s2">"_default"</span><span class="p">,</span> <span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span><span class="n">_swap_abilities</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">)}</span>
|
||
|
||
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This is more code, but the logic is the same - we have a node (<code class="docutils literal notranslate"><span class="pre">node_swap_abilities</span></code>) and
|
||
and a goto-callable helper (<code class="docutils literal notranslate"><span class="pre">_swap_abilities</span></code>). We catch everything the user writes on the
|
||
node (such as <code class="docutils literal notranslate"><span class="pre">WIS</span> <span class="pre">CON</span></code>) and feed it into the helper.</p>
|
||
<p>In <code class="docutils literal notranslate"><span class="pre">_swap_abilities</span></code>, we need to analyze the <code class="docutils literal notranslate"><span class="pre">raw_string</span></code> from the user to see what they
|
||
want to do.</p>
|
||
<p>Most code in the helper is validating the user didn’t enter nonsense. If they did,
|
||
we use <code class="docutils literal notranslate"><span class="pre">caller.msg()</span></code> to tell them and then return <code class="docutils literal notranslate"><span class="pre">None,</span> <span class="pre">kwargs</span></code>, which re-runs the same node (the name-selection) all over again.</p>
|
||
<p>Since we want users to be able to write “CON” instead of the longer “constitution”, we need a mapping <code class="docutils literal notranslate"><span class="pre">_ABILITIES</span></code> to easily convert between the two (it’s stored as <code class="docutils literal notranslate"><span class="pre">consitution</span></code> on the temporary character sheet). Once we know which abilities they want to swap, we do so and tick up the <code class="docutils literal notranslate"><span class="pre">.ability_changes</span></code> counter. This means this option will no longer be available from the main node.</p>
|
||
<p>Finally, we return to <code class="docutils literal notranslate"><span class="pre">node_chargen</span></code> again.</p>
|
||
</section>
|
||
<section id="node-creating-the-character">
|
||
<h2><span class="section-number">6.8. </span>Node: Creating the Character<a class="headerlink" href="#node-creating-the-character" title="Link to this heading">¶</a></h2>
|
||
<p>We get here from the main node by opting to finish chargen.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">node_apply_character</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</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">"""</span>
|
||
<span class="sd"> End chargen and create the character. We will also puppet it.</span>
|
||
|
||
<span class="sd"> """</span>
|
||
<span class="n">tmp_character</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s2">"tmp_character"</span><span class="p">]</span>
|
||
<span class="n">new_character</span> <span class="o">=</span> <span class="n">tmp_character</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="n">caller</span><span class="p">)</span>
|
||
|
||
<span class="n">caller</span><span class="o">.</span><span class="n">account</span><span class="o">.</span><span class="n">add_character</span><span class="p">(</span><span class="n">new_character</span><span class="p">)</span>
|
||
|
||
<span class="n">text</span> <span class="o">=</span> <span class="s2">"Character created!"</span>
|
||
|
||
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="kc">None</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>When entering the node, we will take the Temporary character sheet and use its <code class="docutils literal notranslate"><span class="pre">.apply</span></code> method to create a new Character with all equipment.</p>
|
||
<p>This is what is called an <em>end node</em>, because it returns <code class="docutils literal notranslate"><span class="pre">None</span></code> instead of options. After this, the menu will exit. We will be back to the default character selection screen. The characters found on that screen are the ones listed in the <code class="docutils literal notranslate"><span class="pre">_playable_characters</span></code> Attribute, so we need to also the new character to it.</p>
|
||
</section>
|
||
<section id="tying-the-nodes-together">
|
||
<h2><span class="section-number">6.9. </span>Tying the nodes together<a class="headerlink" href="#tying-the-nodes-together" title="Link to this heading">¶</a></h2>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">start_chargen</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">session</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""</span>
|
||
<span class="sd"> This is a start point for spinning up the chargen from a command later.</span>
|
||
|
||
<span class="sd"> """</span>
|
||
<span class="n">menutree</span> <span class="o">=</span> <span class="p">{</span> <span class="c1"># <----- can now add this!</span>
|
||
<span class="s2">"node_chargen"</span><span class="p">:</span> <span class="n">node_chargen</span><span class="p">,</span>
|
||
<span class="s2">"node_change_name"</span><span class="p">:</span> <span class="n">node_change_name</span><span class="p">,</span>
|
||
<span class="s2">"node_swap_abilities"</span><span class="p">:</span> <span class="n">node_swap_abilities</span><span class="p">,</span>
|
||
<span class="s2">"node_apply_character"</span><span class="p">:</span> <span class="n">node_apply_character</span><span class="p">,</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="c1"># this generates all random components of the character</span>
|
||
<span class="n">tmp_character</span> <span class="o">=</span> <span class="n">TemporaryCharacterSheet</span><span class="p">()</span>
|
||
|
||
<span class="n">EvMenu</span><span class="p">(</span>
|
||
<span class="n">caller</span><span class="p">,</span>
|
||
<span class="n">menutree</span><span class="p">,</span>
|
||
<span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span>
|
||
<span class="n">startnode</span><span class="o">=</span><span class="s2">"node_chargen"</span><span class="p">,</span> <span class="c1"># <-- make sure it's set!</span>
|
||
<span class="n">startnode_input</span><span class="o">=</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="p">{</span><span class="s2">"tmp_character"</span><span class="p">:</span> <span class="n">tmp_character</span><span class="p">}),</span>
|
||
<span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Now that we have all the nodes, we add them to the <code class="docutils literal notranslate"><span class="pre">menutree</span></code> we left empty before. We only add the nodes, <em>not</em> the goto-helpers! The keys we set in the <code class="docutils literal notranslate"><span class="pre">menutree</span></code> dictionary are the names we should use to point to nodes from inside the menu (and we did).</p>
|
||
<p>We also add a keyword argument <code class="docutils literal notranslate"><span class="pre">startnode</span></code> pointing to the <code class="docutils literal notranslate"><span class="pre">node_chargen</span></code> node. This tells EvMenu to first jump into that node when the menu is starting up.</p>
|
||
</section>
|
||
<section id="conclusions">
|
||
<h2><span class="section-number">6.10. </span>Conclusions<a class="headerlink" href="#conclusions" title="Link to this heading">¶</a></h2>
|
||
<p>This lesson taught us how to use <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> to make an interactive character generator. In an RPG more complex than <em>Knave</em>, the menu would be bigger and more intricate, but the same principles apply.</p>
|
||
<p>Together with the previous lessons we have now fished most of the basics around player
|
||
characters - how they store their stats, handle their equipment and how to create them.</p>
|
||
<p>In the next lesson we’ll address how EvAdventure <em>Rooms</em> work.</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="#">6. Character Generation</a><ul>
|
||
<li><a class="reference internal" href="#how-it-will-work">6.1. How it will work</a></li>
|
||
<li><a class="reference internal" href="#random-tables">6.2. Random tables</a></li>
|
||
<li><a class="reference internal" href="#storing-state-of-the-menu">6.3. Storing state of the menu</a><ul>
|
||
<li><a class="reference internal" href="#showing-the-sheet">6.3.1. Showing the sheet</a></li>
|
||
<li><a class="reference internal" href="#apply-character">6.3.2. Apply character</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#initializing-evmenu">6.4. Initializing EvMenu</a></li>
|
||
<li><a class="reference internal" href="#main-node-choosing-what-to-do">6.5. Main Node: Choosing what to do</a></li>
|
||
<li><a class="reference internal" href="#node-changing-your-name">6.6. Node: Changing your name</a></li>
|
||
<li><a class="reference internal" href="#node-swapping-abilities-around">6.7. Node: Swapping Abilities around</a></li>
|
||
<li><a class="reference internal" href="#node-creating-the-character">6.8. Node: Creating the Character</a></li>
|
||
<li><a class="reference internal" href="#tying-the-nodes-together">6.9. Tying the nodes together</a></li>
|
||
<li><a class="reference internal" href="#conclusions">6.10. Conclusions</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<div>
|
||
<h4>Previous topic</h4>
|
||
<p class="topless"><a href="Beginner-Tutorial-Equipment.html"
|
||
title="previous chapter"><span class="section-number">5. </span>Handling Equipment</a></p>
|
||
</div>
|
||
<div>
|
||
<h4>Next topic</h4>
|
||
<p class="topless"><a href="Beginner-Tutorial-Rooms.html"
|
||
title="next chapter"><span class="section-number">7. </span>In-game Rooms</a></p>
|
||
</div>
|
||
<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-Chargen.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/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="Beginner-Tutorial-Rooms.html" title="7. In-game Rooms"
|
||
>next</a> |</li>
|
||
<li class="right" >
|
||
<a href="Beginner-Tutorial-Equipment.html" title="5. Handling Equipment"
|
||
>previous</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="../../../index.html">Evennia</a> »</li>
|
||
<li class="nav-item nav-item-1"><a href="../../Howtos-Overview.html" >Tutorials and How-To’s</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="../Beginner-Tutorial-Overview.html" >Beginner Tutorial</a> »</li>
|
||
<li class="nav-item nav-item-3"><a href="Beginner-Tutorial-Part3-Overview.html" >Part 3: How We Get There (Example Game)</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href=""><span class="section-number">6. </span>Character Generation</a></li>
|
||
</ul>
|
||
</div>
|
||
<div class="footer" role="contentinfo">
|
||
© Copyright 2024, The Evennia developer community.
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
|
||
</div>
|
||
</body>
|
||
</html> |