mirror of
https://github.com/evennia/evennia.git
synced 2026-03-18 22:06:30 +01:00
1378 lines
No EOL
103 KiB
HTML
1378 lines
No EOL
103 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>EvMenu — Evennia 1.0-dev documentation</title>
|
||
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
|
||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||
<script src="../_static/jquery.js"></script>
|
||
<script src="../_static/underscore.js"></script>
|
||
<script src="../_static/doctools.js"></script>
|
||
<script src="../_static/language_data.js"></script>
|
||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||
<link rel="index" title="Index" href="../genindex.html" />
|
||
<link rel="search" title="Search" href="../search.html" />
|
||
</head><body>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>Navigation</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="General Index"
|
||
accesskey="I">index</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python Module Index"
|
||
>modules</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">EvMenu</a></li>
|
||
</ul>
|
||
<div class="develop">develop branch</div>
|
||
</div>
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<div class="section" id="evmenu">
|
||
<h1>EvMenu<a class="headerlink" href="#evmenu" title="Permalink to this headline">¶</a></h1>
|
||
<div class="section" id="introduction">
|
||
<h2>Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline">¶</a></h2>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> utility class is located in
|
||
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/utils/evmenu.py">evennia/utils/evmenu.py</a>.
|
||
It allows for easily adding interactive menus to the game; for example to implement Character
|
||
creation, building commands or similar. Below is an example of offering NPC conversation choices:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">The</span> <span class="n">guard</span> <span class="n">looks</span> <span class="n">at</span> <span class="n">you</span> <span class="n">suspiciously</span><span class="o">.</span>
|
||
<span class="s2">"No one is supposed to be in here ..."</span>
|
||
<span class="n">he</span> <span class="n">says</span><span class="p">,</span> <span class="n">a</span> <span class="n">hand</span> <span class="n">on</span> <span class="n">his</span> <span class="n">weapon</span><span class="o">.</span>
|
||
<span class="n">_______________________________________________</span>
|
||
<span class="mf">1.</span> <span class="n">Try</span> <span class="n">to</span> <span class="n">bribe</span> <span class="n">him</span> <span class="p">[</span><span class="n">Cha</span> <span class="o">+</span> <span class="mi">10</span> <span class="n">gold</span><span class="p">]</span>
|
||
<span class="mf">2.</span> <span class="n">Convince</span> <span class="n">him</span> <span class="n">you</span> <span class="n">work</span> <span class="n">here</span> <span class="p">[</span><span class="n">Int</span><span class="p">]</span>
|
||
<span class="mf">3.</span> <span class="n">Appeal</span> <span class="n">to</span> <span class="n">his</span> <span class="n">vanity</span> <span class="p">[</span><span class="n">Cha</span><span class="p">]</span>
|
||
<span class="mf">4.</span> <span class="n">Try</span> <span class="n">to</span> <span class="n">knock</span> <span class="n">him</span> <span class="n">out</span> <span class="p">[</span><span class="n">Luck</span> <span class="o">+</span> <span class="n">Dex</span><span class="p">]</span>
|
||
<span class="mf">5.</span> <span class="n">Try</span> <span class="n">to</span> <span class="n">run</span> <span class="n">away</span> <span class="p">[</span><span class="n">Dex</span><span class="p">]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This is an example of a menu <em>node</em>. Think of a node as a point where the menu stops printing text
|
||
and waits for user to give some input. By jumping to different nodes depending on the input, a menu
|
||
is constructed.</p>
|
||
<p>To create the menu, EvMenu uses normal Python functions, one per node. It will load all those
|
||
functions/nodes either from a module or by being passed a dictionary mapping the node’s names to
|
||
said functions, like <code class="docutils literal notranslate"><span class="pre">{"nodename":</span> <span class="pre"><function>,</span> <span class="pre">...}</span></code></p>
|
||
</div>
|
||
<div class="section" id="launching-the-menu">
|
||
<h2>Launching the menu<a class="headerlink" href="#launching-the-menu" title="Permalink to this headline">¶</a></h2>
|
||
<p>Initializing the menu is done using a call to the <code class="docutils literal notranslate"><span class="pre">evennia.utils.evmenu.EvMenu</span></code> class. This is the
|
||
most common way to do so - from inside a <a class="reference internal" href="Commands.html"><span class="doc">Command</span></a>:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in, for example gamedir/commands/command.py</span>
|
||
|
||
<span class="kn">from</span> <span class="nn">evennia.utils.evmenu</span> <span class="kn">import</span> <span class="n">EvMenu</span>
|
||
|
||
<span class="k">class</span> <span class="nc">CmdTestMenu</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
||
|
||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"testcommand"</span>
|
||
|
||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</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="s2">"world.mymenu"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>When running this command, the menu will start using the menu nodes loaded from
|
||
<code class="docutils literal notranslate"><span class="pre">mygame/world/mymenu.py</span></code>. See next section on how to define menu nodes.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> has the following optional callsign:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">EvMenu</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">menu_data</span><span class="p">,</span>
|
||
<span class="n">startnode</span><span class="o">=</span><span class="s2">"start"</span><span class="p">,</span>
|
||
<span class="n">cmdset_mergetype</span><span class="o">=</span><span class="s2">"Replace"</span><span class="p">,</span> <span class="n">cmdset_priority</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span>
|
||
<span class="n">auto_quit</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">auto_look</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">auto_help</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
|
||
<span class="n">cmd_on_exit</span><span class="o">=</span><span class="s2">"look"</span><span class="p">,</span>
|
||
<span class="n">persistent</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span>
|
||
<span class="n">startnode_input</span><span class="o">=</span><span class="s2">""</span><span class="p">,</span>
|
||
<span class="n">session</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span>
|
||
<span class="n">debug</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span>
|
||
<span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">caller</span></code> (Object or Account): is a reference to the object using the menu. This object will get a
|
||
new <a class="reference internal" href="Command-Sets.html"><span class="doc">CmdSet</span></a> assigned to it, for handling the menu.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">menu_data</span></code> (str, module or dict): is a module or python path to a module where the global-level
|
||
functions will each be considered to be a menu node. Their names in the module will be the names
|
||
by which they are referred to in the module. Importantly, function names starting with an
|
||
underscore
|
||
<code class="docutils literal notranslate"><span class="pre">_</span></code> will be ignored by the loader. Alternatively, this can be a direct mapping
|
||
<code class="docutils literal notranslate"><span class="pre">{"nodename":function,</span> <span class="pre">...}</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">startnode</span></code> (str): is the name of the menu-node to start the menu at. Changing this means that
|
||
you can jump into a menu tree at different positions depending on circumstance and thus possibly
|
||
re-use menu entries.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">cmdset_mergetype</span></code> (str): This is usually one of “Replace” or “Union” (see [CmdSets](Command-
|
||
Sets).
|
||
The first means that the menu is exclusive - the user has no access to any other commands while
|
||
in the menu. The Union mergetype means the menu co-exists with previous commands (and may
|
||
overload
|
||
them, so be careful as to what to name your menu entries in this case).</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">cmdset_priority</span></code> (int): The priority with which to merge in the menu cmdset. This allows for
|
||
advanced usage.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">auto_quit</span></code>, <code class="docutils literal notranslate"><span class="pre">auto_look</span></code>, <code class="docutils literal notranslate"><span class="pre">auto_help</span></code> (bool): If either of these are <code class="docutils literal notranslate"><span class="pre">True</span></code>, the menu
|
||
automatically makes a <code class="docutils literal notranslate"><span class="pre">quit</span></code>, <code class="docutils literal notranslate"><span class="pre">look</span></code> or <code class="docutils literal notranslate"><span class="pre">help</span></code> command available to the user. The main reason why
|
||
you’d want to turn this off is if you want to use the aliases “q”, “l” or “h” for something in
|
||
your
|
||
menu. Nevertheless, at least <code class="docutils literal notranslate"><span class="pre">quit</span></code> is highly recommend - if <code class="docutils literal notranslate"><span class="pre">False</span></code>, the menu <em>must</em> itself
|
||
supply
|
||
an “exit node” (a node without any options), or the user will be stuck in the menu until the
|
||
server
|
||
reloads (or eternally if the menu is <code class="docutils literal notranslate"><span class="pre">persistent</span></code>)!</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">cmd_on_exit</span></code> (str): This command string will be executed right <em>after</em> the menu has closed down.
|
||
From experience, it’s useful to trigger a “look” command to make sure the user is aware of the
|
||
change of state; but any command can be used. If set to <code class="docutils literal notranslate"><span class="pre">None</span></code>, no command will be triggered
|
||
after
|
||
exiting the menu.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">persistent</span></code> (bool) - if <code class="docutils literal notranslate"><span class="pre">True</span></code>, the menu will survive a reload (so the user will not be kicked
|
||
out by the reload - make sure they can exit on their own!)</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">startnode_input</span></code> (str or (str, dict) tuple): Pass an input text or a input text + kwargs to the
|
||
start node as if it was entered on a fictional previous node. This can be very useful in order to
|
||
start a menu differently depending on the Command’s arguments in which it was initialized.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">session</span></code> (Session): Useful when calling the menu from an <a class="reference internal" href="Accounts.html"><span class="doc">Account</span></a> in
|
||
<code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODDE</span></code> higher than 2, to make sure only the right Session sees the menu output.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">debug</span></code> (bool): If set, the <code class="docutils literal notranslate"><span class="pre">menudebug</span></code> command will be made available in the menu. Use it to
|
||
list the current state of the menu and use <code class="docutils literal notranslate"><span class="pre">menudebug</span> <span class="pre"><variable></span></code> to inspect a specific state
|
||
variable from the list.</p></li>
|
||
<li><p>All other keyword arguments will be available as initial data for the nodes. They will be
|
||
available in all nodes as properties on <code class="docutils literal notranslate"><span class="pre">caller.ndb._menutree</span></code> (see below). These will also
|
||
survive a <code class="docutils literal notranslate"><span class="pre">@reload</span></code> if the menu is <code class="docutils literal notranslate"><span class="pre">persistent</span></code>.</p></li>
|
||
</ul>
|
||
<p>You don’t need to store the EvMenu instance anywhere - the very act of initializing it will store it
|
||
as <code class="docutils literal notranslate"><span class="pre">caller.ndb._menutree</span></code> on the <code class="docutils literal notranslate"><span class="pre">caller</span></code>. This object will be deleted automatically when the menu
|
||
is exited and you can also use it to store your own temporary variables for access throughout the
|
||
menu. Temporary variables you store on a persistent <code class="docutils literal notranslate"><span class="pre">_menutree</span></code> as it runs will
|
||
<em>not</em> survive a <code class="docutils literal notranslate"><span class="pre">@reload</span></code>, only those you set as part of the original <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> call.</p>
|
||
</div>
|
||
<div class="section" id="the-menu-nodes">
|
||
<h2>The Menu nodes<a class="headerlink" href="#the-menu-nodes" title="Permalink to this headline">¶</a></h2>
|
||
<p>The EvMenu nodes consist of functions on one of these forms.</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">menunodename1</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||
<span class="c1"># code</span>
|
||
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
|
||
|
||
<span class="k">def</span> <span class="nf">menunodename2</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="c1"># code</span>
|
||
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
|
||
|
||
<span class="k">def</span> <span class="nf">menunodename3</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="c1"># code</span>
|
||
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<blockquote>
|
||
<div><p>While all of the above forms are okay, it’s recommended to stick to the third and last form since
|
||
it
|
||
gives the most flexibility. The previous forms are mainly there for backwards compatibility with
|
||
existing menus from a time when EvMenu was less able.</p>
|
||
</div></blockquote>
|
||
<div class="section" id="input-arguments-to-the-node">
|
||
<h3>Input arguments to the node<a class="headerlink" href="#input-arguments-to-the-node" title="Permalink to this headline">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">caller</span></code> (Object or Account): The object using the menu - usually a Character but could also be a
|
||
Session or Account depending on where the menu is used.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">raw_string</span></code> (str): If this is given, it will be set to the exact text the user entered on the
|
||
<em>previous</em> node (that is, the command entered to get to this node). On the starting-node of the
|
||
menu, this will be an empty string, unless <code class="docutils literal notranslate"><span class="pre">startnode_input</span></code> was set.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">kwargs</span></code> (dict): These extra keyword arguments are extra optional arguments passed to the node
|
||
when the user makes a choice on the <em>previous</em> node. This may include things like status flags
|
||
and details about which exact option was chosen (which can be impossible to determine from
|
||
<code class="docutils literal notranslate"><span class="pre">raw_string</span></code> alone). Just what is passed in <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> is up to you when you create the previous
|
||
node.</p></li>
|
||
</ul>
|
||
</div>
|
||
<div class="section" id="return-values-from-the-node">
|
||
<h3>Return values from the node<a class="headerlink" href="#return-values-from-the-node" title="Permalink to this headline">¶</a></h3>
|
||
<p>Each function must return two variables, <code class="docutils literal notranslate"><span class="pre">text</span></code> and <code class="docutils literal notranslate"><span class="pre">options</span></code>.</p>
|
||
<div class="section" id="text">
|
||
<h4>text<a class="headerlink" href="#text" title="Permalink to this headline">¶</a></h4>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">text</span></code> variable is a string or tuple. This text is what will be displayed when the user reaches
|
||
this node. If this is a tuple, then the first element of the tuple will be considered the displayed
|
||
text and the second the help-text to display when the user enters the <code class="docutils literal notranslate"><span class="pre">help</span></code> command on this node.</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">text</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"This is the text to display"</span><span class="p">,</span> <span class="s2">"This is the help text for this node"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>Returning a <code class="docutils literal notranslate"><span class="pre">None</span></code> text is allowed and simply leads to a node with no text and only options. If the
|
||
help text is not given, the menu will give a generic error message when using <code class="docutils literal notranslate"><span class="pre">help</span></code>.</p>
|
||
</div>
|
||
<div class="section" id="options">
|
||
<h4>options<a class="headerlink" href="#options" title="Permalink to this headline">¶</a></h4>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">options</span></code> list describe all the choices available to the user when viewing this node. If
|
||
<code class="docutils literal notranslate"><span class="pre">options</span></code> is
|
||
returned as <code class="docutils literal notranslate"><span class="pre">None</span></code>, it means that this node is an <em>Exit node</em> - any text is displayed and then the
|
||
menu immediately exits, running the <code class="docutils literal notranslate"><span class="pre">exit_cmd</span></code> if given.</p>
|
||
<p>Otherwise, <code class="docutils literal notranslate"><span class="pre">options</span></code> should be a list (or tuple) of dictionaries, one for each option. If only one
|
||
option is
|
||
available, a single dictionary can also be returned. This is how it could look:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">node_test</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">text</span> <span class="o">=</span> <span class="s2">"A goblin attacks you!"</span>
|
||
|
||
<span class="n">options</span> <span class="o">=</span> <span class="p">(</span>
|
||
<span class="p">{</span><span class="s2">"key"</span><span class="p">:</span> <span class="p">(</span><span class="s2">"Attack"</span><span class="p">,</span> <span class="s2">"a"</span><span class="p">,</span> <span class="s2">"att"</span><span class="p">),</span>
|
||
<span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"Strike the enemy with all your might"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="s2">"node_attack"</span><span class="p">},</span>
|
||
<span class="p">{</span><span class="s2">"key"</span><span class="p">:</span> <span class="p">(</span><span class="s2">"Defend"</span><span class="p">,</span> <span class="s2">"d"</span><span class="p">,</span> <span class="s2">"def"</span><span class="p">),</span>
|
||
<span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"Hold back and defend yourself"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span><span class="n">_defend</span><span class="p">,</span> <span class="p">{</span><span class="s2">"str"</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span> <span class="s2">"enemyname"</span><span class="p">:</span> <span class="s2">"Goblin"</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>
|
||
</td></tr></table></div>
|
||
<p>This will produce a menu node looking like this:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>A goblin attacks you!
|
||
________________________________
|
||
|
||
Attack: Strike the enemy with all your might
|
||
Defend: Hold back and defend yourself
|
||
</pre></div>
|
||
</div>
|
||
<div class="section" id="option-key-key">
|
||
<h5>option-key ‘key’<a class="headerlink" href="#option-key-key" title="Permalink to this headline">¶</a></h5>
|
||
<p>The option’s <code class="docutils literal notranslate"><span class="pre">key</span></code> is what the user should enter in order to choose that option. If given as a
|
||
tuple, the
|
||
first string of that tuple will be what is shown on-screen while the rest are aliases for picking
|
||
that option. In the above example, the user could enter “Attack” (or “attack”, it’s not
|
||
case-sensitive), “a” or “att” in order to attack the goblin. Aliasing is useful for adding custom
|
||
coloring to the choice. The first element of the aliasing tuple should then be the colored version,
|
||
followed by a version without color - since otherwise the user would have to enter the color codes
|
||
to select that choice.</p>
|
||
<p>Note that the <code class="docutils literal notranslate"><span class="pre">key</span></code> is <em>optional</em>. If no key is given, it will instead automatically be replaced
|
||
with a running number starting from <code class="docutils literal notranslate"><span class="pre">1</span></code>. If removing the <code class="docutils literal notranslate"><span class="pre">key</span></code> part of each option, the resulting
|
||
menu node would look like this instead:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>A goblin attacks you!
|
||
________________________________
|
||
|
||
1: Strike the enemy with all your might
|
||
2: Hold back and defend yourself
|
||
</pre></div>
|
||
</div>
|
||
<p>Whether you want to use a key or rely on numbers is mostly
|
||
a matter of style and the type of menu.</p>
|
||
<p>EvMenu accepts one important special <code class="docutils literal notranslate"><span class="pre">key</span></code> given only as <code class="docutils literal notranslate"><span class="pre">"_default"</span></code>. This key is used when a user
|
||
enters something that does not match any other fixed keys. It is particularly useful for getting
|
||
user input:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">node_readuser</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">text</span> <span class="o">=</span> <span class="s2">"Please enter your name"</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="s2">"node_parse_input"</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>
|
||
</td></tr></table></div>
|
||
<p>A <code class="docutils literal notranslate"><span class="pre">"_default"</span></code> option does not show up in the menu, so the above will just be a node saying
|
||
<code class="docutils literal notranslate"><span class="pre">"Please</span> <span class="pre">enter</span> <span class="pre">your</span> <span class="pre">name"</span></code>. The name they entered will appear as <code class="docutils literal notranslate"><span class="pre">raw_string</span></code> in the next node.</p>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="option-key-desc">
|
||
<h4>option-key ‘desc’<a class="headerlink" href="#option-key-desc" title="Permalink to this headline">¶</a></h4>
|
||
<p>This simply contains the description as to what happens when selecting the menu option. For
|
||
<code class="docutils literal notranslate"><span class="pre">"_default"</span></code> options or if the <code class="docutils literal notranslate"><span class="pre">key</span></code> is already long or descriptive, it is not strictly needed. But
|
||
usually it’s better to keep the <code class="docutils literal notranslate"><span class="pre">key</span></code> short and put more detail in <code class="docutils literal notranslate"><span class="pre">desc</span></code>.</p>
|
||
</div>
|
||
<div class="section" id="option-key-goto">
|
||
<h4>option-key ‘goto’<a class="headerlink" href="#option-key-goto" title="Permalink to this headline">¶</a></h4>
|
||
<p>This is the operational part of the option and fires only when the user chooses said option. Here
|
||
are three ways to write it</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22
|
||
23</pre></div></td><td class="code"><div class="highlight"><pre><span></span>
|
||
<span class="k">def</span> <span class="nf">_action_two</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="c1"># do things ...</span>
|
||
<span class="k">return</span> <span class="s2">"calculated_node_to_go_to"</span>
|
||
|
||
<span class="k">def</span> <span class="nf">_action_three</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="c1"># do things ...</span>
|
||
<span class="k">return</span> <span class="s2">"node_four"</span><span class="p">,</span> <span class="p">{</span><span class="s2">"mode"</span><span class="p">:</span> <span class="mi">4</span><span class="p">}</span>
|
||
|
||
<span class="k">def</span> <span class="nf">node_select</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">text</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"select one"</span><span class="p">,</span>
|
||
<span class="s2">"help - they all do different things ..."</span><span class="p">)</span>
|
||
|
||
<span class="n">options</span> <span class="o">=</span> <span class="p">({</span><span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"Option one"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="s2">"node_one"</span><span class="p">},</span>
|
||
<span class="p">{</span><span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"Option two"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="n">_action_two</span><span class="p">},</span>
|
||
<span class="p">{</span><span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"Option three"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span><span class="n">_action_three</span><span class="p">,</span> <span class="p">{</span><span class="s2">"key"</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s2">"key2"</span><span class="p">:</span> <span class="mi">2</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>
|
||
</td></tr></table></div>
|
||
<p>As seen above, <code class="docutils literal notranslate"><span class="pre">goto</span></code> could just be pointing to a single <code class="docutils literal notranslate"><span class="pre">nodename</span></code> string - the name of the node to
|
||
go to. When given like this, EvMenu will look for a node named like this and call its associated
|
||
function as</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">nodename</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>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>Here, <code class="docutils literal notranslate"><span class="pre">raw_string</span></code> is always the input the user entered to make that choice and <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> are the
|
||
same as those <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> that already entered the <em>current</em> node (they are passed on).</p>
|
||
<p>Alternatively the <code class="docutils literal notranslate"><span class="pre">goto</span></code> could point to a “goto-callable”. Such callables are usually defined in the
|
||
same
|
||
module as the menu nodes and given names starting with <code class="docutils literal notranslate"><span class="pre">_</span></code> (to avoid being parsed as nodes
|
||
themselves). These callables will be called the same as a node function - <code class="docutils literal notranslate"><span class="pre">callable(caller,</span> <span class="pre">raw_string,</span> <span class="pre">**kwargs)</span></code>, where <code class="docutils literal notranslate"><span class="pre">raw_string</span></code> is what the user entered on this node and <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> is
|
||
forwarded from the node’s own input.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">goto</span></code> option key could also point to a tuple <code class="docutils literal notranslate"><span class="pre">(callable,</span> <span class="pre">kwargs)</span></code> - this allows for customizing
|
||
the kwargs passed into the goto-callable, for example you could use the same callable but change the
|
||
kwargs passed into it depending on which option was actually chosen.</p>
|
||
<p>The “goto callable” must either return a string <code class="docutils literal notranslate"><span class="pre">"nodename"</span></code> or a tuple <code class="docutils literal notranslate"><span class="pre">("nodename",</span> <span class="pre">mykwargs)</span></code>.
|
||
This will lead to the next node being called as either <code class="docutils literal notranslate"><span class="pre">nodename(caller,</span> <span class="pre">raw_string,</span> <span class="pre">**kwargs)</span></code> or
|
||
<code class="docutils literal notranslate"><span class="pre">nodename(caller,</span> <span class="pre">raw_string,</span> <span class="pre">**mykwargs)</span></code> - so this allows changing (or replacing) the options
|
||
going
|
||
into the next node depending on what option was chosen.</p>
|
||
<p>There is one important case - if the goto-callable returns <code class="docutils literal notranslate"><span class="pre">None</span></code> for a <code class="docutils literal notranslate"><span class="pre">nodename</span></code>, <em>the current
|
||
node will run again</em>, possibly with different kwargs. This makes it very easy to re-use a node over
|
||
and over, for example allowing different options to update some text form being passed and
|
||
manipulated for every iteration.</p>
|
||
<blockquote>
|
||
<div><p>The EvMenu also supports the <code class="docutils literal notranslate"><span class="pre">exec</span></code> option key. This allows for running a callable <em>before</em> the
|
||
goto-callable. This functionality comes from a time before goto could be a callable and is
|
||
<em>deprecated</em> as of Evennia 0.8. Use <code class="docutils literal notranslate"><span class="pre">goto</span></code> for all functionality where you’d before use <code class="docutils literal notranslate"><span class="pre">exec</span></code>.</p>
|
||
</div></blockquote>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="temporary-storage">
|
||
<h2>Temporary storage<a class="headerlink" href="#temporary-storage" title="Permalink to this headline">¶</a></h2>
|
||
<p>When the menu starts, the EvMenu instance is stored on the caller as <code class="docutils literal notranslate"><span class="pre">caller.ndb._menutree</span></code>. Through
|
||
this object you can in principle reach the menu’s internal state if you know what you are doing.
|
||
This is also a good place to store temporary, more global variables that may be cumbersome to keep
|
||
passing from node to node via the <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code>. The <code class="docutils literal notranslate"><span class="pre">_menutree</span></code> will be deleted automatically when the
|
||
menu closes, meaning you don’t need to worry about cleaning anything up.</p>
|
||
<p>If you want <em>permanent</em> state storage, it’s instead better to use an Attribute on <code class="docutils literal notranslate"><span class="pre">caller</span></code>. Remember
|
||
that this will remain after the menu closes though, so you need to handle any needed cleanup
|
||
yourself.</p>
|
||
</div>
|
||
<div class="section" id="customizing-menu-formatting">
|
||
<h2>Customizing Menu formatting<a class="headerlink" href="#customizing-menu-formatting" title="Permalink to this headline">¶</a></h2>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> display of nodes, options etc are controlled by a series of formatting methods on the
|
||
<code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> class. To customize these, simply create a new child class of <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> and override as
|
||
needed. Here is an example:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22
|
||
23
|
||
24
|
||
25
|
||
26
|
||
27
|
||
28
|
||
29
|
||
30
|
||
31
|
||
32
|
||
33
|
||
34
|
||
35
|
||
36
|
||
37
|
||
38
|
||
39
|
||
40
|
||
41
|
||
42
|
||
43
|
||
44
|
||
45
|
||
46
|
||
47
|
||
48
|
||
49
|
||
50
|
||
51
|
||
52
|
||
53
|
||
54
|
||
55</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils.evmenu</span> <span class="kn">import</span> <span class="n">EvMenu</span>
|
||
|
||
<span class="k">class</span> <span class="nc">MyEvMenu</span><span class="p">(</span><span class="n">EvMenu</span><span class="p">):</span>
|
||
|
||
<span class="k">def</span> <span class="nf">nodetext_formatter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodetext</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> Format the node text itself.</span>
|
||
|
||
<span class="sd"> Args:</span>
|
||
<span class="sd"> nodetext (str): The full node text (the text describing the node).</span>
|
||
|
||
<span class="sd"> Returns:</span>
|
||
<span class="sd"> nodetext (str): The formatted node text.</span>
|
||
|
||
<span class="sd"> """</span>
|
||
|
||
<span class="k">def</span> <span class="nf">helptext_formatter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">helptext</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> Format the node's help text</span>
|
||
|
||
<span class="sd"> Args:</span>
|
||
<span class="sd"> helptext (str): The unformatted help text for the node.</span>
|
||
|
||
<span class="sd"> Returns:</span>
|
||
<span class="sd"> helptext (str): The formatted help text.</span>
|
||
|
||
<span class="sd"> """</span>
|
||
|
||
<span class="k">def</span> <span class="nf">options_formatter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">optionlist</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> Formats the option block.</span>
|
||
|
||
<span class="sd"> Args:</span>
|
||
<span class="sd"> optionlist (list): List of (key, description) tuples for every</span>
|
||
<span class="sd"> option related to this node.</span>
|
||
<span class="sd"> caller (Object, Account or None, optional): The caller of the node.</span>
|
||
|
||
<span class="sd"> Returns:</span>
|
||
<span class="sd"> options (str): The formatted option display.</span>
|
||
|
||
<span class="sd"> """</span>
|
||
|
||
<span class="k">def</span> <span class="nf">node_formatter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodetext</span><span class="p">,</span> <span class="n">optionstext</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> Formats the entirety of the node.</span>
|
||
|
||
<span class="sd"> Args:</span>
|
||
<span class="sd"> nodetext (str): The node text as returned by `self.nodetext_formatter`.</span>
|
||
<span class="sd"> optionstext (str): The options display as returned by `self.options_formatter`.</span>
|
||
<span class="sd"> caller (Object, Account or None, optional): The caller of the node.</span>
|
||
|
||
<span class="sd"> Returns:</span>
|
||
<span class="sd"> node (str): The formatted node to display.</span>
|
||
|
||
<span class="sd"> """</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>See <code class="docutils literal notranslate"><span class="pre">evennia/utils/evmenu.py</span></code> for the details of their default implementations.</p>
|
||
</div>
|
||
<div class="section" id="examples">
|
||
<h2>Examples:<a class="headerlink" href="#examples" title="Permalink to this headline">¶</a></h2>
|
||
<ul class="simple">
|
||
<li><p><strong><a class="reference external" href="Components/EvMenu.html#example-simple-branching-menu">Simple branching menu</a></strong> - choose from options</p></li>
|
||
<li><p><strong><a class="reference external" href="Components/EvMenu.html#example-dynamic-goto">Dynamic goto</a></strong> - jumping to different nodes based on response</p></li>
|
||
<li><p><strong><a class="reference external" href="Components/EvMenu.html#example-set-caller-properties">Set caller properties</a></strong> - a menu that changes things</p></li>
|
||
<li><p><strong><a class="reference external" href="Components/EvMenu.html#example-get-arbitrary-input">Getting arbitrary input</a></strong> - entering text</p></li>
|
||
<li><p><strong><a class="reference external" href="Components/EvMenu.html#example-storing-data-between-nodes">Storing data between nodes</a></strong> - keeping states and
|
||
information while in the menu</p></li>
|
||
<li><p><strong><a class="reference external" href="Components/EvMenu.html#example-repeating-the-same-node">Repeating the same node</a></strong> - validating within the node
|
||
before moving to the next</p></li>
|
||
<li><p><strong><a class="reference external" href="Components/EvMenu.html#example-full-menu">Full Menu</a>:</strong> a complete example</p></li>
|
||
<li><p><strong><a class="reference external" href="Components/EvMenu.html#example-yesno-prompt">Yes/No prompt</a></strong> - entering text with limited possible responses
|
||
(this is <em>not</em> using EvMenu but the conceptually similar yet technically unrelated <code class="docutils literal notranslate"><span class="pre">get_input</span></code>
|
||
helper function accessed as <code class="docutils literal notranslate"><span class="pre">evennia.utils.evmenu.get_input</span></code>).</p></li>
|
||
</ul>
|
||
<div class="section" id="example-simple-branching-menu">
|
||
<h3>Example: Simple branching menu<a class="headerlink" href="#example-simple-branching-menu" title="Permalink to this headline">¶</a></h3>
|
||
<p>Below is an example of a simple branching menu node leading to different other nodes depending on
|
||
choice:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/world/mychargen.py</span>
|
||
|
||
<span class="k">def</span> <span class="nf">define_character</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||
<span class="n">text</span> <span class="o">=</span> \
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> What aspect of your character do you want</span>
|
||
<span class="sd"> to change next?</span>
|
||
<span class="sd"> """</span>
|
||
<span class="n">options</span> <span class="o">=</span> <span class="p">({</span><span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"Change the name"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="s2">"set_name"</span><span class="p">},</span>
|
||
<span class="p">{</span><span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"Change the description"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="s2">"set_description"</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="n">EvMenu</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">"world.mychargen"</span><span class="p">,</span> <span class="n">startnode</span><span class="o">=</span><span class="s2">"define_character"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>This will result in the following node display:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>What aspect of your character do you want
|
||
to change next?
|
||
_________________________
|
||
1: Change the name
|
||
2: Change the description
|
||
</pre></div>
|
||
</div>
|
||
<p>Note that since we didn’t specify the “name” key, EvMenu will let the user enter numbers instead. In
|
||
the following examples we will not include the <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> call but just show nodes running inside the
|
||
menu. Also, since <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> also takes a dictionary to describe the menu, we could have called it
|
||
like this instead in the example:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">EvMenu</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="p">{</span><span class="s2">"define_character"</span><span class="p">:</span> <span class="n">define_character</span><span class="p">},</span> <span class="n">startnode</span><span class="o">=</span><span class="s2">"define_character"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
</div>
|
||
<div class="section" id="example-dynamic-goto">
|
||
<h3>Example: Dynamic goto<a class="headerlink" href="#example-dynamic-goto" title="Permalink to this headline">¶</a></h3>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14</pre></div></td><td class="code"><div class="highlight"><pre><span></span>
|
||
<span class="k">def</span> <span class="nf">_is_in_mage_guild</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="k">if</span> <span class="n">caller</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'mage'</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">"guild_member"</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="s2">"mage_guild_welcome"</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="s2">"mage_guild_blocked"</span>
|
||
|
||
<span class="k">def</span> <span class="nf">enter_guild</span><span class="p">:</span>
|
||
<span class="n">text</span> <span class="o">=</span> <span class="s1">'You say to the mage guard:'</span>
|
||
<span class="n">options</span> <span class="p">({</span><span class="s1">'desc'</span><span class="p">:</span> <span class="s1">'I need to get in there.'</span><span class="p">,</span>
|
||
<span class="s1">'goto'</span><span class="p">:</span> <span class="n">_is_in_mage_guild</span><span class="p">},</span>
|
||
<span class="p">{</span><span class="s1">'desc'</span><span class="p">:</span> <span class="s1">'Never mind'</span><span class="p">,</span>
|
||
<span class="s1">'goto'</span><span class="p">:</span> <span class="s1">'end_conversation'</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>
|
||
</td></tr></table></div>
|
||
<p>This simple callable goto will analyse what happens depending on who the <code class="docutils literal notranslate"><span class="pre">caller</span></code> is. The
|
||
<code class="docutils literal notranslate"><span class="pre">enter_guild</span></code> node will give you a choice of what to say to the guard. If you try to enter, you will
|
||
end up in different nodes depending on (in this example) if you have the right <a class="reference internal" href="Tags.html"><span class="doc">Tag</span></a> set on
|
||
yourself or not. Note that since we don’t include any ‘key’s in the option dictionary, you will just
|
||
get to pick between numbers.</p>
|
||
</div>
|
||
<div class="section" id="example-set-caller-properties">
|
||
<h3>Example: Set caller properties<a class="headerlink" href="#example-set-caller-properties" title="Permalink to this headline">¶</a></h3>
|
||
<p>Here is an example of passing arguments into the <code class="docutils literal notranslate"><span class="pre">goto</span></code> callable and use that to influence
|
||
which node it should go to next:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22
|
||
23
|
||
24
|
||
25
|
||
26
|
||
27
|
||
28</pre></div></td><td class="code"><div class="highlight"><pre><span></span>
|
||
<span class="k">def</span> <span class="nf">_set_attribute</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="s2">"Get which attribute to modify and set it"</span>
|
||
|
||
<span class="n">attrname</span><span class="p">,</span> <span class="n">value</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"attr"</span><span class="p">,</span> <span class="p">(</span><span class="bp">None</span><span class="p">,</span> <span class="bp">None</span><span class="p">))</span>
|
||
<span class="n">next_node</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"next_node"</span><span class="p">)</span>
|
||
|
||
<span class="n">caller</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">attrname</span><span class="p">,</span> <span class="n">attrvalue</span><span class="p">)</span>
|
||
|
||
<span class="k">return</span> <span class="n">next_node</span>
|
||
|
||
|
||
<span class="k">def</span> <span class="nf">node_background</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||
<span class="n">text</span> <span class="o">=</span> \
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> {} experienced a traumatic event</span>
|
||
<span class="sd"> in their childhood. What was it?</span>
|
||
<span class="sd"> """</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">caller</span><span class="o">.</span><span class="n">key</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">"death"</span><span class="p">,</span>
|
||
<span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"A violent death in the family"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span><span class="n">_set_attribute</span><span class="p">,</span> <span class="p">{</span><span class="s2">"attr"</span><span class="p">:</span> <span class="p">(</span><span class="s2">"experienced_violence"</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span>
|
||
<span class="s2">"next_node"</span><span class="p">:</span> <span class="s2">"node_violent_background"</span><span class="p">})},</span>
|
||
<span class="p">{</span><span class="s2">"key"</span><span class="p">:</span> <span class="s2">"betrayal"</span><span class="p">,</span>
|
||
<span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"The betrayal of a trusted grown-up"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span><span class="n">_set_attribute</span><span class="p">,</span> <span class="p">{</span><span class="s2">"attr"</span><span class="p">:</span> <span class="p">(</span><span class="s2">"experienced_betrayal"</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span>
|
||
<span class="s2">"next_node"</span><span class="p">:</span> <span class="s2">"node_betrayal_background"</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>
|
||
</td></tr></table></div>
|
||
<p>This will give the following output:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>Kovash the magnificent experienced a traumatic event
|
||
in their childhood. What was it?
|
||
____________________________________________________
|
||
death: A violent death in the family
|
||
betrayal: The betrayal of a trusted grown-up
|
||
</pre></div>
|
||
</div>
|
||
<p>Note above how we use the <code class="docutils literal notranslate"><span class="pre">_set_attribute</span></code> helper function to set the attribute depending on the
|
||
User’s choice. In thie case the helper function doesn’t know anything about what node called it - we
|
||
even tell it which nodename it should return, so the choices leads to different paths in the menu.
|
||
We could also imagine the helper function analyzing what other choices</p>
|
||
</div>
|
||
<div class="section" id="example-get-arbitrary-input">
|
||
<h3>Example: Get arbitrary input<a class="headerlink" href="#example-get-arbitrary-input" title="Permalink to this headline">¶</a></h3>
|
||
<p>An example of the menu asking the user for input - any input.</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22
|
||
23
|
||
24
|
||
25
|
||
26
|
||
27
|
||
28
|
||
29
|
||
30
|
||
31
|
||
32
|
||
33
|
||
34
|
||
35</pre></div></td><td class="code"><div class="highlight"><pre><span></span>
|
||
<span class="k">def</span> <span class="nf">_set_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="n">inp</span> <span class="o">=</span> <span class="n">raw_string</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
|
||
|
||
<span class="n">prev_entry</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"prev_entry"</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">inp</span><span class="p">:</span>
|
||
<span class="c1"># a blank input either means OK or Abort</span>
|
||
<span class="k">if</span> <span class="n">prev_entry</span><span class="p">:</span>
|
||
<span class="n">caller</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">prev_entry</span>
|
||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Set name to {}."</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">prev_entry</span><span class="p">))</span>
|
||
<span class="k">return</span> <span class="s2">"node_background"</span>
|
||
<span class="k">else</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">"Aborted."</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="s2">"node_exit"</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="c1"># re-run old node, but pass in the name given</span>
|
||
<span class="k">return</span> <span class="bp">None</span><span class="p">,</span> <span class="p">{</span><span class="s2">"prev_entry"</span><span class="p">:</span> <span class="n">inp</span><span class="p">}</span>
|
||
|
||
|
||
<span class="k">def</span> <span class="nf">enter_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="c1"># check if we already entered a name before</span>
|
||
<span class="n">prev_entry</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"prev_entry"</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="n">prev_entry</span><span class="p">:</span>
|
||
<span class="n">text</span> <span class="o">=</span> <span class="s2">"Current name: {}.</span><span class="se">\n</span><span class="s2">Enter another name or <return> to accept."</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">text</span> <span class="o">=</span> <span class="s2">"Enter your character's name or <return> to abort."</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">_set_name</span><span class="p">,</span> <span class="p">{</span><span class="s2">"prev_entry"</span><span class="p">:</span> <span class="n">prev_entry</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>
|
||
</td></tr></table></div>
|
||
<p>This will display as</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Enter</span> <span class="n">your</span> <span class="n">character</span><span class="s1">'s name or <return> to abort.</span>
|
||
|
||
<span class="o">></span> <span class="n">Gandalf</span>
|
||
|
||
<span class="n">Current</span> <span class="n">name</span><span class="p">:</span> <span class="n">Gandalf</span>
|
||
<span class="n">Enter</span> <span class="n">another</span> <span class="n">name</span> <span class="ow">or</span> <span class="o"><</span><span class="k">return</span><span class="o">></span> <span class="n">to</span> <span class="n">accept</span><span class="o">.</span>
|
||
|
||
<span class="o">></span>
|
||
|
||
<span class="n">Set</span> <span class="n">name</span> <span class="n">to</span> <span class="n">Gandalf</span><span class="o">.</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Here we re-use the same node twice for reading the input data from the user. Whatever we enter will
|
||
be caught by the <code class="docutils literal notranslate"><span class="pre">_default</span></code> option and passed into the helper function. We also pass along whatever
|
||
name we have entered before. This allows us to react correctly on an “empty” input - continue to the
|
||
node named <code class="docutils literal notranslate"><span class="pre">"node_background"</span></code> if we accept the input or go to an exit node if we presses Return
|
||
without entering anything. By returning <code class="docutils literal notranslate"><span class="pre">None</span></code> from the helper function we automatically re-run the
|
||
previous node, but updating its ingoing kwargs to tell it to display a different text.</p>
|
||
</div>
|
||
<div class="section" id="example-storing-data-between-nodes">
|
||
<h3>Example: Storing data between nodes<a class="headerlink" href="#example-storing-data-between-nodes" title="Permalink to this headline">¶</a></h3>
|
||
<p>A convenient way to store data is to store it on the <code class="docutils literal notranslate"><span class="pre">caller.ndb._menutree</span></code> which you can reach from
|
||
every node. The advantage of doing this is that the <code class="docutils literal notranslate"><span class="pre">_menutree</span></code> NAttribute will be deleted
|
||
automatically when you exit the menu.</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22
|
||
23
|
||
24
|
||
25
|
||
26
|
||
27</pre></div></td><td class="code"><div class="highlight"><pre><span></span>
|
||
<span class="k">def</span> <span class="nf">_set_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="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_menutree</span><span class="o">.</span><span class="n">charactersheet</span> <span class="o">=</span> <span class="p">{}</span>
|
||
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_menutree</span><span class="o">.</span><span class="n">charactersheet</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]</span> <span class="o">=</span> <span class="n">raw_string</span>
|
||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"You set your name to {}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">raw_string</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="s2">"background"</span>
|
||
|
||
<span class="k">def</span> <span class="nf">node_set_name</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||
<span class="n">text</span> <span class="o">=</span> <span class="s1">'Enter your name:'</span>
|
||
<span class="n">options</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'key'</span><span class="p">:</span> <span class="s1">'_default'</span><span class="p">,</span>
|
||
<span class="s1">'goto'</span><span class="p">:</span> <span class="n">_set_name</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="o">...</span>
|
||
|
||
|
||
<span class="k">def</span> <span class="nf">node_view_sheet</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||
<span class="n">text</span> <span class="o">=</span> <span class="s2">"Character sheet:</span><span class="se">\n</span><span class="s2"> {}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_menutree</span><span class="o">.</span><span class="n">charactersheet</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">"Accept"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="s2">"finish_chargen"</span><span class="p">},</span>
|
||
<span class="p">{</span><span class="s2">"key"</span><span class="p">:</span> <span class="s2">"Decline"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="s2">"start_over"</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>
|
||
</td></tr></table></div>
|
||
<p>Instead of passing the character sheet along from node to node through the <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> we instead
|
||
set it up temporarily on <code class="docutils literal notranslate"><span class="pre">caller.ndb._menutree.charactersheet</span></code>. This makes it easy to reach from
|
||
all nodes. At the end we look at it and, if we accept the character the menu will likely save the
|
||
result to permanent storage and exit.</p>
|
||
<blockquote>
|
||
<div><p>One point to remember though is that storage on <code class="docutils literal notranslate"><span class="pre">caller.ndb._menutree</span></code> is not persistent across
|
||
<code class="docutils literal notranslate"><span class="pre">@reloads</span></code>. If you are using a persistent menu (using <code class="docutils literal notranslate"><span class="pre">EvMenu(...,</span> <span class="pre">persistent=True)</span></code> you should
|
||
use
|
||
<code class="docutils literal notranslate"><span class="pre">caller.db</span></code> to store in-menu data like this as well. You must then yourself make sure to clean it
|
||
when the user exits the menu.</p>
|
||
</div></blockquote>
|
||
</div>
|
||
<div class="section" id="example-repeating-the-same-node">
|
||
<h3>Example: Repeating the same node<a class="headerlink" href="#example-repeating-the-same-node" title="Permalink to this headline">¶</a></h3>
|
||
<p>Sometimes you want to make a chain of menu nodes one after another, but you don’t want the user to
|
||
be able to continue to the next node until you have verified that what they input in the previous
|
||
node is ok. A common example is a login menu:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22
|
||
23
|
||
24
|
||
25
|
||
26
|
||
27
|
||
28
|
||
29
|
||
30
|
||
31
|
||
32
|
||
33
|
||
34
|
||
35
|
||
36
|
||
37</pre></div></td><td class="code"><div class="highlight"><pre><span></span>
|
||
<span class="k">def</span> <span class="nf">_check_username</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="c1"># we assume lookup_username() exists</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">lookup_username</span><span class="p">(</span><span class="n">raw_string</span><span class="p">):</span>
|
||
<span class="c1"># re-run current node by returning `None`</span>
|
||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"|rUsername not found. Try again."</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="bp">None</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="c1"># username ok - continue to next node</span>
|
||
<span class="k">return</span> <span class="s2">"node_password"</span>
|
||
|
||
|
||
<span class="k">def</span> <span class="nf">node_username</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||
<span class="n">text</span> <span class="o">=</span> <span class="s2">"Please enter your user name."</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="n">_check_username</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="k">def</span> <span class="nf">_check_password</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">nattempts</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"nattempts"</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="n">nattempts</span> <span class="o">></span> <span class="mi">3</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">"Too many failed attempts. Logging out"</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="s2">"node_abort"</span>
|
||
<span class="k">elif</span> <span class="ow">not</span> <span class="n">validate_password</span><span class="p">(</span><span class="n">raw_string</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">"Password error. Try again."</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="bp">None</span><span class="p">,</span> <span class="p">{</span><span class="s2">"nattempts"</span><span class="p">,</span> <span class="n">nattempts</span> <span class="o">+</span> <span class="mi">1</span><span class="p">}</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="c1"># password accepted</span>
|
||
<span class="k">return</span> <span class="s2">"node_login"</span>
|
||
|
||
<span class="k">def</span> <span class="nf">node_password</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">text</span> <span class="o">=</span> <span class="s2">"Enter your password."</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="n">_check_password</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>
|
||
</td></tr></table></div>
|
||
<p>This will display something like</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">---------------------------</span>
|
||
<span class="n">Please</span> <span class="n">enter</span> <span class="n">your</span> <span class="n">username</span><span class="o">.</span>
|
||
<span class="o">---------------------------</span>
|
||
|
||
<span class="o">></span> <span class="n">Fo</span>
|
||
|
||
<span class="o">------------------------------</span>
|
||
<span class="n">Username</span> <span class="ow">not</span> <span class="n">found</span><span class="o">.</span> <span class="n">Try</span> <span class="n">again</span><span class="o">.</span>
|
||
<span class="n">______________________________</span>
|
||
<span class="n">abort</span><span class="p">:</span> <span class="p">(</span><span class="n">back</span> <span class="n">to</span> <span class="n">start</span><span class="p">)</span>
|
||
<span class="o">------------------------------</span>
|
||
|
||
<span class="o">></span> <span class="n">Foo</span>
|
||
|
||
<span class="o">---------------------------</span>
|
||
<span class="n">Please</span> <span class="n">enter</span> <span class="n">your</span> <span class="n">password</span><span class="o">.</span>
|
||
<span class="o">---------------------------</span>
|
||
|
||
<span class="o">></span> <span class="n">Bar</span>
|
||
|
||
<span class="o">--------------------------</span>
|
||
<span class="n">Password</span> <span class="n">error</span><span class="o">.</span> <span class="n">Try</span> <span class="n">again</span><span class="o">.</span>
|
||
<span class="o">--------------------------</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>And so on.</p>
|
||
<p>Here the goto-callables will return to the previous node if there is an error. In the case of
|
||
password attempts, this will tick up the <code class="docutils literal notranslate"><span class="pre">nattempts</span></code> argument that will get passed on from iteration
|
||
to iteration until too many attempts have been made.</p>
|
||
</div>
|
||
<div class="section" id="defining-nodes-in-a-dictionary">
|
||
<h3>Defining nodes in a dictionary<a class="headerlink" href="#defining-nodes-in-a-dictionary" title="Permalink to this headline">¶</a></h3>
|
||
<p>You can also define your nodes directly in a dictionary to feed into the <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> creator.</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">mynode</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||
<span class="c1"># a normal menu node function</span>
|
||
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
|
||
|
||
<span class="n">menu_data</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"node1"</span><span class="p">:</span> <span class="n">mynode</span><span class="p">,</span>
|
||
<span class="s2">"node2"</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">caller</span><span class="p">:</span> <span class="p">(</span>
|
||
<span class="s2">"This is the node text"</span><span class="p">,</span>
|
||
<span class="p">({</span><span class="s2">"key"</span><span class="p">:</span> <span class="s2">"lambda node 1"</span><span class="p">,</span>
|
||
<span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"go to node 1 (mynode)"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="s2">"node1"</span><span class="p">},</span>
|
||
<span class="p">{</span><span class="s2">"key"</span><span class="p">:</span> <span class="s2">"lambda node 2"</span><span class="p">,</span>
|
||
<span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"go to thirdnode"</span><span class="p">,</span>
|
||
<span class="s2">"goto"</span><span class="p">:</span> <span class="s2">"node3"</span><span class="p">})),</span>
|
||
<span class="s2">"node3"</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">:</span> <span class="p">(</span>
|
||
<span class="c1"># ... etc ) }</span>
|
||
|
||
<span class="c1"># start menu, assuming 'caller' is available from earlier</span>
|
||
<span class="n">EvMenu</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">menu_data</span><span class="p">,</span> <span class="n">startnode</span><span class="o">=</span><span class="s2">"node1"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>The keys of the dictionary become the node identifiers. You can use any callable on the right form
|
||
to describe each node. If you use Python <code class="docutils literal notranslate"><span class="pre">lambda</span></code> expressions you can make nodes really on the fly.
|
||
If you do, the lambda expression must accept one or two arguments and always return a tuple with two
|
||
elements (the text of the node and its options), same as any menu node function.</p>
|
||
<p>Creating menus like this is one way to present a menu that changes with the circumstances - you
|
||
could for example remove or add nodes before launching the menu depending on some criteria. The
|
||
drawback is that a <code class="docutils literal notranslate"><span class="pre">lambda</span></code> expression <a class="reference external" href="https://docs.python.org/2/tutorial/controlflow.html#lambda-expressions">is much more
|
||
limited</a> than a full
|
||
function - for example you can’t use other Python keywords like <code class="docutils literal notranslate"><span class="pre">if</span></code> inside the body of the
|
||
<code class="docutils literal notranslate"><span class="pre">lambda</span></code>.</p>
|
||
<p>Unless you are dealing with a relatively simple dynamic menu, defining menus with lambda’s is
|
||
probably more work than it’s worth: You can create dynamic menus by instead making each node
|
||
function more clever. See the <a class="reference internal" href="../Howto/NPC-shop-Tutorial.html"><span class="doc">NPC shop tutorial</span></a> for an example of this.</p>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="ask-for-simple-input">
|
||
<h2>Ask for simple input<a class="headerlink" href="#ask-for-simple-input" title="Permalink to this headline">¶</a></h2>
|
||
<p>This describes two ways for asking for simple questions from the user. Using Python’s <code class="docutils literal notranslate"><span class="pre">input</span></code>
|
||
will <em>not</em> work in Evennia. <code class="docutils literal notranslate"><span class="pre">input</span></code> will <em>block</em> the entire server for <em>everyone</em> until that one
|
||
player has entered their text, which is not what you want.</p>
|
||
<div class="section" id="the-yield-way">
|
||
<h3>The <code class="docutils literal notranslate"><span class="pre">yield</span></code> way<a class="headerlink" href="#the-yield-way" title="Permalink to this headline">¶</a></h3>
|
||
<p>In the <code class="docutils literal notranslate"><span class="pre">func</span></code> method of your Commands (only) you can use Python’s built-in <code class="docutils literal notranslate"><span class="pre">yield</span></code> command to
|
||
request input in a similar way to <code class="docutils literal notranslate"><span class="pre">input</span></code>. It looks like this:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">result</span> <span class="o">=</span> <span class="k">yield</span><span class="p">(</span><span class="s2">"Please enter your answer:"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>This will send “Please enter your answer” to the Command’s <code class="docutils literal notranslate"><span class="pre">self.caller</span></code> and then pause at that
|
||
point. All other players at the server will be unaffected. Once caller enteres a reply, the code
|
||
execution will continue and you can do stuff with the <code class="docutils literal notranslate"><span class="pre">result</span></code>. Here is an example:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">Command</span>
|
||
<span class="k">class</span> <span class="nc">CmdTestInput</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"test"</span>
|
||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="n">result</span> <span class="o">=</span> <span class="k">yield</span><span class="p">(</span><span class="s2">"Please enter something:"</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">f</span><span class="s2">"You entered {result}."</span><span class="p">)</span>
|
||
<span class="n">result2</span> <span class="o">=</span> <span class="k">yield</span><span class="p">(</span><span class="s2">"Now enter something else:"</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">f</span><span class="s2">"You now entered {result2}."</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>Using <code class="docutils literal notranslate"><span class="pre">yield</span></code> is simple and intuitive, but it will only access input from <code class="docutils literal notranslate"><span class="pre">self.caller</span></code> and you
|
||
cannot abort or time out the pause until the player has responded. Under the hood, it is actually
|
||
just a wrapper calling <code class="docutils literal notranslate"><span class="pre">get_input</span></code> described in the following section.</p>
|
||
<blockquote>
|
||
<div><p>Important Note: In Python you <em>cannot mix <code class="docutils literal notranslate"><span class="pre">yield</span></code> and <code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre"><value></span></code> in the same method</em>. It has
|
||
to do with <code class="docutils literal notranslate"><span class="pre">yield</span></code> turning the method into a
|
||
<a class="reference external" href="https://www.learnpython.org/en/Generators">generator</a>. A <code class="docutils literal notranslate"><span class="pre">return</span></code> without an argument works, you
|
||
can just not do <code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre"><value></span></code>. This is usually not something you need to do in <code class="docutils literal notranslate"><span class="pre">func()</span></code> anyway,
|
||
but worth keeping in mind.</p>
|
||
</div></blockquote>
|
||
</div>
|
||
<div class="section" id="the-get-input-way">
|
||
<h3>The <code class="docutils literal notranslate"><span class="pre">get_input</span></code> way<a class="headerlink" href="#the-get-input-way" title="Permalink to this headline">¶</a></h3>
|
||
<p>The evmenu module offers a helper function named <code class="docutils literal notranslate"><span class="pre">get_input</span></code>. This is wrapped by the <code class="docutils literal notranslate"><span class="pre">yield</span></code>
|
||
statement which is often easier and more intuitive to use. But <code class="docutils literal notranslate"><span class="pre">get_input</span></code> offers more flexibility
|
||
and power if you need it. While in the same module as <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code>, <code class="docutils literal notranslate"><span class="pre">get_input</span></code> is technically unrelated
|
||
to it. The <code class="docutils literal notranslate"><span class="pre">get_input</span></code> allows you to ask and receive simple one-line input from the user without
|
||
launching the full power of a menu to do so. To use, call <code class="docutils literal notranslate"><span class="pre">get_input</span></code> like this:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">get_input</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">prompt</span><span class="p">,</span> <span class="n">callback</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>Here <code class="docutils literal notranslate"><span class="pre">caller</span></code> is the entity that should receive the prompt for input given as <code class="docutils literal notranslate"><span class="pre">prompt</span></code>. The
|
||
<code class="docutils literal notranslate"><span class="pre">callback</span></code> is a callable <code class="docutils literal notranslate"><span class="pre">function(caller,</span> <span class="pre">prompt,</span> <span class="pre">user_input)</span></code> that you define to handle the answer
|
||
from the user. When run, the caller will see <code class="docutils literal notranslate"><span class="pre">prompt</span></code> appear on their screens and <em>any</em> text they
|
||
enter will be sent into the callback for whatever processing you want.</p>
|
||
<p>Below is a fully explained callback and example call:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">Command</span>
|
||
<span class="kn">from</span> <span class="nn">evennia.utils.evmenu</span> <span class="kn">import</span> <span class="n">get_input</span>
|
||
|
||
<span class="k">def</span> <span class="nf">callback</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">prompt</span><span class="p">,</span> <span class="n">user_input</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> This is a callback you define yourself.</span>
|
||
|
||
<span class="sd"> Args:</span>
|
||
<span class="sd"> caller (Account or Object): The one being asked</span>
|
||
<span class="sd"> for input</span>
|
||
<span class="sd"> prompt (str): A copy of the current prompt</span>
|
||
<span class="sd"> user_input (str): The input from the account.</span>
|
||
|
||
<span class="sd"> Returns:</span>
|
||
<span class="sd"> repeat (bool): If not set or False, exit the</span>
|
||
<span class="sd"> input prompt and clean up. If returning anything</span>
|
||
<span class="sd"> True, stay in the prompt, which means this callback</span>
|
||
<span class="sd"> will be called again with the next user input.</span>
|
||
<span class="sd"> """</span>
|
||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">f</span><span class="s2">"When asked '{prompt}', you answered '{user_input}'."</span><span class="p">)</span>
|
||
|
||
<span class="n">get_input</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">"Write something! "</span><span class="p">,</span> <span class="n">callback</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>This will show as</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>Write something!
|
||
> Hello
|
||
When asked 'Write something!', you answered 'Hello'.
|
||
</pre></div>
|
||
</div>
|
||
<p>Normally, the <code class="docutils literal notranslate"><span class="pre">get_input</span></code> function quits after any input, but as seen in the example docs, you could
|
||
return True from the callback to repeat the prompt until you pass whatever check you want.</p>
|
||
<blockquote>
|
||
<div><p>Note: You <em>cannot</em> link consecutive questions by putting a new <code class="docutils literal notranslate"><span class="pre">get_input</span></code> call inside the
|
||
callback If you want that you should use an EvMenu instead (see the <a class="reference external" href="Components/EvMenu.html#example-repeating-the-same-node">Repeating the same
|
||
node</a> example above). Otherwise you can either peek at the
|
||
implementation of <code class="docutils literal notranslate"><span class="pre">get_input</span></code> and implement your own mechanism (it’s just using cmdset nesting) or
|
||
you can look at <a class="reference external" href="https://groups.google.com/forum/#%21category-topic/evennia/evennia-questions/16pi0SfMO5U">this extension suggested on the mailing
|
||
list</a>.</p>
|
||
</div></blockquote>
|
||
<div class="section" id="example-yes-no-prompt">
|
||
<h4>Example: Yes/No prompt<a class="headerlink" href="#example-yes-no-prompt" title="Permalink to this headline">¶</a></h4>
|
||
<p>Below is an example of a Yes/No prompt using the <code class="docutils literal notranslate"><span class="pre">get_input</span></code> function:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">yesno</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">prompt</span><span class="p">,</span> <span class="n">result</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="n">result</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">"y"</span><span class="p">,</span> <span class="s2">"yes"</span><span class="p">,</span> <span class="s2">"n"</span><span class="p">,</span> <span class="s2">"no"</span><span class="p">):</span>
|
||
<span class="c1"># do stuff to handle the yes/no answer</span>
|
||
<span class="c1"># ...</span>
|
||
<span class="c1"># if we return None/False the prompt state</span>
|
||
<span class="c1"># will quit after this</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="c1"># the answer is not on the right yes/no form</span>
|
||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Please answer Yes or No. </span><span class="se">\n</span><span class="s2">{prompt}"</span><span class="p">)</span>
|
||
<span class="err">@</span> <span class="c1"># returning True will make sure the prompt state is not exited</span>
|
||
<span class="k">return</span> <span class="bp">True</span>
|
||
|
||
<span class="c1"># ask the question</span>
|
||
<span class="n">get_input</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">"Is Evennia great (Yes/No)?"</span><span class="p">,</span> <span class="n">yesno</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="the-list-node-decorator">
|
||
<h2>The <code class="docutils literal notranslate"><span class="pre">@list_node</span></code> decorator<a class="headerlink" href="#the-list-node-decorator" title="Permalink to this headline">¶</a></h2>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">evennia.utils.evmenu.list_node</span></code> is an advanced decorator for use with <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> node functions.
|
||
It is used to quickly create menus for manipulating large numbers of items.</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">text</span> <span class="n">here</span>
|
||
<span class="n">______________________________________________</span>
|
||
|
||
<span class="mf">1.</span> <span class="n">option1</span> <span class="mf">7.</span> <span class="n">option7</span> <span class="mf">13.</span> <span class="n">option13</span>
|
||
<span class="mf">2.</span> <span class="n">option2</span> <span class="mf">8.</span> <span class="n">option8</span> <span class="mf">14.</span> <span class="n">option14</span>
|
||
<span class="mf">3.</span> <span class="n">option3</span> <span class="mf">9.</span> <span class="n">option9</span> <span class="p">[</span><span class="n">p</span><span class="p">]</span><span class="n">revius</span> <span class="n">page</span>
|
||
<span class="mf">4.</span> <span class="n">option4</span> <span class="mf">10.</span> <span class="n">option10</span> <span class="n">page</span> <span class="mi">2</span>
|
||
<span class="mf">5.</span> <span class="n">option5</span> <span class="mf">11.</span> <span class="n">option11</span> <span class="p">[</span><span class="n">n</span><span class="p">]</span><span class="n">ext</span> <span class="n">page</span>
|
||
<span class="mf">6.</span> <span class="n">option6</span> <span class="mf">12.</span> <span class="n">option12</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The menu will automatically create an multi-page option listing that one can flip through. One can
|
||
inpect each entry and then select them with prev/next. This is how it is used:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils.evmenu</span> <span class="kn">import</span> <span class="n">list_node</span>
|
||
|
||
|
||
<span class="o">...</span>
|
||
|
||
<span class="n">_options</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="p">[</span><span class="s1">'option1'</span><span class="p">,</span> <span class="s1">'option2'</span><span class="p">,</span> <span class="o">...</span> <span class="s1">'option100'</span><span class="p">]</span>
|
||
|
||
<span class="n">_select</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">menuchoice</span><span class="p">,</span> <span class="n">available_choices</span><span class="p">):</span>
|
||
<span class="c1"># analyze choice</span>
|
||
<span class="k">return</span> <span class="s2">"next_node"</span>
|
||
|
||
<span class="nd">@list_node</span><span class="p">(</span><span class="n">options</span><span class="p">,</span> <span class="n">select</span><span class="o">=</span><span class="n">_select</span><span class="p">,</span> <span class="n">pagesize</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
|
||
<span class="k">def</span> <span class="nf">node_mylist</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="o">...</span>
|
||
|
||
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">options</span></code> argument to <code class="docutils literal notranslate"><span class="pre">list_node</span></code> is either a list, a generator or a callable returning a list
|
||
of strings for each option that should be displayed in the node.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">select</span></code> is a callable in the example above but could also be the name of a menu node. If a
|
||
callable, the <code class="docutils literal notranslate"><span class="pre">menuchoice</span></code> argument holds the selection done and <code class="docutils literal notranslate"><span class="pre">available_choices</span></code> holds all the
|
||
options available. The callable should return the menu to go to depending on the selection (or
|
||
<code class="docutils literal notranslate"><span class="pre">None</span></code> to rerun the same node). If the name of a menu node, the selection will be passed as
|
||
<code class="docutils literal notranslate"><span class="pre">selection</span></code> kwarg to that node.</p>
|
||
<p>The decorated node itself should return <code class="docutils literal notranslate"><span class="pre">text</span></code> to display in the node. It must return at least an
|
||
empty dictionary for its options. It returning options, those will supplement the options
|
||
auto-created by the <code class="docutils literal notranslate"><span class="pre">list_node</span></code> decorator.</p>
|
||
</div>
|
||
<div class="section" id="assorted-notes">
|
||
<h2>Assorted notes<a class="headerlink" href="#assorted-notes" title="Permalink to this headline">¶</a></h2>
|
||
<p>The EvMenu is implemented using <a class="reference internal" href="Commands.html"><span class="doc">Commands</span></a>. When you start a new EvMenu, the user of the
|
||
menu will be assigned a <a class="reference internal" href="Command-Sets.html"><span class="doc">CmdSet</span></a> with the commands they need to navigate the menu.
|
||
This means that if you were to, from inside the menu, assign a new command set to the caller, <em>you
|
||
may override the Menu Cmdset and kill the menu</em>. If you want to assign cmdsets to the caller as part
|
||
of the menu, you should store the cmdset on <code class="docutils literal notranslate"><span class="pre">caller.ndb._menutree</span></code> and wait to actually assign it
|
||
until the exit node.</p>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<div class="clearer"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||
<div class="sphinxsidebarwrapper">
|
||
<p class="logo"><a href="../index.html">
|
||
<img class="logo" src="../_static/evennia_logo.png" alt="Logo"/>
|
||
</a></p>
|
||
<div id="searchbox" style="display: none" role="search">
|
||
<h3 id="searchlabel">Quick search</h3>
|
||
<div class="searchformwrapper">
|
||
<form class="search" action="../search.html" method="get">
|
||
<input type="text" name="q" aria-labelledby="searchlabel" />
|
||
<input type="submit" value="Go" />
|
||
</form>
|
||
</div>
|
||
</div>
|
||
<script>$('#searchbox').show(0);</script>
|
||
<p><h3><a href="../index.html">Table of Contents</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#">EvMenu</a><ul>
|
||
<li><a class="reference internal" href="#introduction">Introduction</a></li>
|
||
<li><a class="reference internal" href="#launching-the-menu">Launching the menu</a></li>
|
||
<li><a class="reference internal" href="#the-menu-nodes">The Menu nodes</a><ul>
|
||
<li><a class="reference internal" href="#input-arguments-to-the-node">Input arguments to the node</a></li>
|
||
<li><a class="reference internal" href="#return-values-from-the-node">Return values from the node</a><ul>
|
||
<li><a class="reference internal" href="#text">text</a></li>
|
||
<li><a class="reference internal" href="#options">options</a><ul>
|
||
<li><a class="reference internal" href="#option-key-key">option-key ‘key’</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#option-key-desc">option-key ‘desc’</a></li>
|
||
<li><a class="reference internal" href="#option-key-goto">option-key ‘goto’</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#temporary-storage">Temporary storage</a></li>
|
||
<li><a class="reference internal" href="#customizing-menu-formatting">Customizing Menu formatting</a></li>
|
||
<li><a class="reference internal" href="#examples">Examples:</a><ul>
|
||
<li><a class="reference internal" href="#example-simple-branching-menu">Example: Simple branching menu</a></li>
|
||
<li><a class="reference internal" href="#example-dynamic-goto">Example: Dynamic goto</a></li>
|
||
<li><a class="reference internal" href="#example-set-caller-properties">Example: Set caller properties</a></li>
|
||
<li><a class="reference internal" href="#example-get-arbitrary-input">Example: Get arbitrary input</a></li>
|
||
<li><a class="reference internal" href="#example-storing-data-between-nodes">Example: Storing data between nodes</a></li>
|
||
<li><a class="reference internal" href="#example-repeating-the-same-node">Example: Repeating the same node</a></li>
|
||
<li><a class="reference internal" href="#defining-nodes-in-a-dictionary">Defining nodes in a dictionary</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#ask-for-simple-input">Ask for simple input</a><ul>
|
||
<li><a class="reference internal" href="#the-yield-way">The <code class="docutils literal notranslate"><span class="pre">yield</span></code> way</a></li>
|
||
<li><a class="reference internal" href="#the-get-input-way">The <code class="docutils literal notranslate"><span class="pre">get_input</span></code> way</a><ul>
|
||
<li><a class="reference internal" href="#example-yes-no-prompt">Example: Yes/No prompt</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#the-list-node-decorator">The <code class="docutils literal notranslate"><span class="pre">@list_node</span></code> decorator</a></li>
|
||
<li><a class="reference internal" href="#assorted-notes">Assorted notes</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<div role="note" aria-label="source link">
|
||
<!--h3>This Page</h3-->
|
||
<ul class="this-page-menu">
|
||
<li><a href="../_sources/Components/EvMenu.md.txt"
|
||
rel="nofollow">Show Page Source</a></li>
|
||
</ul>
|
||
</div>
|
||
<h3>Versions</h3>
|
||
<ul>
|
||
<li><a href="EvMenu.html">1.0-dev (develop branch)</a></li>
|
||
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
|
||
</ul>
|
||
|
||
</div>
|
||
</div>
|
||
<div class="clearer"></div>
|
||
</div>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>Navigation</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="General Index"
|
||
>index</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python Module Index"
|
||
>modules</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">EvMenu</a></li>
|
||
</ul>
|
||
<div class="develop">develop branch</div>
|
||
</div>
|
||
<div class="footer" role="contentinfo">
|
||
© Copyright 2020, The Evennia developer community.
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
||
</div>
|
||
</body>
|
||
</html> |