mirror of
https://github.com/evennia/evennia.git
synced 2026-03-30 04:27:16 +02:00
Updated HTML docs.
This commit is contained in:
parent
370a11cf2f
commit
88477386fe
64 changed files with 2209 additions and 2458 deletions
|
|
@ -1,4 +1,4 @@
|
|||
# Sphinx build info version 1
|
||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||
config: 1bec5873027ef524caa791e179769b21
|
||||
config: d9a7ba5d71a8c97b082c6fe60a8738b0
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||
|
|
|
|||
|
|
@ -1174,7 +1174,7 @@ function - for example you can’t use other Python keywords like <code class="d
|
|||
<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="../Howtos/NPC-shop-Tutorial.html"><span class="doc std std-doc">NPC shop tutorial</span></a> for an example of this.</p>
|
||||
function more clever. See the <a class="reference internal" href="../Howtos/Tutorial-NPC-Merchants.html"><span class="doc std std-doc">NPC shop tutorial</span></a> for an example of this.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="ask-for-simple-input">
|
||||
|
|
|
|||
|
|
@ -117,8 +117,7 @@ asynchronous timer that you can query to see if a certain time has yet passed.</
|
|||
state. They do not fire callbacks, so are not a good fit for use cases
|
||||
where something needs to happen on a specific schedule (use delay or
|
||||
a TickerHandler for that instead).</p>
|
||||
<p>See also the evennia documentation for command cooldowns
|
||||
(<a class="reference external" href="https://github.com/evennia/evennia/wiki/Command-Cooldown">https://github.com/evennia/evennia/wiki/Command-Cooldown</a>) for more information
|
||||
<p>See also the evennia <a class="reference internal" href="../Howtos/Howto-Command-Cooldown.html"><span class="doc std std-doc">howto</span></a> for more information
|
||||
about the concept.</p>
|
||||
<section id="installation">
|
||||
<h2>Installation<a class="headerlink" href="#installation" title="Permalink to this headline">¶</a></h2>
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Tutorial Tweeting Game Stats" href="Tutorial-Tweeting-Game-Stats.html" />
|
||||
<link rel="prev" title="Static In Game Map" href="Static-In-Game-Map.html" />
|
||||
<link rel="next" title="Implementing a game rule system" href="Implementing-a-game-rule-system.html" />
|
||||
<link rel="prev" title="Evennia for MUSH Users" href="Evennia-for-MUSH-Users.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -30,10 +30,10 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-Tweeting-Game-Stats.html" title="Tutorial Tweeting Game Stats"
|
||||
<a href="Implementing-a-game-rule-system.html" title="Implementing a game rule system"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Static-In-Game-Map.html" title="Static In Game Map"
|
||||
<a href="Evennia-for-MUSH-Users.html" title="Evennia for MUSH Users"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howto’s</a> »</li>
|
||||
|
|
@ -78,11 +78,11 @@
|
|||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Static-In-Game-Map.html"
|
||||
title="previous chapter">Static In Game Map</a></p>
|
||||
<p class="topless"><a href="Evennia-for-MUSH-Users.html"
|
||||
title="previous chapter">Evennia for MUSH Users</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Tutorial-Tweeting-Game-Stats.html"
|
||||
title="next chapter">Tutorial Tweeting Game Stats</a></p>
|
||||
<p class="topless"><a href="Implementing-a-game-rule-system.html"
|
||||
title="next chapter">Implementing a game rule system</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -115,33 +115,27 @@
|
|||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="arxcode-installing-help">
|
||||
<h1>Arxcode installing help<a class="headerlink" href="#arxcode-installing-help" title="Permalink to this headline">¶</a></h1>
|
||||
<p><a class="reference external" href="https://play.arxmush.org/">Arx - After the Reckoning</a> is a big and very popular
|
||||
<a class="reference external" href="https://www.evennia.com">Evennia</a>-based game. Arx is heavily roleplaying-centric, relying on game
|
||||
masters to drive the story. Technically it’s maybe best described as “a MUSH, but with more coded
|
||||
systems”. In August of 2018, the game’s developer, Tehom, generously released the <a class="reference external" href="https://github.com/Arx-Game/arxcode">source code of
|
||||
Arx on github</a>. This is a treasure-trove for developers wanting
|
||||
to pick ideas or even get a starting game to build on.</p>
|
||||
<blockquote>
|
||||
<div><p>These instructions are based on the Arx-code released as of <em>Aug 12, 2018</em>. They will probably
|
||||
not work 100% out of the box anymore. Report any differences and changes needed.</p>
|
||||
</div></blockquote>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<p>Arxcode is separately maintained.</p>
|
||||
<p>While Arxcode uses Evennia, it is <em>not</em> part of Evennia itself; we include this documentation only as a service to users. Also, while Arxcode is still actively maintained (2022), these instructions are based on the Arx-code released as of <em>Aug 12, 2018</em>. They will probably not work 100% out of the box anymore.</p>
|
||||
<p>Arxcode bugs should be directed to <a class="reference external" href="https://github.com/Arx-Game/arxcode/issues">the Arxcode github issue tracker</a>.</p>
|
||||
</div>
|
||||
<p><a class="reference external" href="https://play.arxmush.org/">Arx - After the Reckoning</a> is a big and very popular <a class="reference external" href="https://www.evennia.com">Evennia</a>-based game. Arx is heavily roleplaying-centric, relying on game masters to drive the story. Technically it’s maybe best described as “a MUSH, but with more coded systems”. In August of 2018, the game’s developer, Tehom, generously released the <a class="reference external" href="https://github.com/Arx-Game/arxcode">source code of Arx on github</a>. This is a treasure-trove for developers wanting to pick ideas or even get a starting game to build on.</p>
|
||||
<p>It’s not too hard to run Arx from the sources (of course you’ll start with an empty database) but
|
||||
since part of Arx has grown organically, it doesn’t follow standard Evennia paradigms everywhere.
|
||||
This page covers one take on installing and setting things up while making your new Arx-based game
|
||||
better match with the vanilla Evennia install.</p>
|
||||
This page covers one take on installing and setting things up while making your new Arx-based game better match with the vanilla Evennia install.</p>
|
||||
<section id="installing-evennia">
|
||||
<h2>Installing Evennia<a class="headerlink" href="#installing-evennia" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Firstly, set aside a folder/directory on your drive for everything to follow.</p>
|
||||
<p>You need to start by installing <a class="reference external" href="https://www.evennia.com">Evennia</a> by following most of the
|
||||
<a class="reference internal" href="../Setup/Installation-Git.html"><span class="doc std std-doc">Git-installation instructions</span></a> for your OS. The difference is that you
|
||||
need to <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">clone</span> <span class="pre">https://github.com/TehomCD/evennia.git</span></code> instead of Evennia’s repo because Arx
|
||||
uses TehomCD’s older Evennia 0.8 <a class="reference external" href="https://github.com/TehomCD/evennia">fork</a>, notably still using
|
||||
Python2. This detail is important if referring to newer Evennia documentation.</p>
|
||||
<p>If you are new to Evennia it’s <em>highly</em> recommended that you run through the normal install
|
||||
instructions in full - including initializing and starting a new empty game and connecting to it.
|
||||
<p>You need to start by installing <a class="reference external" href="https://www.evennia.com">Evennia</a> by following most of the <a class="reference internal" href="../Setup/Installation-Git.html"><span class="doc std std-doc">Git-installation instructions</span></a> for your OS. The difference is that instead of cloning from upstream Evennia, you should do</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git clone https://github.com/TehomCD/evennia.git
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This is because Arx uses TehomCD’s older Evennia 0.8 <a class="reference external" href="https://github.com/TehomCD/evennia">fork</a>, notably still using Python2. This detail is important if referring to newer Evennia documentation.</p>
|
||||
<p>If you are new to Evennia it’s <em>highly</em> recommended that you run through the normal install instructions in full - including initializing and starting a new empty game and connecting to it.
|
||||
That way you can be sure Evennia works correctly as a baseline.</p>
|
||||
<p>After installing you should have a <code class="docutils literal notranslate"><span class="pre">virtualenv</span></code> running and you should have the following file
|
||||
structure in your set-aside folder:</p>
|
||||
<p>After installing you should have a <code class="docutils literal notranslate"><span class="pre">virtualenv</span></code> running and you should have the following file structure in your set-aside folder:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">muddev</span><span class="o">/</span>
|
||||
<span class="n">vienv</span><span class="o">/</span>
|
||||
<span class="n">evennia</span><span class="o">/</span>
|
||||
|
|
@ -161,8 +155,7 @@ to compare to.</p>
|
|||
</div>
|
||||
<p>A new folder <code class="docutils literal notranslate"><span class="pre">myarx</span></code> should appear next to the ones you already had. You could rename this to
|
||||
something else if you want.</p>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">cd</span></code> into <code class="docutils literal notranslate"><span class="pre">myarx</span></code>. If you wonder about the structure of the game dir, you can
|
||||
<a class="reference internal" href="Beginner-Tutorial/Part1/Beginner-Tutorial-Gamedir-Overview.html"><span class="doc std std-doc">read more about it here</span></a>.</p>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">cd</span></code> into <code class="docutils literal notranslate"><span class="pre">myarx</span></code>. If you wonder about the structure of the game dir, you can <a class="reference internal" href="Beginner-Tutorial/Part1/Beginner-Tutorial-Gamedir-Overview.html"><span class="doc std std-doc">read more about it here</span></a>.</p>
|
||||
<section id="clean-up-settings">
|
||||
<h3>Clean up settings<a class="headerlink" href="#clean-up-settings" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Arx has split evennia’s normal settings into <code class="docutils literal notranslate"><span class="pre">base_settings.py</span></code> and <code class="docutils literal notranslate"><span class="pre">production_settings.py</span></code>. It
|
||||
|
|
@ -184,27 +177,18 @@ way but we’ll remove the secret-handling and replace it with the normal Evenni
|
|||
</pre></div>
|
||||
</div>
|
||||
<blockquote>
|
||||
<div><p>Note: Indents and capitalization matter in Python. Make indents 4 spaces (not tabs) for your own
|
||||
sanity. If you want a starter on Python in Evennia, [you can look here](Python-basic-
|
||||
introduction).</p>
|
||||
<div><p>Note: Indents and capitalization matter in Python. Make indents 4 spaces (not tabs) for your own sanity. If you want a starter on Python in Evennia, [you can look here](Beginner-Tutorial-Python-basic- introduction).</p>
|
||||
</div></blockquote>
|
||||
<p>This will import Arx’ base settings and override them with the Evennia-default telnet port and give
|
||||
the game a name. The slogan changes the sub-text shown under the name of your game in the website
|
||||
header. You can tweak these to your own liking later.</p>
|
||||
<p>This will import Arx’ base settings and override them with the Evennia-default telnet port and give the game a name. The slogan changes the sub-text shown under the name of your game in the website header. You can tweak these to your own liking later.</p>
|
||||
<p>Next, create a new, empty file <code class="docutils literal notranslate"><span class="pre">secret_settings.py</span></code> in the same location as the <code class="docutils literal notranslate"><span class="pre">settings.py</span></code> file.
|
||||
This can just contain the following:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">SECRET_KEY</span> <span class="o">=</span> <span class="s2">"sefsefiwwj3 jnwidufhjw4545_oifej whewiu hwejfpoiwjrpw09&4er43233fwefwfw"</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Replace the long random string with random ASCII characters of your own. The secret key should not
|
||||
be shared.</p>
|
||||
<p>Next, open <code class="docutils literal notranslate"><span class="pre">myarx/server/conf/base_settings.py</span></code> in your text editor. We want to remove/comment out
|
||||
all mentions of the <code class="docutils literal notranslate"><span class="pre">decouple</span></code> package, which Evennia doesn’t use (we use <code class="docutils literal notranslate"><span class="pre">private_settings.py</span></code> to
|
||||
hide away settings that should not be shared).</p>
|
||||
<p>Comment out <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">decouple</span> <span class="pre">import</span> <span class="pre">config</span></code> by adding a <code class="docutils literal notranslate"><span class="pre">#</span></code> to the start of the line: <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">from</span> <span class="pre">decouple</span> <span class="pre">import</span> <span class="pre">config</span></code>. Then search for <code class="docutils literal notranslate"><span class="pre">config(</span></code> in the file and comment out all lines where this is used.
|
||||
Many of these are specific to the server environment where the original Arx runs, so is not that
|
||||
relevant to us.</p>
|
||||
<p>Replace the long random string with random ASCII characters of your own. The secret key should not be shared.</p>
|
||||
<p>Next, open <code class="docutils literal notranslate"><span class="pre">myarx/server/conf/base_settings.py</span></code> in your text editor. We want to remove/comment out all mentions of the <code class="docutils literal notranslate"><span class="pre">decouple</span></code> package, which Evennia doesn’t use (we use <code class="docutils literal notranslate"><span class="pre">private_settings.py</span></code> to hide away settings that should not be shared).</p>
|
||||
<p>Comment out <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">decouple</span> <span class="pre">import</span> <span class="pre">config</span></code> by adding a <code class="docutils literal notranslate"><span class="pre">#</span></code> to the start of the line: <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">from</span> <span class="pre">decouple</span> <span class="pre">import</span> <span class="pre">config</span></code>. Then search for <code class="docutils literal notranslate"><span class="pre">config(</span></code> in the file and comment out all lines where this is used. Many of these are specific to the server environment where the original Arx runs, so is not that relevant to us.</p>
|
||||
</section>
|
||||
<section id="install-arx-dependencies">
|
||||
<h3>Install Arx dependencies<a class="headerlink" href="#install-arx-dependencies" title="Permalink to this headline">¶</a></h3>
|
||||
|
|
@ -241,10 +225,7 @@ mkdir server\logs
|
|||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia start
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If all goes well Evennia will now start up, running Arx! You can connect to it on <code class="docutils literal notranslate"><span class="pre">localhost</span></code> (or
|
||||
<code class="docutils literal notranslate"><span class="pre">127.0.0.1</span></code> if your platform doesn’t alias <code class="docutils literal notranslate"><span class="pre">localhost</span></code>), port <code class="docutils literal notranslate"><span class="pre">4000</span></code> using a Telnet client.
|
||||
Alternatively, you can use your web browser to browse to <code class="docutils literal notranslate"><span class="pre">http://localhost:4001</span></code> to see the game’s
|
||||
website and get to the web client.</p>
|
||||
<p>If all goes well Evennia will now start up, running Arx! You can connect to it on <code class="docutils literal notranslate"><span class="pre">localhost</span></code> (or <code class="docutils literal notranslate"><span class="pre">127.0.0.1</span></code> if your platform doesn’t alias <code class="docutils literal notranslate"><span class="pre">localhost</span></code>), port <code class="docutils literal notranslate"><span class="pre">4000</span></code> using a Telnet client. Alternatively, you can use your web browser to browse to <code class="docutils literal notranslate"><span class="pre">http://localhost:4001</span></code> to see the game’s website and get to the web client.</p>
|
||||
<p>When you log in you’ll get the standard Evennia greeting (since the database is empty), but you can
|
||||
try <code class="docutils literal notranslate"><span class="pre">help</span></code> to see that it’s indeed Arx that is running.</p>
|
||||
</section>
|
||||
|
|
@ -261,86 +242,89 @@ run steps 7-8 and 10 to create and connect to your in-came Character.</p>
|
|||
<li><p>Navigate to the <code class="docutils literal notranslate"><span class="pre">Accounts</span></code> section.</p></li>
|
||||
<li><p>Add a new Account named for the new staffer. Use a place holder password and dummy e-mail
|
||||
address.</p></li>
|
||||
<li><p>Flag account as <code class="docutils literal notranslate"><span class="pre">Staff</span></code> and apply the <code class="docutils literal notranslate"><span class="pre">Admin</span></code> permission group (This assumes you have already set
|
||||
up an Admin Group in Django).</p></li>
|
||||
<li><p>Flag account as <code class="docutils literal notranslate"><span class="pre">Staff</span></code> and apply the <code class="docutils literal notranslate"><span class="pre">Admin</span></code> permission group (This assumes you have already set up an Admin Group in Django).</p></li>
|
||||
<li><p>Add Tags named <code class="docutils literal notranslate"><span class="pre">player</span></code> and <code class="docutils literal notranslate"><span class="pre">developer</span></code>.</p></li>
|
||||
<li><p>Log into the game using the web client (or a third-party telnet client) using your superuser
|
||||
account. Move to where you want the new staffer character to appear.</p></li>
|
||||
<li><p>In the game client, run <code class="docutils literal notranslate"><span class="pre">@create/drop</span> <span class="pre"><staffername>:typeclasses.characters.Character</span></code>, where
|
||||
<code class="docutils literal notranslate"><span class="pre"><staffername></span></code> is usually the same name you used for the Staffer account you created in the
|
||||
Admin earlier (if you are creating a Character for your superuser, use your superuser account
|
||||
name).
|
||||
This creates a new in-game Character and places it in your current location.</p></li>
|
||||
<li><p>Log into the game using the web client (or a third-party telnet client) using your superuser account. Move to where you want the new staffer character to appear.</p></li>
|
||||
<li><p>In the game client, run <code class="docutils literal notranslate"><span class="pre">@create/drop</span> <span class="pre"><staffername>:typeclasses.characters.Character</span></code>, where <code class="docutils literal notranslate"><span class="pre"><staffername></span></code> is usually the same name you used for the Staffer account you created in the Admin earlier (if you are creating a Character for your superuser, use your superuser account name). This creates a new in-game Character and places it in your current location.</p></li>
|
||||
<li><p>Have the new Admin player log into the game.</p></li>
|
||||
<li><p>Have the new Admin puppet the character with <code class="docutils literal notranslate"><span class="pre">@ic</span> <span class="pre">StafferName</span></code>.</p></li>
|
||||
<li><p>Have the new Admin change their password - <code class="docutils literal notranslate"><span class="pre">@password</span> <span class="pre"><old</span> <span class="pre">password></span> <span class="pre">=</span> <span class="pre"><new</span> <span class="pre">password></span></code>.</p></li>
|
||||
</ol>
|
||||
<p>Now that you have a Character and an Account object, there’s a few additional things you may need to
|
||||
do in order for some commands to function properly. You can either execute these as in-game commands
|
||||
while <code class="docutils literal notranslate"><span class="pre">ic</span></code> (controlling your character object).</p>
|
||||
<ol class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">py</span> <span class="pre">from</span> <span class="pre">web.character.models</span> <span class="pre">import</span> <span class="pre">RosterEntry;RosterEntry.objects.create(player=self.player,</span> <span class="pre">character=self)</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">py</span> <span class="pre">from</span> <span class="pre">world.dominion.models</span> <span class="pre">import</span> <span class="pre">PlayerOrNpc,</span> <span class="pre">AssetOwner;dompc</span> <span class="pre">=</span> <span class="pre">PlayerOrNpc.objects.create(player</span> <span class="pre">=</span> <span class="pre">self.player);AssetOwner.objects.create(player=dompc)</span></code></p></li>
|
||||
</ol>
|
||||
<p>Those steps will give you a ‘RosterEntry’, ‘PlayerOrNpc’, and ‘AssetOwner’ objects. RosterEntry
|
||||
<p>Now that you have a Character and an Account object, there’s a few additional things you may need to do in order for some commands to function properly. You can either execute these as in-game commands while <code class="docutils literal notranslate"><span class="pre">ic</span></code> (controlling your character object).</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>py from web.character.models import RosterEntry;RosterEntry.objects.create(player=self.player, character=self)
|
||||
|
||||
py from world.dominion.models import PlayerOrNpc, AssetOwner;dompc = PlayerOrNpc.objects.create(player=self.player);AssetOwner.objects.create(player=dompc)
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Those steps will give you ‘RosterEntry’, ‘PlayerOrNpc’, and ‘AssetOwner’ objects. RosterEntry
|
||||
explicitly connects a character and account object together, even while offline, and contains
|
||||
additional information about a character’s current presence in game (such as which ‘roster’ they’re
|
||||
in, if you choose to use an active roster of characters). PlayerOrNpc are more character extensions,
|
||||
as well as support for npcs with no in-game presence and just represented by a name which can be
|
||||
offscreen members of a character’s family. It also allows for membership in Organizations.
|
||||
AssetOwner holds information about a character or organization’s money and resources.</p>
|
||||
in, if you choose to use an active roster of characters). PlayerOrNpc are more character extensions, as well as support for npcs with no in-game presence and just represented by a name which can be offscreen members of a character’s family. It also allows for membership in Organizations. AssetOwner holds information about a character or organization’s money and resources.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="alternate-windows-install-guide">
|
||||
<h2>Alternate Windows install guide<a class="headerlink" href="#alternate-windows-install-guide" title="Permalink to this headline">¶</a></h2>
|
||||
<p><em>Contributed by Pax</em></p>
|
||||
<p>If for some reason you cannot use the Windows Subsystem for Linux (which would use instructions
|
||||
identical to the ones above), it’s possible to get Evennia/Arx running under Anaconda for Windows. The
|
||||
process is a little bit trickier.</p>
|
||||
<p>If for some reason you cannot use the Windows Subsystem for Linux (which would use instructions identical to the ones above), it’s possible to get Evennia/Arx running under Anaconda for Windows. The process is a little bit trickier.</p>
|
||||
<p>Make sure you have:</p>
|
||||
<ul class="simple">
|
||||
<ul>
|
||||
<li><p>Git for Windows <a class="reference external" href="https://git-scm.com/download/win">https://git-scm.com/download/win</a></p></li>
|
||||
<li><p>Anaconda for Windows <a class="reference external" href="https://www.anaconda.com/distribution/">https://www.anaconda.com/distribution/</a></p></li>
|
||||
<li><p>VC++ Compiler for Python 2.7 <a class="reference external" href="https://aka.ms/vcpython27">https://aka.ms/vcpython27</a></p></li>
|
||||
</ul>
|
||||
<li><p>VC++ Compiler for Python 2.7 <a class="reference external" href="https://aka.ms/vcpython27">https://aka.ms/vcpython27</a></p>
|
||||
<p>conda update conda
|
||||
conda create -n arx python=2.7
|
||||
source activate arx</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Set up a convenient repository place for things.</p>
|
||||
<p>cd ~
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>cd ~
|
||||
mkdir Source
|
||||
cd Source
|
||||
mkdir Arx
|
||||
cd Arx</p>
|
||||
cd Arx
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Replace the SSH git clone links below with your own github forks.
|
||||
If you don’t plan to change Evennia at all, you can use the
|
||||
evennia/evennia.git repo instead of a forked one.</p>
|
||||
<p>git clone <a class="reference external" href="mailto:git%40github.com">git<span>@</span>github<span>.</span>com</a>:<youruser>/evennia.git
|
||||
git clone <a class="reference external" href="mailto:git%40github.com">git<span>@</span>github<span>.</span>com</a>:<youruser>/arxcode.git</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git clone git@github.com:<youruser>/evennia.git
|
||||
git clone git@github.com:<youruser>/arxcode.git
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Evennia is a package itself, so we want to install it and all of its
|
||||
prerequisites, after switching to the appropriately-tagged branch for
|
||||
Arxcode.</p>
|
||||
<p>cd evennia
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>cd evennia
|
||||
git checkout tags/v0.7 -b arx-master
|
||||
pip install -e .</p>
|
||||
pip install -e .
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Arx has some dependencies of its own, so now we’ll go install them
|
||||
As it is not a package, we’ll use the normal requirements file.</p>
|
||||
<p>cd …/arxcode
|
||||
pip install -r requirements.txt</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>cd ../arxcode
|
||||
pip install -r requirements.txt
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The git repo doesn’t include the empty log directory and Evennia is unhappy if you
|
||||
don’t have it, so while still in the arxcode directory…</p>
|
||||
<p>mkdir server/logs</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>mkdir server/logs
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Now hit <a class="reference external" href="https://github.com/evennia/evennia/wiki/Arxcode-installing-help">https://github.com/evennia/evennia/wiki/Arxcode-installing-help</a> and
|
||||
change the setup stuff as in the ‘Clean up settings’ section.</p>
|
||||
<p>Then we will create our default database…</p>
|
||||
<p>…/evennia/bin/windows/evennia.bat migrate</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>../evennia/bin/windows/evennia.bat migrate
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>…and do the first run. You need winpty because Windows does not have a TTY/PTY
|
||||
by default, and so the Python console input commands (used for prompts on first
|
||||
run) will fail and you will end up in an unhappy place. Future runs, you should
|
||||
not need winpty.</p>
|
||||
<p>winpty …/evennia/bin/windows/evennia.bat start</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>winpty ../evennia/bin/windows/evennia.bat start
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Once this is done, you should have your Evennia server running Arxcode up
|
||||
on localhost at port 4000, and the webserver at <a class="reference external" href="http://localhost:4001/">http://localhost:4001/</a></p>
|
||||
on localhost at port 4000, and the webserver at <a class="reference external" href="http://localhost:4001/">http://localhost:4001/</a>.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
|
@ -360,10 +344,10 @@ on localhost at port 4000, and the webserver at <a class="reference external" hr
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-Tweeting-Game-Stats.html" title="Tutorial Tweeting Game Stats"
|
||||
<a href="Implementing-a-game-rule-system.html" title="Implementing a game rule system"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Static-In-Game-Map.html" title="Static In Game Map"
|
||||
<a href="Evennia-for-MUSH-Users.html" title="Evennia for MUSH Users"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../../../genindex.html" />
|
||||
<link rel="search" title="Search" href="../../../search.html" />
|
||||
<link rel="next" title="Command Prompt" href="../../Howto-Command-Prompt.html" />
|
||||
<link rel="next" title="Adding a Command Prompt" href="../../Howto-Command-Prompt.html" />
|
||||
<link rel="prev" title="1. Add a simple new web page" href="Add-a-simple-new-web-page.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
<a href="../../../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="../../Howto-Command-Prompt.html" title="Command Prompt"
|
||||
<a href="../../Howto-Command-Prompt.html" title="Adding a Command Prompt"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Add-a-simple-new-web-page.html" title="1. Add a simple new web page"
|
||||
|
|
@ -78,7 +78,7 @@
|
|||
title="previous chapter"><span class="section-number">1. </span>Add a simple new web page</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="../../Howto-Command-Prompt.html"
|
||||
title="next chapter">Command Prompt</a></p>
|
||||
title="next chapter">Adding a Command Prompt</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -234,7 +234,7 @@ works and what possibilities exist.</p>
|
|||
<a href="../../../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="../../Howto-Command-Prompt.html" title="Command Prompt"
|
||||
<a href="../../Howto-Command-Prompt.html" title="Adding a Command Prompt"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Add-a-simple-new-web-page.html" title="1. Add a simple new web page"
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Tutorial Vehicles" href="Tutorial-Vehicles.html" />
|
||||
<link rel="prev" title="NPC shop Tutorial" href="NPC-shop-Tutorial.html" />
|
||||
<link rel="prev" title="NPC merchants" href="Tutorial-NPC-Merchants.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
<a href="Tutorial-Vehicles.html" title="Tutorial Vehicles"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="NPC-shop-Tutorial.html" title="NPC shop Tutorial"
|
||||
<a href="Tutorial-NPC-Merchants.html" title="NPC merchants"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howto’s</a> »</li>
|
||||
|
|
@ -74,8 +74,8 @@
|
|||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="NPC-shop-Tutorial.html"
|
||||
title="previous chapter">NPC shop Tutorial</a></p>
|
||||
<p class="topless"><a href="Tutorial-NPC-Merchants.html"
|
||||
title="previous chapter">NPC merchants</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Tutorial-Vehicles.html"
|
||||
title="next chapter">Tutorial Vehicles</a></p>
|
||||
|
|
@ -358,7 +358,7 @@ shooting goodness would be made available to you only when you enter it.</p>
|
|||
<a href="Tutorial-Vehicles.html" title="Tutorial Vehicles"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="NPC-shop-Tutorial.html" title="NPC shop Tutorial"
|
||||
<a href="Tutorial-NPC-Merchants.html" title="NPC merchants"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Implementing a game rule system" href="Implementing-a-game-rule-system.html" />
|
||||
<link rel="next" title="Arxcode installing help" href="Arxcode-Installation.html" />
|
||||
<link rel="prev" title="Evennia for Diku Users" href="Evennia-for-Diku-Users.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Implementing-a-game-rule-system.html" title="Implementing a game rule system"
|
||||
<a href="Arxcode-Installation.html" title="Arxcode installing help"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Evennia-for-Diku-Users.html" title="Evennia for Diku Users"
|
||||
|
|
@ -80,8 +80,8 @@
|
|||
<p class="topless"><a href="Evennia-for-Diku-Users.html"
|
||||
title="previous chapter">Evennia for Diku Users</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Implementing-a-game-rule-system.html"
|
||||
title="next chapter">Implementing a game rule system</a></p>
|
||||
<p class="topless"><a href="Arxcode-Installation.html"
|
||||
title="next chapter">Arxcode installing help</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -325,7 +325,7 @@ or post a question in our <a class="reference external" href="https://groups.goo
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Implementing-a-game-rule-system.html" title="Implementing a game rule system"
|
||||
<a href="Arxcode-Installation.html" title="Arxcode installing help"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Evennia-for-Diku-Users.html" title="Evennia for Diku Users"
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Mass and weight for objects" href="Mass-and-weight-for-objects.html" />
|
||||
<link rel="next" title="Weather Tutorial" href="Weather-Tutorial.html" />
|
||||
<link rel="prev" title="Making a Persistent object Handler" href="Tutorial-Persistent-Handler.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Mass-and-weight-for-objects.html" title="Mass and weight for objects"
|
||||
<a href="Weather-Tutorial.html" title="Weather Tutorial"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-Persistent-Handler.html" title="Making a Persistent object Handler"
|
||||
|
|
@ -82,8 +82,8 @@
|
|||
<p class="topless"><a href="Tutorial-Persistent-Handler.html"
|
||||
title="previous chapter">Making a Persistent object Handler</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Mass-and-weight-for-objects.html"
|
||||
title="next chapter">Mass and weight for objects</a></p>
|
||||
<p class="topless"><a href="Weather-Tutorial.html"
|
||||
title="next chapter">Weather Tutorial</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -407,7 +407,7 @@ same way as described for the default one above.</p>
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Mass-and-weight-for-objects.html" title="Mass and weight for objects"
|
||||
<a href="Weather-Tutorial.html" title="Weather Tutorial"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-Persistent-Handler.html" title="Making a Persistent object Handler"
|
||||
|
|
|
|||
255
docs/1.0-dev/Howtos/Howto-Add-Object-Weight.html
Normal file
255
docs/1.0-dev/Howtos/Howto-Add-Object-Weight.html
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Give objects weight — Evennia 1.0-dev documentation</title>
|
||||
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<script src="../_static/language_data.js"></script>
|
||||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="NPCs that listen to what is said" href="Tutorial-NPC-Listening.html" />
|
||||
<link rel="prev" title="Return custom errors on missing Exits" href="Howto-Default-Exit-Errors.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="../genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-NPC-Listening.html" title="NPCs that listen to what is said"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Howto-Default-Exit-Errors.html" title="Return custom errors on missing Exits"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Give objects weight</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
|
||||
<div class="documentwrapper">
|
||||
<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>
|
||||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Give objects weight</a><ul>
|
||||
<li><a class="reference internal" href="#limit-inventory-by-weight-carried">Limit inventory by weight carried</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Howto-Default-Exit-Errors.html"
|
||||
title="previous chapter">Return custom errors on missing Exits</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Tutorial-NPC-Listening.html"
|
||||
title="next chapter">NPCs that listen to what is said</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Howtos/Howto-Add-Object-Weight.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div><h3>Links</h3>
|
||||
<ul>
|
||||
<li><a href="https://www.evennia.com">Home page</a> </li>
|
||||
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
|
||||
<li><a href="http://games.evennia.com">Game Index</a> </li>
|
||||
<li>
|
||||
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
|
||||
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
|
||||
<a href="https://evennia.blogspot.com/">Blog</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Howto-Add-Object-Weight.html">1.0-dev (develop branch)</a></li>
|
||||
<ul>
|
||||
<li><a href="../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="give-objects-weight">
|
||||
<h1>Give objects weight<a class="headerlink" href="#give-objects-weight" title="Permalink to this headline">¶</a></h1>
|
||||
<p>All in-game objets you can touch usually has some weight. What weight does varies from game to game. Commonly it limits how much you can carry. A heavy stone may also hurt you more than a ballon, if it falls on you. If you want to get fancy, a pressure plate may only trigger if the one stepping on it is heavy enough.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
|
||||
<span class="normal"> 2</span>
|
||||
<span class="normal"> 3</span>
|
||||
<span class="normal"> 4</span>
|
||||
<span class="normal"> 5</span>
|
||||
<span class="normal"> 6</span>
|
||||
<span class="normal"> 7</span>
|
||||
<span class="normal"> 8</span>
|
||||
<span class="normal"> 9</span>
|
||||
<span class="normal">10</span>
|
||||
<span class="normal">11</span>
|
||||
<span class="normal">12</span>
|
||||
<span class="normal">13</span>
|
||||
<span class="normal">14</span>
|
||||
<span class="normal">15</span>
|
||||
<span class="normal">16</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1"># inside your mygame/typeclasses/objects.py</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">DefaultObject</span>
|
||||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">AttributeProperty</span>
|
||||
|
||||
<span class="hll"><span class="k">class</span> <span class="nc">ObjectParent</span><span class="p">:</span>
|
||||
</span>
|
||||
<span class="hll"> <span class="n">weight</span> <span class="o">=</span> <span class="n">AttributeProperty</span><span class="p">(</span><span class="n">default</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||||
</span>
|
||||
<span class="hll"> <span class="nd">@property</span>
|
||||
</span> <span class="k">def</span> <span class="nf">total_weight</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="hll"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">weight</span> <span class="o">+</span> <span class="nb">sum</span><span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">total_weight</span> <span class="k">for</span> <span class="n">obj</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">)</span>
|
||||
</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">Object</span><span class="p">(</span><span class="n">ObjectParent</span><span class="p">,</span> <span class="n">DefaultObject</span><span class="p">):</span>
|
||||
<span class="c1"># ...</span>
|
||||
</pre></div></td></tr></table></div>
|
||||
</div>
|
||||
<aside class="sidebar">
|
||||
<p class="sidebar-title">Why not mass? </p>
|
||||
<p>Yes, we know weight varies with gravity. ‘Mass’ is more scientifically correct. But ‘mass’ is less commonly used in RPGs, so we stick to ‘weight’ here. Just know if if your sci-fi characters can vacation on the Moon (1/6 gravity of Earth) you should consider using <code class="docutils literal notranslate"><span class="pre">mass</span></code> everywhere and calculate the current weight on the fly.</p>
|
||||
</aside>
|
||||
<ul class="simple">
|
||||
<li><p><strong>Line 6</strong>: We use the <code class="docutils literal notranslate"><span class="pre">ObjectParent</span></code> mixin. Since this mixin is used for <code class="docutils literal notranslate"><span class="pre">Characters</span></code>, <code class="docutils literal notranslate"><span class="pre">Exits</span></code> and <code class="docutils literal notranslate"><span class="pre">Rooms</span></code> as well as for <code class="docutils literal notranslate"><span class="pre">Object</span></code>, it means all of those will automatically <em>also</em> have weight!</p></li>
|
||||
<li><p><strong>Line 8</strong>: We use an <a class="reference internal" href="../Components/Attributes.html#using-attributeproperty"><span class="std std-doc">AttributeProperty</span></a> to set up the ‘default’ weight of 1 (whatever that is). Setting <code class="docutils literal notranslate"><span class="pre">autocreate=False</span></code> means no actual <code class="docutils literal notranslate"><span class="pre">Attribute</span></code> will be created until the weight is actually changed from the default of 1. See the <code class="docutils literal notranslate"><span class="pre">AttributeProperty</span></code> documentation for caveats with this.</p></li>
|
||||
<li><p><strong>Line 10 and 11</strong>: Using the <code class="docutils literal notranslate"><span class="pre">@property</span></code> decorator on <code class="docutils literal notranslate"><span class="pre">total_weight</span></code> means that we will be able to call <code class="docutils literal notranslate"><span class="pre">obj.total_weight</span></code> instead of <code class="docutils literal notranslate"><span class="pre">obj.total_weight()</span></code> later.</p></li>
|
||||
<li><p><strong>Line 12</strong>: We sum up all weights from everything “in” this object, by looping over <code class="docutils literal notranslate"><span class="pre">self.contents</span></code>. Since <em>all</em> objects will have weight now, this should always work!</p></li>
|
||||
</ul>
|
||||
<p>Let’s check out the weight of some trusty boxes</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">></span> <span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">box1</span>
|
||||
<span class="o">></span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">"box1"</span><span class="p">)</span><span class="o">.</span><span class="n">weight</span>
|
||||
<span class="mi">1</span>
|
||||
<span class="o">></span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">"box1"</span><span class="p">)</span><span class="o">.</span><span class="n">total_weight</span>
|
||||
<span class="mi">1</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Let’s put another box into the first one.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">></span> <span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">box2</span>
|
||||
<span class="o">></span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">"box2"</span><span class="p">)</span><span class="o">.</span><span class="n">total_weight</span>
|
||||
<span class="mi">1</span>
|
||||
<span class="o">></span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">"box2"</span><span class="p">)</span><span class="o">.</span><span class="n">location</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">"box1"</span><span class="p">)</span>
|
||||
<span class="o">></span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="n">box1</span><span class="p">)</span><span class="o">.</span><span class="n">total_weight</span>
|
||||
<span class="mi">2</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="limit-inventory-by-weight-carried">
|
||||
<h2>Limit inventory by weight carried<a class="headerlink" href="#limit-inventory-by-weight-carried" title="Permalink to this headline">¶</a></h2>
|
||||
<p>To limit how much you can carry, you first need to know your own strength</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/typeclasses/characters.py </span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">AttributeProperty</span>
|
||||
|
||||
<span class="c1"># ... </span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">Character</span><span class="p">(</span><span class="n">ObjectParent</span><span class="p">,</span> <span class="n">DefaultCharacter</span><span class="p">):</span>
|
||||
|
||||
<span class="n">carrying_capacity</span> <span class="o">=</span> <span class="n">AttributeProperty</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">autocreate</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">carried_weight</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">total_weight</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">weight</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Here we make sure to add another <code class="docutils literal notranslate"><span class="pre">AttributeProperty</span></code> telling us how much to carry. In a real game, this may be based on how strong the Character is. When we consider how much weight we already carry, we should not include <em>our own</em> weight, so we subtract that.</p>
|
||||
<p>To honor this limit, we’ll need to override the default <code class="docutils literal notranslate"><span class="pre">get</span></code> command.</p>
|
||||
<aside class="sidebar">
|
||||
<p class="sidebar-title">Overriding default commands</p>
|
||||
<p>In this example, we implement the beginning of the <code class="docutils literal notranslate"><span class="pre">CmdGet</span></code> and then call the full <code class="docutils literal notranslate"><span class="pre">CmdGet()</span></code> at the end. This is not very efficient, because the parent <code class="docutils literal notranslate"><span class="pre">CmdGet</span></code> will again have to do the <code class="docutils literal notranslate"><span class="pre">caller.search()</span></code> again. To be more efficient, you will likely want to copy the entirety of the <code class="docutils literal notranslate"><span class="pre">CmdGet</span></code> code into your own version and modify it.</p>
|
||||
</aside>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/commands/command.py </span>
|
||||
|
||||
<span class="c1"># ... </span>
|
||||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">default_cmds</span>
|
||||
|
||||
<span class="c1"># ... </span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">WeightAwareCmdGet</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">CmdGet</span><span class="p">):</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">caller</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</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">"Get what?"</span><span class="p">)</span>
|
||||
<span class="k">return</span>
|
||||
|
||||
<span class="n">obj</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">)</span>
|
||||
|
||||
<span class="k">if</span> <span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">weight</span> <span class="o">+</span> <span class="n">caller</span><span class="o">.</span><span class="n">carried_weight</span>
|
||||
<span class="o">></span> <span class="n">caller</span><span class="o">.</span><span class="n">carrying_capacity</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">"You can't carry that much!"</span><span class="p">)</span>
|
||||
<span class="k">return</span>
|
||||
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">func</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Here we add an extra check for the weight of the thing we are trying to pick up, then we call the normal <code class="docutils literal notranslate"><span class="pre">CmdGet</span></code> with <code class="docutils literal notranslate"><span class="pre">super().func()</span></code>.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="../genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-NPC-Listening.html" title="NPCs that listen to what is said"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Howto-Default-Exit-Errors.html" title="Return custom errors on missing Exits"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Give objects weight</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2022, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Command Cooldown — Evennia 1.0-dev documentation</title>
|
||||
<title>Adding Command Cooldowns — 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>
|
||||
|
|
@ -17,8 +17,8 @@
|
|||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Command Duration" href="Howto-Command-Duration.html" />
|
||||
<link rel="prev" title="Command Prompt" href="Howto-Command-Prompt.html" />
|
||||
<link rel="next" title="Commands that take time to finish" href="Howto-Command-Duration.html" />
|
||||
<link rel="prev" title="Adding a Command Prompt" href="Howto-Command-Prompt.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -30,14 +30,14 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Howto-Command-Duration.html" title="Command Duration"
|
||||
<a href="Howto-Command-Duration.html" title="Commands that take time to finish"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Howto-Command-Prompt.html" title="Command Prompt"
|
||||
<a href="Howto-Command-Prompt.html" title="Adding a Command Prompt"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Command Cooldown</a></li>
|
||||
<li class="nav-item nav-item-this"><a href="">Adding Command Cooldowns</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
|
@ -62,10 +62,11 @@
|
|||
<script>$('#searchbox').show(0);</script>
|
||||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Command Cooldown</a><ul>
|
||||
<li><a class="reference internal" href="#the-cooldown-contrib">The Cooldown Contrib</a></li>
|
||||
<li><a class="reference internal" href="#non-persistent-cooldown">Non-persistent cooldown</a></li>
|
||||
<li><a class="reference internal" href="#persistent-cooldown">Persistent cooldown</a></li>
|
||||
<li><a class="reference internal" href="#">Adding Command Cooldowns</a><ul>
|
||||
<li><a class="reference internal" href="#an-efficient-cooldown">An efficient cooldown</a><ul>
|
||||
<li><a class="reference internal" href="#non-persistent-cooldown">Non-Persistent cooldown</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#make-a-cooldown-aware-command-parent">Make a cooldown-aware command parent</a><ul>
|
||||
<li><a class="reference internal" href="#command-crossover">Command crossover</a></li>
|
||||
</ul>
|
||||
|
|
@ -76,10 +77,10 @@
|
|||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Howto-Command-Prompt.html"
|
||||
title="previous chapter">Command Prompt</a></p>
|
||||
title="previous chapter">Adding a Command Prompt</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Howto-Command-Duration.html"
|
||||
title="next chapter">Command Duration</a></p>
|
||||
title="next chapter">Commands that take time to finish</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -110,31 +111,28 @@
|
|||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="command-cooldown">
|
||||
<h1>Command Cooldown<a class="headerlink" href="#command-cooldown" title="Permalink to this headline">¶</a></h1>
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="adding-command-cooldowns">
|
||||
<h1>Adding Command Cooldowns<a class="headerlink" href="#adding-command-cooldowns" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> hit goblin with sword
|
||||
You strike goblin with the sword. It dodges!
|
||||
> hit goblin with sword
|
||||
You are off-balance and can't attack again yet.
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Some types of games want to limit how often a command can be run. If a
|
||||
character casts the spell <em>Firestorm</em>, you might not want them to spam that
|
||||
command over and over. Or in an advanced combat system, a massive swing may
|
||||
command over and over. In an advanced combat system, a massive swing may
|
||||
offer a chance of lots of damage at the cost of not being able to re-do it for
|
||||
a while. Such effects are called <em>cooldowns</em>.</p>
|
||||
<p>This page exemplifies a very resource-efficient way to do cooldowns. A more
|
||||
‘active’ way is to use asynchronous delays as in the <a class="reference internal" href="Howto-Command-Duration.html#blocking-commands"><span class="std std-doc">Blocking commands</span></a>, the two might be useful to
|
||||
combine if you want to echo some message to the user after the cooldown ends.</p>
|
||||
<section id="the-cooldown-contrib">
|
||||
<h2>The Cooldown Contrib<a class="headerlink" href="#the-cooldown-contrib" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <a class="reference internal" href="../Contribs/Contrib-Cooldowns.html"><span class="doc std std-doc">Cooldown contrib</span></a> is a ready-made solution for
|
||||
command cooldowns you can use. It implements a <em>handler</em> on the object to
|
||||
conveniently manage and store the cooldowns in a similar manner exemplified in
|
||||
this tutorial.</p>
|
||||
</section>
|
||||
<section id="non-persistent-cooldown">
|
||||
<h2>Non-persistent cooldown<a class="headerlink" href="#non-persistent-cooldown" title="Permalink to this headline">¶</a></h2>
|
||||
<p>This little recipe will limit how often a particular command can be run. Since
|
||||
Commands are class instances, and those are cached in memory, a command
|
||||
instance will remember things you store on it. So just store the current time
|
||||
of execution! Next time the command is run, it just needs to check if it has
|
||||
that time stored, and compare it with the current time to see if a desired
|
||||
delay has passed.</p>
|
||||
a while.</p>
|
||||
<p>Such effects are called <em>command cooldowns</em>.</p>
|
||||
<aside class="sidebar">
|
||||
<p>The <a class="reference internal" href="../Contribs/Contrib-Cooldowns.html"><span class="doc std std-doc">Cooldown contrib</span></a> is a ready-made solution for command cooldowns. It is based on this howto and implements a <span class="xref myst">handler</span> on the object to conveniently manage and store the cooldowns.</p>
|
||||
</aside>
|
||||
<p>This howto exemplifies a very resource-efficient way to do cooldowns. A more
|
||||
‘active’ way is to use asynchronous delays as in the <span class="xref myst">Command-Duration howto</span> suggests. The two howto’s might be useful to combine if you want to echo some message to the user after the cooldown ends.</p>
|
||||
<section id="an-efficient-cooldown">
|
||||
<h2>An efficient cooldown<a class="headerlink" href="#an-efficient-cooldown" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The idea is that when a <a class="reference internal" href="../Components/Commands.html"><span class="doc std std-doc">Command</span></a> runs, we store the time it runs. When it next runs, we check again the current time. The command is only allowed to run if enough time passed since now and the previous run. This is a <em>very</em> efficient implementation that only checks on-demand.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in, say, mygame/commands/spells.py</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">time</span>
|
||||
|
|
@ -157,7 +155,7 @@ delay has passed.</p>
|
|||
<span class="s2">"Implement the spell"</span>
|
||||
|
||||
<span class="n">now</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
|
||||
<span class="n">last_cast</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">firestorm_last_cast</span> <span class="c1"># could be None</span>
|
||||
<span class="n">last_cast</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">firestorm_last_cast</span> <span class="c1"># could be None</span>
|
||||
<span class="k">if</span> <span class="n">last_cast</span> <span class="ow">and</span> <span class="p">(</span><span class="n">now</span> <span class="o">-</span> <span class="n">last_cast</span> <span class="o"><</span> <span class="bp">self</span><span class="o">.</span><span class="n">rate_of_fire</span><span class="p">):</span>
|
||||
<span class="n">message</span> <span class="o">=</span> <span class="s2">"You cannot cast this spell again yet."</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">message</span><span class="p">)</span>
|
||||
|
|
@ -166,21 +164,20 @@ delay has passed.</p>
|
|||
<span class="c1"># [the spell effect is implemented]</span>
|
||||
|
||||
<span class="c1"># if the spell was successfully cast, store the casting time</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">firestorm_last_cast</span> <span class="o">=</span> <span class="n">now</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">firestorm_last_cast</span> <span class="o">=</span> <span class="n">now</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>We specify <code class="docutils literal notranslate"><span class="pre">rate_of_fire</span></code> and then just check for a NAtrribute
|
||||
<code class="docutils literal notranslate"><span class="pre">firestorm_last_cast</span></code> and update it if everything works out.</p>
|
||||
<p>Simple and very effective since everything is just stored in memory. The
|
||||
drawback of this simple scheme is that it’s non-persistent. If you do
|
||||
<code class="docutils literal notranslate"><span class="pre">reload</span></code>, the cache is cleaned and all such ongoing cooldowns will be
|
||||
forgotten.</p>
|
||||
<p>We specify <code class="docutils literal notranslate"><span class="pre">rate_of_fire</span></code> and then just check for an <a class="reference internal" href="../Components/Attributes.html"><span class="doc std std-doc">Attribute</span></a> <code class="docutils literal notranslate"><span class="pre">firestorm_last_cast</span></code> on the <code class="docutils literal notranslate"><span class="pre">caller.</span></code> It is either <code class="docutils literal notranslate"><span class="pre">None</span></code> (because the spell was never cast before) or an timestamp representing the last time the spell was cast.</p>
|
||||
<section id="non-persistent-cooldown">
|
||||
<h3>Non-Persistent cooldown<a class="headerlink" href="#non-persistent-cooldown" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The above implementation will survive a reload. If you don’t want that, you can just switch to let <code class="docutils literal notranslate"><span class="pre">firestorm_last_cast</span></code> be a <a class="reference internal" href="../Components/Attributes.html#in-memory-attributes-nattributes"><span class="std std-doc">NAtrribute</span></a> instead. For example:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">last_cast</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">firestorm_last_cast</span>
|
||||
<span class="c1"># ... </span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">firestorm_last_cast</span> <span class="o">=</span> <span class="n">now</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>That is, use <code class="docutils literal notranslate"><span class="pre">.ndb</span></code> instead of <code class="docutils literal notranslate"><span class="pre">.db</span></code>. Since a <code class="docutils literal notranslate"><span class="pre">NAttribute</span></code>s are purely in-memory, they can be faster to read and write to than an <code class="docutils literal notranslate"><span class="pre">Attribute</span></code>. So this can be more optimal if your intervals are short and need to change often. The drawback is that they’ll reset if the server reloads.</p>
|
||||
</section>
|
||||
<section id="persistent-cooldown">
|
||||
<h2>Persistent cooldown<a class="headerlink" href="#persistent-cooldown" title="Permalink to this headline">¶</a></h2>
|
||||
<p>To make a cooldown <em>persistent</em> (so it survives a server reload), just
|
||||
use the same technique, but use <a class="reference internal" href="../Components/Attributes.html"><span class="doc std std-doc">Attributes</span></a> (that is, <code class="docutils literal notranslate"><span class="pre">.db</span></code> instead
|
||||
of <code class="docutils literal notranslate"><span class="pre">.ndb</span></code> storage to save the last-cast time.</p>
|
||||
</section>
|
||||
<section id="make-a-cooldown-aware-command-parent">
|
||||
<h2>Make a cooldown-aware command parent<a class="headerlink" href="#make-a-cooldown-aware-command-parent" title="Permalink to this headline">¶</a></h2>
|
||||
|
|
@ -253,7 +250,7 @@ reuse this mixin for all your cooldowns.</p>
|
|||
you can have all fire-related spells store the cooldown with the same
|
||||
<code class="docutils literal notranslate"><span class="pre">cooldown_storage_key</span></code> (like <code class="docutils literal notranslate"><span class="pre">fire_spell_last_used</span></code>). That would mean casting
|
||||
of <em>Firestorm</em> would block all other fire-related spells for a while.</p>
|
||||
<p>Similarly, when you take that that big sword swing, other types of attacks could
|
||||
<p>Similarly, when you take that big sword swing, other types of attacks could
|
||||
be blocked before you can recover your balance.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
|
@ -275,14 +272,14 @@ be blocked before you can recover your balance.</p>
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Howto-Command-Duration.html" title="Command Duration"
|
||||
<a href="Howto-Command-Duration.html" title="Commands that take time to finish"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Howto-Command-Prompt.html" title="Command Prompt"
|
||||
<a href="Howto-Command-Prompt.html" title="Adding a Command Prompt"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Command Cooldown</a></li>
|
||||
<li class="nav-item nav-item-this"><a href="">Adding Command Cooldowns</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Command Duration — Evennia 1.0-dev documentation</title>
|
||||
<title>Commands that take time to finish — 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>
|
||||
|
|
@ -17,8 +17,8 @@
|
|||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Default Exit Errors" href="Howto-Default-Exit-Errors.html" />
|
||||
<link rel="prev" title="Command Cooldown" href="Howto-Command-Cooldown.html" />
|
||||
<link rel="next" title="Return custom errors on missing Exits" href="Howto-Default-Exit-Errors.html" />
|
||||
<link rel="prev" title="Adding Command Cooldowns" href="Howto-Command-Cooldown.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -30,14 +30,14 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Howto-Default-Exit-Errors.html" title="Default Exit Errors"
|
||||
<a href="Howto-Default-Exit-Errors.html" title="Return custom errors on missing Exits"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Howto-Command-Cooldown.html" title="Command Cooldown"
|
||||
<a href="Howto-Command-Cooldown.html" title="Adding Command Cooldowns"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Command Duration</a></li>
|
||||
<li class="nav-item nav-item-this"><a href="">Commands that take time to finish</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
|
@ -62,25 +62,21 @@
|
|||
<script>$('#searchbox').show(0);</script>
|
||||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Command Duration</a><ul>
|
||||
<li><a class="reference internal" href="#the-simple-way-to-pause-commands-with-yield">The simple way to pause commands with yield</a></li>
|
||||
<li><a class="reference internal" href="#the-more-advanced-way-with-utils-delay">The more advanced way with utils.delay</a><ul>
|
||||
<li><a class="reference internal" href="#about-utils-delay">About utils.delay()</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#blocking-commands">Blocking commands</a></li>
|
||||
<li><a class="reference internal" href="#abortable-commands">Abortable commands</a></li>
|
||||
<li><a class="reference internal" href="#persistent-delays">Persistent delays</a></li>
|
||||
<li><a class="reference internal" href="#">Commands that take time to finish</a><ul>
|
||||
<li><a class="reference internal" href="#pause-commands-with-yield">Pause commands with <code class="docutils literal notranslate"><span class="pre">yield</span></code></a></li>
|
||||
<li><a class="reference internal" href="#pause-commands-with-utils-delay">Pause commands with <code class="docutils literal notranslate"><span class="pre">utils.delay</span></code></a></li>
|
||||
<li><a class="reference internal" href="#making-a-blocking-command">Making a blocking command</a></li>
|
||||
<li><a class="reference internal" href="#make-a-command-possible-to-abort">Make a Command possible to Abort</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Howto-Command-Cooldown.html"
|
||||
title="previous chapter">Command Cooldown</a></p>
|
||||
title="previous chapter">Adding Command Cooldowns</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Howto-Default-Exit-Errors.html"
|
||||
title="next chapter">Default Exit Errors</a></p>
|
||||
title="next chapter">Return custom errors on missing Exits</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -111,23 +107,52 @@
|
|||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="command-duration">
|
||||
<h1>Command Duration<a class="headerlink" href="#command-duration" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Before reading this tutorial, if you haven’t done so already, you might want to
|
||||
read <a class="reference internal" href="../Components/Commands.html"><span class="doc std std-doc">the documentation on commands</span></a> to get a basic understanding of
|
||||
how commands work in Evennia.</p>
|
||||
<p>In some types of games a command should not start and finish immediately.
|
||||
Loading a crossbow might take a bit of time to do - time you don’t have when
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="commands-that-take-time-to-finish">
|
||||
<h1>Commands that take time to finish<a class="headerlink" href="#commands-that-take-time-to-finish" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> craft fine sword
|
||||
You start crafting a fine sword.
|
||||
> north
|
||||
You are too focused on your crafting, and can't move!
|
||||
You create the blade of the sword.
|
||||
You create the pommel of the sword.
|
||||
You finish crafting a Fine Sword.
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>In some types of games a command should not start and finish immediately.</p>
|
||||
<p>Loading a crossbow might take a bit of time to do - time you don’t have when
|
||||
the enemy comes rushing at you. Crafting that armour will not be immediate
|
||||
either. For some types of games the very act of moving or changing pose all
|
||||
comes with a certain time associated with it.</p>
|
||||
<section id="the-simple-way-to-pause-commands-with-yield">
|
||||
<h2>The simple way to pause commands with yield<a class="headerlink" href="#the-simple-way-to-pause-commands-with-yield" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Evennia allows a shortcut in syntax to create simple pauses in commands. This
|
||||
syntax uses the <code class="docutils literal notranslate"><span class="pre">yield</span></code> keyword. The <code class="docutils literal notranslate"><span class="pre">yield</span></code> keyword is used in Python to
|
||||
create generators, although you don’t need to know what generators are to use
|
||||
this syntax. A short example will probably make it clear:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">CmdTest</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
||||
<p>There are two main suitable ways to introduce a ‘delay’ in a <a class="reference internal" href="../Components/Commands.html"><span class="doc std std-doc">Command</span></a>’s execution:</p>
|
||||
<ul class="simple">
|
||||
<li><p>Using <code class="docutils literal notranslate"><span class="pre">yield</span></code> in the Command’s <code class="docutils literal notranslate"><span class="pre">func</span></code> method.</p></li>
|
||||
<li><p>Using the <code class="docutils literal notranslate"><span class="pre">evennia.utils.delay</span></code> utility function.</p></li>
|
||||
</ul>
|
||||
<p>We’ll simplify both below.</p>
|
||||
<section id="pause-commands-with-yield">
|
||||
<h2>Pause commands with <code class="docutils literal notranslate"><span class="pre">yield</span></code><a class="headerlink" href="#pause-commands-with-yield" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">yield</span></code> keyword is a reserved word in Python. It’s used to create <a class="reference external" href="https://realpython.com/introduction-to-python-generators/">generators</a>, which are interesting in their own right. For the purpose of this howto though, we just need to know that Evennia will use it to ‘pause’ the execution of the command for a certain time.</p>
|
||||
<aside class="sidebar">
|
||||
<p class="sidebar-title">This only works in Command.func!</p>
|
||||
<p>This <code class="docutils literal notranslate"><span class="pre">yield</span></code> functionality will <em>only</em> work in the <code class="docutils literal notranslate"><span class="pre">func</span></code> method of
|
||||
Commands. It works because Evennia has especially catered for it as a convenient shortcut. Trying to use it elsewhere will not work. If you want the same functionality elsewhere you should look up the <a class="reference internal" href="../Concepts/Async-Process.html#the-interactive-decorator"><span class="std std-doc">interactive decorator</span></a>.</p>
|
||||
</aside>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
|
||||
<span class="normal"> 2</span>
|
||||
<span class="normal"> 3</span>
|
||||
<span class="normal"> 4</span>
|
||||
<span class="normal"> 5</span>
|
||||
<span class="normal"> 6</span>
|
||||
<span class="normal"> 7</span>
|
||||
<span class="normal"> 8</span>
|
||||
<span class="normal"> 9</span>
|
||||
<span class="normal">10</span>
|
||||
<span class="normal">11</span>
|
||||
<span class="normal">12</span>
|
||||
<span class="normal">13</span>
|
||||
<span class="normal">14</span>
|
||||
<span class="normal">15</span>
|
||||
<span class="normal">16</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">class</span> <span class="nc">CmdTest</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
||||
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> A test command just to test waiting.</span>
|
||||
|
|
@ -138,51 +163,81 @@ this syntax. A short example will probably make it clear:</p>
|
|||
<span class="sd"> """</span>
|
||||
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"test"</span>
|
||||
<span class="n">locks</span> <span class="o">=</span> <span class="s2">"cmd:all()"</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="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Before ten seconds..."</span><span class="p">)</span>
|
||||
<span class="k">yield</span> <span class="mi">10</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Afterwards."</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
<span class="hll"> <span class="k">yield</span> <span class="mi">10</span>
|
||||
</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Afterwards."</span><span class="p">)</span>
|
||||
</pre></div></td></tr></table></div>
|
||||
</div>
|
||||
<blockquote>
|
||||
<div><p>Important: The <code class="docutils literal notranslate"><span class="pre">yield</span></code> functionality will <em>only</em> work in the <code class="docutils literal notranslate"><span class="pre">func</span></code> method of
|
||||
Commands. It only works because Evennia has especially
|
||||
catered for it in Commands. If you want the same functionality elsewhere you
|
||||
must use the <a class="reference internal" href="../Concepts/Async-Process.html#the-interactive-decorator"><span class="std std-doc">interactive decorator</span></a>.</p>
|
||||
</div></blockquote>
|
||||
<p>The important line is the <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">10</span></code>. It tells Evennia to “pause” the command
|
||||
<ul class="simple">
|
||||
<li><p><strong>Line 15</strong> : This is the important line. The <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">10</span></code> tells Evennia to “pause” the command
|
||||
and to wait for 10 seconds to execute the rest. If you add this command and
|
||||
run it, you’ll see the first message, then, after a pause of ten seconds, the
|
||||
next message. You can use <code class="docutils literal notranslate"><span class="pre">yield</span></code> several times in your command.</p>
|
||||
<p>This syntax will not “freeze” all commands. While the command is “pausing”,
|
||||
you can execute other commands (or even call the same command again). And
|
||||
other players aren’t frozen either.</p>
|
||||
next message. You can use <code class="docutils literal notranslate"><span class="pre">yield</span></code> several times in your command.</p></li>
|
||||
</ul>
|
||||
<p>This syntax will not “freeze” all commands. While the command is “pausing”, you can execute other commands (or even call the same command again). And other players aren’t frozen either.</p>
|
||||
<blockquote>
|
||||
<div><p>Note: this will not save anything in the database. If you reload the game
|
||||
while a command is “paused”, it will not resume after the server has
|
||||
reloaded.</p>
|
||||
<div><p>Using <code class="docutils literal notranslate"><span class="pre">yield</span></code> is non-persistent. If you <code class="docutils literal notranslate"><span class="pre">reload</span></code> the game while a command is “paused”, that pause state is lost and it will <em>not</em> resume after the server has reloaded.</p>
|
||||
</div></blockquote>
|
||||
</section>
|
||||
<section id="the-more-advanced-way-with-utils-delay">
|
||||
<h2>The more advanced way with utils.delay<a class="headerlink" href="#the-more-advanced-way-with-utils-delay" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">yield</span></code> syntax is easy to read, easy to understand, easy to use. But it’s not that flexible if
|
||||
you want more advanced options. Learning to use alternatives might be much worth it in the end.</p>
|
||||
<p>Below is a simple command example for adding a duration for a command to finish.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">default_cmds</span><span class="p">,</span> <span class="n">utils</span>
|
||||
<section id="pause-commands-with-utils-delay">
|
||||
<h2>Pause commands with <code class="docutils literal notranslate"><span class="pre">utils.delay</span></code><a class="headerlink" href="#pause-commands-with-utils-delay" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">yield</span></code> syntax is easy to read, easy to understand, easy to use. But it’s non-persistent and not that flexible if you want more advanced options.</p>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">evennia.utils.delay</span></code> represents is a more powerful way to introduce delays. Unlike <code class="docutils literal notranslate"><span class="pre">yield</span></code>, it<br />
|
||||
can be made persistent and also works outside of <code class="docutils literal notranslate"><span class="pre">Command.func</span></code>. It’s however a little more cumbersome to write since unlike <code class="docutils literal notranslate"><span class="pre">yield</span></code> it will not actually stop at the line it’s called.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
|
||||
<span class="normal"> 2</span>
|
||||
<span class="normal"> 3</span>
|
||||
<span class="normal"> 4</span>
|
||||
<span class="normal"> 5</span>
|
||||
<span class="normal"> 6</span>
|
||||
<span class="normal"> 7</span>
|
||||
<span class="normal"> 8</span>
|
||||
<span class="normal"> 9</span>
|
||||
<span class="normal">10</span>
|
||||
<span class="normal">11</span>
|
||||
<span class="normal">12</span>
|
||||
<span class="normal">13</span>
|
||||
<span class="normal">14</span>
|
||||
<span class="normal">15</span>
|
||||
<span class="normal">16</span>
|
||||
<span class="normal">17</span>
|
||||
<span class="normal">18</span>
|
||||
<span class="normal">19</span>
|
||||
<span class="normal">20</span>
|
||||
<span class="normal">21</span>
|
||||
<span class="normal">22</span>
|
||||
<span class="normal">23</span>
|
||||
<span class="normal">24</span>
|
||||
<span class="normal">25</span>
|
||||
<span class="normal">26</span>
|
||||
<span class="normal">27</span>
|
||||
<span class="normal">28</span>
|
||||
<span class="normal">29</span>
|
||||
<span class="normal">30</span>
|
||||
<span class="normal">31</span></pre></div></td><td class="code"><div><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">default_cmds</span><span class="p">,</span> <span class="n">utils</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">CmdEcho</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">MuxCommand</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> wait for an echo</span>
|
||||
<span class="sd"> Wait for an echo</span>
|
||||
<span class="sd"> </span>
|
||||
<span class="sd"> Usage: </span>
|
||||
<span class="sd"> echo <string></span>
|
||||
<span class="sd"> </span>
|
||||
<span class="sd"> Calls and waits for an echo</span>
|
||||
<span class="sd"> Calls and waits for an echo.</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"echo"</span>
|
||||
<span class="n">locks</span> <span class="o">=</span> <span class="s2">"cmd:all()"</span>
|
||||
|
||||
<span class="hll"> <span class="k">def</span> <span class="nf">echo</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
</span> <span class="s2">"Called after 10 seconds."</span>
|
||||
<span class="n">shout</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</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="s2">"You hear an echo: "</span>
|
||||
<span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">shout</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span><span class="si">}</span><span class="s2"> ... "</span>
|
||||
<span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">shout</span><span class="o">.</span><span class="n">capitalize</span><span class="p">()</span><span class="si">}</span><span class="s2"> ... "</span>
|
||||
<span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">shout</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</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="sd">"""</span>
|
||||
|
|
@ -190,50 +245,67 @@ you want more advanced options. Learning to use alternatives might be much wort
|
|||
<span class="sd"> """</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="sa">f</span><span class="s2">"You shout '</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="si">}</span><span class="s2">' and wait for an echo ..."</span><span class="p">)</span>
|
||||
<span class="c1"># this waits non-blocking for 10 seconds, then calls self.echo</span>
|
||||
<span class="n">utils</span><span class="o">.</span><span class="n">delay</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">echo</span><span class="p">)</span> <span class="c1"># call echo after 10 seconds</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">echo</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="s2">"Called after 10 seconds."</span>
|
||||
<span class="n">shout</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</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="sa">f</span><span class="s2">"You hear an echo: </span><span class="si">{</span><span class="n">shout</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span><span class="si">}</span><span class="s2"> ... </span><span class="si">{</span><span class="n">shout</span><span class="o">.</span><span class="n">capitalize</span><span class="p">()</span><span class="si">}</span><span class="s2"> ... </span><span class="si">{</span><span class="n">shout</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="hll"> <span class="n">utils</span><span class="o">.</span><span class="n">delay</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">echo</span><span class="p">)</span> <span class="c1"># call echo after 10 seconds</span>
|
||||
</span>
|
||||
</pre></div></td></tr></table></div>
|
||||
</div>
|
||||
<p>Import this new echo command into the default command set and reload the server. You will find that it will take 10 seconds before you see your shout coming back.</p>
|
||||
<ul class="simple">
|
||||
<li><p><strong>Line 14</strong>: We add a new method <code class="docutils literal notranslate"><span class="pre">echo</span></code>. This is a <em>callback</em> - a method/function we will call after a certain time.</p></li>
|
||||
<li><p><strong>Line 30</strong>: Here we use <code class="docutils literal notranslate"><span class="pre">utils.delay</span></code> to tell Evennia “Please wait for 10 seconds, then call “<code class="docutils literal notranslate"><span class="pre">self.echo</span></code>”. Note how we pass <code class="docutils literal notranslate"><span class="pre">self.echo</span></code> and <em>not</em> <code class="docutils literal notranslate"><span class="pre">self.echo()</span></code>! If we did the latter, <code class="docutils literal notranslate"><span class="pre">echo</span></code> would fire <em>immediately</em>. Instead we let Evennia do this call for us ten seconds later.</p></li>
|
||||
</ul>
|
||||
<p>You will also find that this is a <em>non-blocking</em> effect; you can issue other commands in the interim and the game will go on as usual. The echo will come back to you in its own time.</p>
|
||||
<p>The call signature for <code class="docutils literal notranslate"><span class="pre">utils.delay</span></code> is:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">utils</span><span class="o">.</span><span class="n">delay</span><span class="p">(</span><span class="n">timedelay</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span> <span class="n">persistent</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Import this new echo command into the default command set and reload the server. You will find that
|
||||
it will take 10 seconds before you see your shout coming back. You will also find that this is a
|
||||
<em>non-blocking</em> effect; you can issue other commands in the interim and the game will go on as usual.
|
||||
The echo will come back to you in its own time.</p>
|
||||
<section id="about-utils-delay">
|
||||
<h3>About utils.delay()<a class="headerlink" href="#about-utils-delay" title="Permalink to this headline">¶</a></h3>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">utils.delay(timedelay,</span> <span class="pre">callback,</span> <span class="pre">persistent=False,</span> <span class="pre">*args,</span> <span class="pre">**kwargs)</span></code> is a useful function. It will
|
||||
wait <code class="docutils literal notranslate"><span class="pre">timedelay</span></code> seconds, then call the <code class="docutils literal notranslate"><span class="pre">callback</span></code> function, optionally passing to it the arguments
|
||||
provided to utils.delay by way of *args and/or **kwargs`.</p>
|
||||
<blockquote>
|
||||
<div><p>Note: The callback argument should be provided with a python path to the desired function, for
|
||||
instance <code class="docutils literal notranslate"><span class="pre">my_object.my_function</span></code> instead of <code class="docutils literal notranslate"><span class="pre">my_object.my_function()</span></code>. Otherwise my_function would
|
||||
get called and run immediately upon attempting to pass it to the delay function.
|
||||
If you want to provide arguments for utils.delay to use, when calling your callback function, you
|
||||
have to do it separatly, for instance using the utils.delay *args and/or **kwargs, as mentioned
|
||||
above.</p>
|
||||
</div></blockquote>
|
||||
<blockquote>
|
||||
<div><p>If you are not familiar with the syntax <code class="docutils literal notranslate"><span class="pre">*args</span></code> and <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code>, <a class="reference external" href="https://docs.python.org/2/tutorial/controlflow.html#arbitrary-argument-lists">see the Python documentation
|
||||
here</a>.</p>
|
||||
</div></blockquote>
|
||||
<p>Looking at it you might think that <code class="docutils literal notranslate"><span class="pre">utils.delay(10,</span> <span class="pre">callback)</span></code> in the code above is just an
|
||||
alternative to some more familiar thing like <code class="docutils literal notranslate"><span class="pre">time.sleep(10)</span></code>. This is <em>not</em> the case. If you do
|
||||
<code class="docutils literal notranslate"><span class="pre">time.sleep(10)</span></code> you will in fact freeze the <em>entire server</em> for ten seconds! The <code class="docutils literal notranslate"><span class="pre">utils.delay()</span></code>is
|
||||
a thin wrapper around a Twisted
|
||||
<a class="reference external" href="https://twistedmatrix.com/documents/11.0.0/core/howto/defer.html">Deferred</a> that will delay
|
||||
execution until 10 seconds have passed, but will do so asynchronously, without bothering anyone else
|
||||
(not even you - you can continue to do stuff normally while it waits to continue).</p>
|
||||
<p>The point to remember here is that the <code class="docutils literal notranslate"><span class="pre">delay()</span></code> call will not “pause” at that point when it is
|
||||
<aside class="sidebar">
|
||||
<p class="sidebar-title">*args and **kwargs </p>
|
||||
<p>These are used to indicate any number of arguments or keyword-arguments should be picked up here. In code they are treated as a <code class="docutils literal notranslate"><span class="pre">tuple</span></code> and a <code class="docutils literal notranslate"><span class="pre">dict</span></code> respectively.</p>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">*args</span></code> and <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> are used in many places in Evennia. <a class="reference external" href="https://realpython.com/python-kwargs-and-args">See an online tutorial here</a>.</p>
|
||||
</aside>
|
||||
<p>If you set <code class="docutils literal notranslate"><span class="pre">persistent=True</span></code>, this delay will survive a <code class="docutils literal notranslate"><span class="pre">reload</span></code>. If you pass <code class="docutils literal notranslate"><span class="pre">*args</span></code> and/or <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code>, they will be passed on into the <code class="docutils literal notranslate"><span class="pre">callback</span></code>. So this way you can pass more complex arguments to the delayed function.</p>
|
||||
<p>It’s important to remember that the <code class="docutils literal notranslate"><span class="pre">delay()</span></code> call will not “pause” at that point when it is
|
||||
called (the way <code class="docutils literal notranslate"><span class="pre">yield</span></code> does in the previous section). The lines after the <code class="docutils literal notranslate"><span class="pre">delay()</span></code> call will
|
||||
actually execute <em>right away</em>. What you must do is to tell it which function to call <em>after the time
|
||||
has passed</em> (its “callback”). This may sound strange at first, but it is normal practice in
|
||||
asynchronous systems. You can also link such calls together as seen below:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">default_cmds</span><span class="p">,</span> <span class="n">utils</span>
|
||||
asynchronous systems. You can also link such calls together:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
|
||||
<span class="normal"> 2</span>
|
||||
<span class="normal"> 3</span>
|
||||
<span class="normal"> 4</span>
|
||||
<span class="normal"> 5</span>
|
||||
<span class="normal"> 6</span>
|
||||
<span class="normal"> 7</span>
|
||||
<span class="normal"> 8</span>
|
||||
<span class="normal"> 9</span>
|
||||
<span class="normal">10</span>
|
||||
<span class="normal">11</span>
|
||||
<span class="normal">12</span>
|
||||
<span class="normal">13</span>
|
||||
<span class="normal">14</span>
|
||||
<span class="normal">15</span>
|
||||
<span class="normal">16</span>
|
||||
<span class="normal">17</span>
|
||||
<span class="normal">18</span>
|
||||
<span class="normal">19</span>
|
||||
<span class="normal">20</span>
|
||||
<span class="normal">21</span>
|
||||
<span class="normal">22</span>
|
||||
<span class="normal">23</span>
|
||||
<span class="normal">24</span>
|
||||
<span class="normal">25</span>
|
||||
<span class="normal">26</span>
|
||||
<span class="normal">27</span>
|
||||
<span class="normal">28</span>
|
||||
<span class="normal">29</span>
|
||||
<span class="normal">30</span>
|
||||
<span class="normal">31</span>
|
||||
<span class="normal">32</span>
|
||||
<span class="normal">33</span>
|
||||
<span class="normal">34</span>
|
||||
<span class="normal">35</span>
|
||||
<span class="normal">36</span></pre></div></td><td class="code"><div><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">default_cmds</span><span class="p">,</span> <span class="n">utils</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">CmdEcho</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">MuxCommand</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
|
|
@ -245,56 +317,61 @@ asynchronous systems. You can also link such calls together as seen below:</p>
|
|||
<span class="sd"> Calls and waits for an echo</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"echo"</span>
|
||||
<span class="n">locks</span> <span class="o">=</span> <span class="s2">"cmd:all()"</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="s2">"This sets off a chain of delayed calls"</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="sa">f</span><span class="s2">"You shout '</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="si">}</span><span class="s2">', waiting for an echo ..."</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># wait 2 seconds before calling self.echo1</span>
|
||||
<span class="n">utils</span><span class="o">.</span><span class="n">delay</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">echo1</span><span class="p">)</span>
|
||||
|
||||
<span class="hll"> <span class="n">utils</span><span class="o">.</span><span class="n">delay</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">echo1</span><span class="p">)</span>
|
||||
</span>
|
||||
<span class="c1"># callback chain, started above</span>
|
||||
<span class="k">def</span> <span class="nf">echo1</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="s2">"First echo"</span>
|
||||
<span class="hll"> <span class="k">def</span> <span class="nf">echo1</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
</span> <span class="s2">"First echo"</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="sa">f</span><span class="s2">"... </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="c1"># wait 2 seconds for the next one</span>
|
||||
<span class="n">utils</span><span class="o">.</span><span class="n">delay</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">echo2</span><span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">echo2</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="s2">"Second echo"</span>
|
||||
<span class="hll"> <span class="k">def</span> <span class="nf">echo2</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
</span> <span class="s2">"Second echo"</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="sa">f</span><span class="s2">"... </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">capitalize</span><span class="p">()</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="c1"># wait another 2 seconds</span>
|
||||
<span class="n">utils</span><span class="o">.</span><span class="n">delay</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">callback</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">echo3</span><span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">echo3</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="s2">"Last echo"</span>
|
||||
<span class="hll"> <span class="k">def</span> <span class="nf">echo3</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
</span> <span class="s2">"Last echo"</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="sa">f</span><span class="s2">"... </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="si">}</span><span class="s2"> ..."</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</pre></div></td></tr></table></div>
|
||||
</div>
|
||||
<p>The above version will have the echoes arrive one after another, each separated by a two second
|
||||
delay.</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> echo Hello!
|
||||
<ul class="simple">
|
||||
<li><p><strong>Line 19</strong>: This sets off the chain, telling Evennia to wait 2 seconds before calling <code class="docutils literal notranslate"><span class="pre">self.echo1</span></code>.</p></li>
|
||||
<li><p><strong>Line 22</strong>: This is called after 2 seconds. It tells Evennia to wait another 2 seconds before calling <code class="docutils literal notranslate"><span class="pre">self.echo2</span></code>.</p></li>
|
||||
<li><p><strong>Line 28</strong>: This is called after yet another 2 seonds (4s total). It tells Evennia to wait another 2 seconds before calling, <code class="docutils literal notranslate"><span class="pre">self.echo3</span></code>.</p></li>
|
||||
<li><p><strong>Line34</strong> Called after another 2 seconds (6s total). This ends the delay-chain.</p></li>
|
||||
</ul>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>> echo Hello!
|
||||
... HELLO!
|
||||
... Hello!
|
||||
... hello! ...
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<p>What about time.sleep?</p>
|
||||
<p>You may be aware of the <code class="docutils literal notranslate"><span class="pre">time.sleep</span></code> function coming with Python. Doing `time.sleep(10) pauses Python for 10 seconds. <strong>Do not use this</strong>, it will not work with Evennia. If you use it, you will block the <em>entire server</em> (everyone!) for ten seconds!</p>
|
||||
<p>If you want specifics, <code class="docutils literal notranslate"><span class="pre">utils.delay</span></code> is a thin wrapper around a <a class="reference external" href="https://docs.twisted.org/en/twisted-22.1.0/core/howto/defer.html">Twisted Deferred</a>. This is an <a class="reference internal" href="../Concepts/Async-Process.html"><span class="doc std std-doc">asynchronous concept</span></a>.</p>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="blocking-commands">
|
||||
<h2>Blocking commands<a class="headerlink" href="#blocking-commands" title="Permalink to this headline">¶</a></h2>
|
||||
<p>As mentioned, a great thing about the delay introduced by <code class="docutils literal notranslate"><span class="pre">yield</span></code> or <code class="docutils literal notranslate"><span class="pre">utils.delay()</span></code> is that it does
|
||||
not block. It just goes on in the background and you are free to play normally in the interim. In
|
||||
some cases this is not what you want however. Some commands should simply “block” other commands
|
||||
while they are running. If you are in the process of crafting a helmet you shouldn’t be able to also
|
||||
start crafting a shield at the same time, or if you just did a huge power-swing with your weapon you
|
||||
should not be able to do it again immediately.</p>
|
||||
<p>The simplest way of implementing blocking is to use the technique covered in the <a class="reference internal" href="Howto-Command-Cooldown.html"><span class="doc std std-doc">Command Cooldown</span></a> tutorial. In that tutorial we implemented cooldowns by having the
|
||||
Command store the current time. Next time the Command was called, we compared the current time to
|
||||
the stored time to determine if enough time had passed for a renewed use. This is a <em>very</em>
|
||||
efficient, reliable and passive solution. The drawback is that there is nothing to tell the Player
|
||||
when enough time has passed unless they keep trying.</p>
|
||||
<section id="making-a-blocking-command">
|
||||
<h2>Making a blocking command<a class="headerlink" href="#making-a-blocking-command" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Both <code class="docutils literal notranslate"><span class="pre">yield</span></code> or <code class="docutils literal notranslate"><span class="pre">utils.delay()</span></code> pauses the command but allows the user to use other commands while the first one waits to finish.</p>
|
||||
<p>In some cases you want to instead have that command ‘block’ other commands from running. An example is crafting a helmet: most likely you should not be able to start crafting a shield at the same time. Or even walk out of the smithy.</p>
|
||||
<p>The simplest way of implementing blocking is to use the technique covered in the <a class="reference internal" href="Howto-Command-Cooldown.html"><span class="doc std std-doc">How to implement a Command Cooldown</span></a> tutorial. In that tutorial we cooldowns are implemented by comparing the current time with the last time the command was used. This is the best approach if you can get away with it. It could work well for our crafting example … <em>if</em> you don’t want to automatically update the player on their progress.</p>
|
||||
<p>In short:
|
||||
- If you are fine with the player making an active input to check their status, compare timestamps as done in the Command-cooldown tutorial. On-demand is by far the most efficent.
|
||||
- If you want Evennia to tell the user their status without them taking a further action, you need to use <code class="docutils literal notranslate"><span class="pre">yield</span></code> , <code class="docutils literal notranslate"><span class="pre">delay</span></code> (or some other active time-keeping method).</p>
|
||||
<p>Here is an example where we will use <code class="docutils literal notranslate"><span class="pre">utils.delay</span></code> to tell the player when the cooldown has passed:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">utils</span><span class="p">,</span> <span class="n">default_cmds</span>
|
||||
|
||||
|
|
@ -338,12 +415,10 @@ when enough time has passed unless they keep trying.</p>
|
|||
<p>Note how, after the cooldown, the user will get a message telling them they are now ready for
|
||||
another swing.</p>
|
||||
<p>By storing the <code class="docutils literal notranslate"><span class="pre">off_balance</span></code> flag on the character (rather than on, say, the Command instance
|
||||
itself) it can be accessed by other Commands too. Other attacks may also not work when you are off
|
||||
balance. You could also have an enemy Command check your <code class="docutils literal notranslate"><span class="pre">off_balance</span></code> status to gain bonuses, to
|
||||
take another example.</p>
|
||||
itself) it can be accessed by other Commands too. Other attacks may also not work when you are off balance. You could also have an enemy Command check your <code class="docutils literal notranslate"><span class="pre">off_balance</span></code> status to gain bonuses, to take another example.</p>
|
||||
</section>
|
||||
<section id="abortable-commands">
|
||||
<h2>Abortable commands<a class="headerlink" href="#abortable-commands" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="make-a-command-possible-to-abort">
|
||||
<h2>Make a Command possible to Abort<a class="headerlink" href="#make-a-command-possible-to-abort" title="Permalink to this headline">¶</a></h2>
|
||||
<p>One can imagine that you will want to abort a long-running command before it has a time to finish.
|
||||
If you are in the middle of crafting your armor you will probably want to stop doing that when a
|
||||
monster enters your smithy.</p>
|
||||
|
|
@ -443,60 +518,6 @@ Below is an example of a crafting command that can be aborted by starting a figh
|
|||
<code class="docutils literal notranslate"><span class="pre">attack</span></code> command is issued during this process it will set a flag that causes the crafting to be
|
||||
quietly canceled next time it tries to update.</p>
|
||||
</section>
|
||||
<section id="persistent-delays">
|
||||
<h2>Persistent delays<a class="headerlink" href="#persistent-delays" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In the latter examples above we used <code class="docutils literal notranslate"><span class="pre">.ndb</span></code> storage. This is fast and easy but it will reset all
|
||||
cooldowns/blocks/crafting etc if you reload the server. If you don’t want that you can replace
|
||||
<code class="docutils literal notranslate"><span class="pre">.ndb</span></code> with <code class="docutils literal notranslate"><span class="pre">.db</span></code>. But even this won’t help because the <code class="docutils literal notranslate"><span class="pre">yield</span></code> keyword is not persisent and nor is
|
||||
the use of <code class="docutils literal notranslate"><span class="pre">delay</span></code> shown above. To resolve this you can use <code class="docutils literal notranslate"><span class="pre">delay</span></code> with the <code class="docutils literal notranslate"><span class="pre">persistent=True</span></code>
|
||||
keyword. But wait! Making something persistent will add some extra complications, because now you
|
||||
must make sure Evennia can properly store things to the database.</p>
|
||||
<p>Here is the original echo-command reworked to function with persistence:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">default_cmds</span><span class="p">,</span> <span class="n">utils</span>
|
||||
|
||||
<span class="c1"># this is now in the outermost scope and takes two args! </span>
|
||||
<span class="k">def</span> <span class="nf">echo</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
|
||||
<span class="s2">"Called after 10 seconds."</span>
|
||||
<span class="n">shout</span> <span class="o">=</span> <span class="n">args</span>
|
||||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"You hear an echo: </span><span class="si">{</span><span class="n">shout</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span><span class="si">}</span><span class="s2"> ... </span><span class="si">{</span><span class="n">shout</span><span class="o">.</span><span class="n">capitalize</span><span class="p">()</span><span class="si">}</span><span class="s2"> ... </span><span class="si">{</span><span class="n">shout</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">CmdEcho</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">MuxCommand</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> wait for an echo</span>
|
||||
<span class="sd"> </span>
|
||||
<span class="sd"> Usage: </span>
|
||||
<span class="sd"> echo <string></span>
|
||||
<span class="sd"> </span>
|
||||
<span class="sd"> Calls and waits for an echo</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"echo"</span>
|
||||
<span class="n">locks</span> <span class="o">=</span> <span class="s2">"cmd:all()"</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="sd">"""</span>
|
||||
<span class="sd"> This is called at the initial shout. </span>
|
||||
<span class="sd"> """</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="sa">f</span><span class="s2">"You shout '</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="si">}</span><span class="s2">' and wait for an echo ..."</span><span class="p">)</span>
|
||||
<span class="c1"># this waits non-blocking for 10 seconds, then calls echo(self.caller, self.args)</span>
|
||||
<span class="n">utils</span><span class="o">.</span><span class="n">delay</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">echo</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="n">persistent</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="c1"># changes! </span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Above you notice two changes:</p>
|
||||
<ul class="simple">
|
||||
<li><p>The callback (<code class="docutils literal notranslate"><span class="pre">echo</span></code>) was moved out of the class and became its own stand-alone function in the
|
||||
outermost scope of the module. It also now takes <code class="docutils literal notranslate"><span class="pre">caller</span></code> and <code class="docutils literal notranslate"><span class="pre">args</span></code> as arguments (it doesn’t have
|
||||
access to them directly since this is now a stand-alone function).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">utils.delay</span></code> specifies the <code class="docutils literal notranslate"><span class="pre">echo</span></code> function (not <code class="docutils literal notranslate"><span class="pre">self.echo</span></code> - it’s no longer a method!) and sends
|
||||
<code class="docutils literal notranslate"><span class="pre">self.caller</span></code> and <code class="docutils literal notranslate"><span class="pre">self.args</span></code> as arguments for it to use. We also set <code class="docutils literal notranslate"><span class="pre">persistent=True</span></code>.</p></li>
|
||||
</ul>
|
||||
<p>The reason for this change is because Evennia needs to <code class="docutils literal notranslate"><span class="pre">pickle</span></code> the callback into storage and it
|
||||
cannot do this correctly when the method sits on the command class. Now this behave the same as the
|
||||
first version except if you reload (or even shut down) the server mid-delay it will still fire the
|
||||
callback when the server comes back up (it will resume the countdown and ignore the downtime).</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
|
|
@ -515,14 +536,14 @@ callback when the server comes back up (it will resume the countdown and ignore
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Howto-Default-Exit-Errors.html" title="Default Exit Errors"
|
||||
<a href="Howto-Default-Exit-Errors.html" title="Return custom errors on missing Exits"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Howto-Command-Cooldown.html" title="Command Cooldown"
|
||||
<a href="Howto-Command-Cooldown.html" title="Adding Command Cooldowns"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Command Duration</a></li>
|
||||
<li class="nav-item nav-item-this"><a href="">Commands that take time to finish</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Command Prompt — Evennia 1.0-dev documentation</title>
|
||||
<title>Adding a Command Prompt — 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>
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Command Cooldown" href="Howto-Command-Cooldown.html" />
|
||||
<link rel="next" title="Adding Command Cooldowns" href="Howto-Command-Cooldown.html" />
|
||||
<link rel="prev" title="2. Web Tutorial" href="Beginner-Tutorial/Part5/Web-Tutorial.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
|
|
@ -30,14 +30,14 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Howto-Command-Cooldown.html" title="Command Cooldown"
|
||||
<a href="Howto-Command-Cooldown.html" title="Adding Command Cooldowns"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Beginner-Tutorial/Part5/Web-Tutorial.html" title="2. Web Tutorial"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Command Prompt</a></li>
|
||||
<li class="nav-item nav-item-this"><a href="">Adding a Command Prompt</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
|
@ -62,9 +62,9 @@
|
|||
<script>$('#searchbox').show(0);</script>
|
||||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Command Prompt</a><ul>
|
||||
<li><a class="reference internal" href="#sending-a-prompt">Sending a prompt</a></li>
|
||||
<li><a class="reference internal" href="#a-prompt-sent-with-every-command">A prompt sent with every command</a><ul>
|
||||
<li><a class="reference internal" href="#">Adding a Command Prompt</a><ul>
|
||||
<li><a class="reference internal" href="#a-fixed-location-prompt">A fixed-location prompt</a></li>
|
||||
<li><a class="reference internal" href="#a-prompt-with-every-command">A prompt with every command</a><ul>
|
||||
<li><a class="reference internal" href="#modifying-default-commands">Modifying default commands</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
@ -77,7 +77,7 @@
|
|||
title="previous chapter"><span class="section-number">2. </span>Web Tutorial</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Howto-Command-Cooldown.html"
|
||||
title="next chapter">Command Cooldown</a></p>
|
||||
title="next chapter">Adding Command Cooldowns</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -108,22 +108,24 @@
|
|||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="command-prompt">
|
||||
<h1>Command Prompt<a class="headerlink" href="#command-prompt" title="Permalink to this headline">¶</a></h1>
|
||||
<p>A <em>prompt</em> is quite common in MUDs. The prompt display useful details about your character that you
|
||||
are likely to want to keep tabs on at all times, such as health, magical power etc. It might also
|
||||
show things like in-game time, weather and so on. Many modern MUD clients (including Evennia’s own
|
||||
webclient) allows for identifying the prompt and have it appear in a correct location (usually just
|
||||
above the input line). Usually it will remain like that until it is explicitly updated.</p>
|
||||
<section id="sending-a-prompt">
|
||||
<h2>Sending a prompt<a class="headerlink" href="#sending-a-prompt" title="Permalink to this headline">¶</a></h2>
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="adding-a-command-prompt">
|
||||
<h1>Adding a Command Prompt<a class="headerlink" href="#adding-a-command-prompt" title="Permalink to this headline">¶</a></h1>
|
||||
<p>A <em>prompt</em> is quite common in MUDs:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>HP: 5, MP: 2, SP: 8
|
||||
>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The prompt display useful details about your character that you are likely to want to keep tabs on at all times. It could be health, magical power, gold and current location. It might also show things like in-game time, weather and so on.</p>
|
||||
<p>Traditionally, the prompt (changed or not) was returned with every reply from the server and just displayed on its own line. Many modern MUD clients (including Evennia’s own webclient) allows for identifying the prompt and have it appear in a fixed location that gets updated in-place (usually just above the input line).</p>
|
||||
<section id="a-fixed-location-prompt">
|
||||
<h2>A fixed-location prompt<a class="headerlink" href="#a-fixed-location-prompt" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A prompt is sent using the <code class="docutils literal notranslate"><span class="pre">prompt</span></code> keyword to the <code class="docutils literal notranslate"><span class="pre">msg()</span></code> method on objects. The prompt will be
|
||||
sent without any line breaks.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">prompt</span><span class="o">=</span><span class="s2">"HP: 5, MP: 2, SP: 8"</span><span class="p">)</span>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">prompt</span><span class="o">=</span><span class="s2">"HP: 5, MP: 2, SP: 8"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>You can combine the sending of normal text with the sending (updating of the prompt):</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"This is a text"</span><span class="p">,</span> <span class="n">prompt</span><span class="o">=</span><span class="s2">"This is a prompt"</span><span class="p">)</span>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"This is a text"</span><span class="p">,</span> <span class="n">prompt</span><span class="o">=</span><span class="s2">"This is a prompt"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>You can update the prompt on demand, this is normally done using <a class="reference internal" href="../Concepts/OOB.html"><span class="doc std std-doc">OOB</span></a>-tracking of the relevant
|
||||
|
|
@ -167,17 +169,10 @@ the prompt when they cause a change in health, for example.</p>
|
|||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="a-prompt-sent-with-every-command">
|
||||
<h2>A prompt sent with every command<a class="headerlink" href="#a-prompt-sent-with-every-command" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The prompt sent as described above uses a standard telnet instruction (the Evennia web client gets a
|
||||
special flag). Most MUD telnet clients will understand and allow users to catch this and keep the
|
||||
prompt in place until it updates. So <em>in principle</em> you’d not need to update the prompt every
|
||||
command.</p>
|
||||
<p>However, with a varying user base it can be unclear which clients are used and which skill level the
|
||||
users have. So sending a prompt with every command is a safe catch-all. You don’t need to manually
|
||||
go in and edit every command you have though. Instead you edit the base command class for your
|
||||
custom commands (like <code class="docutils literal notranslate"><span class="pre">MuxCommand</span></code> in your <code class="docutils literal notranslate"><span class="pre">mygame/commands/command.py</span></code> folder) and overload the
|
||||
<code class="docutils literal notranslate"><span class="pre">at_post_cmd()</span></code> hook. This hook is always called <em>after</em> the main <code class="docutils literal notranslate"><span class="pre">func()</span></code> method of the Command.</p>
|
||||
<section id="a-prompt-with-every-command">
|
||||
<h2>A prompt with every command<a class="headerlink" href="#a-prompt-with-every-command" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The prompt sent as described above uses a standard telnet instruction (the Evennia web client gets a special flag). Most MUD telnet clients will understand and allow users to catch this and keep the prompt in place until it updates. So <em>in principle</em> you’d not need to update the prompt every command.</p>
|
||||
<p>However, with a varying user base it can be unclear which clients are used and which skill level the users have. So sending a prompt with every command is a safe catch-all. You don’t need to manually go in and edit every command you have though. Instead you edit the base command class for your custom commands (like <code class="docutils literal notranslate"><span class="pre">MuxCommand</span></code> in your <code class="docutils literal notranslate"><span class="pre">mygame/commands/command.py</span></code> folder) and overload the <code class="docutils literal notranslate"><span class="pre">at_post_cmd()</span></code> hook. This hook is always called <em>after</em> the main <code class="docutils literal notranslate"><span class="pre">func()</span></code> method of the Command.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">default_cmds</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">MuxCommand</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">MuxCommand</span><span class="p">):</span>
|
||||
|
|
@ -192,8 +187,7 @@ custom commands (like <code class="docutils literal notranslate"><span class="pr
|
|||
</div>
|
||||
<section id="modifying-default-commands">
|
||||
<h3>Modifying default commands<a class="headerlink" href="#modifying-default-commands" title="Permalink to this headline">¶</a></h3>
|
||||
<p>If you want to add something small like this to Evennia’s default commands without modifying them
|
||||
directly the easiest way is to just wrap those with a multiple inheritance to your own base class:</p>
|
||||
<p>If you want to add something small like this to Evennia’s default commands without modifying them directly the easiest way is to just wrap those with a multiple inheritance to your own base class:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in (for example) mygame/commands/mycommands.py</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">default_cmds</span>
|
||||
|
|
@ -240,14 +234,14 @@ directly the easiest way is to just wrap those with a multiple inheritance to yo
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Howto-Command-Cooldown.html" title="Command Cooldown"
|
||||
<a href="Howto-Command-Cooldown.html" title="Adding Command Cooldowns"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Beginner-Tutorial/Part5/Web-Tutorial.html" title="2. Web Tutorial"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Command Prompt</a></li>
|
||||
<li class="nav-item nav-item-this"><a href="">Adding a Command Prompt</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Default Exit Errors — Evennia 1.0-dev documentation</title>
|
||||
<title>Return custom errors on missing Exits — 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>
|
||||
|
|
@ -17,8 +17,8 @@
|
|||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Tutorial NPCs listening" href="Tutorial-NPCs-listening.html" />
|
||||
<link rel="prev" title="Command Duration" href="Howto-Command-Duration.html" />
|
||||
<link rel="next" title="Give objects weight" href="Howto-Add-Object-Weight.html" />
|
||||
<link rel="prev" title="Commands that take time to finish" href="Howto-Command-Duration.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -30,14 +30,14 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-NPCs-listening.html" title="Tutorial NPCs listening"
|
||||
<a href="Howto-Add-Object-Weight.html" title="Give objects weight"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Howto-Command-Duration.html" title="Command Duration"
|
||||
<a href="Howto-Command-Duration.html" title="Commands that take time to finish"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Default Exit Errors</a></li>
|
||||
<li class="nav-item nav-item-this"><a href="">Return custom errors on missing Exits</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
|
@ -62,8 +62,7 @@
|
|||
<script>$('#searchbox').show(0);</script>
|
||||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Default Exit Errors</a><ul>
|
||||
<li><a class="reference internal" href="#adding-default-error-commands">Adding default error commands</a></li>
|
||||
<li><a class="reference internal" href="#">Return custom errors on missing Exits</a><ul>
|
||||
<li><a class="reference internal" href="#why-not-a-single-command">Why not a single command?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
@ -71,10 +70,10 @@
|
|||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Howto-Command-Duration.html"
|
||||
title="previous chapter">Command Duration</a></p>
|
||||
title="previous chapter">Commands that take time to finish</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Tutorial-NPCs-listening.html"
|
||||
title="next chapter">Tutorial NPCs listening</a></p>
|
||||
<p class="topless"><a href="Howto-Add-Object-Weight.html"
|
||||
title="next chapter">Give objects weight</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -105,36 +104,34 @@
|
|||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="default-exit-errors">
|
||||
<h1>Default Exit Errors<a class="headerlink" href="#default-exit-errors" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Evennia allows for exits to have any name. The command “kitchen” is a valid exit name as well as “jump out the window”
|
||||
or “north”. An exit actually consists of two parts: an <a class="reference internal" href="../Components/Objects.html"><span class="doc std std-doc">Exit Object</span></a> and
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="return-custom-errors-on-missing-exits">
|
||||
<h1>Return custom errors on missing Exits<a class="headerlink" href="#return-custom-errors-on-missing-exits" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> north
|
||||
Ouch! You bump into a wall!
|
||||
> out
|
||||
But you are already outside ...?
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Evennia allows for exits to have any name. The command “kitchen” is a valid exit name as well as “jump out the window” or “north”. An exit actually consists of two parts: an <a class="reference internal" href="../Components/Objects.html"><span class="doc std std-doc">Exit Object</span></a> and
|
||||
an <a class="reference internal" href="../Components/Commands.html"><span class="doc std std-doc">Exit Command</span></a> stored on said exit object. The command has the same key and aliases as the
|
||||
exit-object, which is why you can see the exit in the room and just write its name to traverse it.</p>
|
||||
<p>So if you try to enter the name of a non-existing exit, Evennia treats is the same way as if you were trying to
|
||||
use a non-existing command:</p>
|
||||
<p>So if you try to enter the name of a non-existing exit, Evennia treats is the same way as if you were trying to use a non-existing command:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > jump out the window
|
||||
Command 'jump out the window' is not available. Type "help" for help.
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Many games don’t need this type of freedom however. They define only the cardinal directions as valid exit names (
|
||||
Evennia’s <code class="docutils literal notranslate"><span class="pre">tunnel</span></code> command also offers this functionality). In this case, the error starts to look less logical:</p>
|
||||
<p>Many games don’t need this type of freedom. They define only the cardinal directions as valid exit names ( Evennia’s <code class="docutils literal notranslate"><span class="pre">tunnel</span></code> command also offers this functionality). In this case, the error starts to look less logical:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > west
|
||||
Command 'west' is not available. Maybe you meant "set" or "reset"?
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Since we for our particular game <em>know</em> that west is an exit direction, it would be better if the error message just
|
||||
told us that we couldn’t go there.</p>
|
||||
<p>Since we for our particular game <em>know</em> that west is an exit direction, it would be better if the error message just told us that we couldn’t go there.</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > west
|
||||
You cannot move west.
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="adding-default-error-commands">
|
||||
<h2>Adding default error commands<a class="headerlink" href="#adding-default-error-commands" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The way to do this is to give Evennia an <em>alternative</em> Command to use when no Exit-Command is found
|
||||
in the room. See <a class="reference internal" href="Beginner-Tutorial/Part1/Beginner-Tutorial-Adding-Commands.html"><span class="doc std std-doc">Adding Commands</span></a> for more info about the
|
||||
process of adding new Commands to Evennia.</p>
|
||||
<p>In this example all we’ll do is echo an error message.</p>
|
||||
<p>The way to do this is to give Evennia an <em>alternative</em> Command to use when no Exit-Command is found in the room. See <a class="reference internal" href="Beginner-Tutorial/Part1/Beginner-Tutorial-Adding-Commands.html"><span class="doc std std-doc">Adding Commands</span></a> for more info about the process of adding new Commands to Evennia.</p>
|
||||
<p>In this example we will just echo an error message, but you could do everything (maybe you lose health if you bump into a wall?)</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># for example in a file mygame/commands/movecommands.py</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">default_cmds</span><span class="p">,</span> <span class="n">CmdSet</span>
|
||||
|
|
@ -177,9 +174,7 @@ process of adding new Commands to Evennia.</p>
|
|||
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">CmdExitErrorSouth</span><span class="p">())</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>We pack our commands in a new little cmdset; if we add this to our
|
||||
<code class="docutils literal notranslate"><span class="pre">CharacterCmdSet</span></code>, we can just add more errors to <code class="docutils literal notranslate"><span class="pre">MovementFailCmdSet</span></code>
|
||||
later without having to change code in two places.</p>
|
||||
<p>We pack our commands in a new little cmdset; if we add this to our <code class="docutils literal notranslate"><span class="pre">CharacterCmdSet</span></code>, we can just add more errors to <code class="docutils literal notranslate"><span class="pre">MovementFailCmdSet</span></code> later without having to change code in two places.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/commands/default_cmdsets.py</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">commands</span> <span class="kn">import</span> <span class="n">movecommands</span>
|
||||
|
|
@ -193,16 +188,12 @@ later without having to change code in two places.</p>
|
|||
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">movecommands</span><span class="o">.</span><span class="n">MovementFailCmdSet</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">reload</span></code> the server. What happens henceforth is that if you are in a room with an Exitobject (let’s say it’s “north”),
|
||||
the proper Exit-command will <em>overload</em> your error command (also named “north”). But if you enter a direction without
|
||||
having a matching exit for it, you will fall back to your default error commands:</p>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">reload</span></code> the server. What happens henceforth is that if you are in a room with an Exitobject (let’s say it’s “north”), the proper Exit-command will <em>overload</em> your error command (also named “north”). But if you enter a direction without having a matching exit for it, you will fall back to your default error commands:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > east
|
||||
You cannot move east.
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Further expansions by the exit system (including manipulating the way the Exit command itself is created) can be done by
|
||||
modifying the <a class="reference internal" href="../Components/Typeclasses.html"><span class="doc std std-doc">Exit typeclass</span></a> directly.</p>
|
||||
</section>
|
||||
<p>Further expansions by the exit system (including manipulating the way the Exit command itself is created) can be done by modifying the <a class="reference internal" href="../Components/Typeclasses.html"><span class="doc std std-doc">Exit typeclass</span></a> directly.</p>
|
||||
<section id="why-not-a-single-command">
|
||||
<h2>Why not a single command?<a class="headerlink" href="#why-not-a-single-command" title="Permalink to this headline">¶</a></h2>
|
||||
<p>So why didn’t we create a single error command above? Something like this:</p>
|
||||
|
|
@ -216,14 +207,9 @@ modifying the <a class="reference internal" href="../Components/Typeclasses.html
|
|||
<span class="c1">#[...]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The reason is that this would <em>not</em> work. Understanding why is important.</p>
|
||||
<p>Evennia’s <a class="reference internal" href="../Components/Commands.html"><span class="doc std std-doc">command system</span></a> compares commands by key and/or aliases. If <em>any</em> key or alias
|
||||
match, the two commands are considered <em>identical</em>. When the cmdsets merge, priority will then decide which of these
|
||||
‘identical’ commandss replace which.</p>
|
||||
<p>So the above example would work fine as long as there were <em>no Exits at all</em> in the room. But when we enter
|
||||
a room with an exit “north”, its Exit-command (which has a higher priority) will override the single <code class="docutils literal notranslate"><span class="pre">CmdExitError</span></code>
|
||||
with its alias ‘north’. So the <code class="docutils literal notranslate"><span class="pre">CmdExitError</span></code> will be gone and while “north” will work, we’ll again get the normal
|
||||
“Command not recognized” error for the other directions.</p>
|
||||
<p>This would <em>not</em> work the way we want. Understanding why is important.</p>
|
||||
<p>Evennia’s <a class="reference internal" href="../Components/Commands.html"><span class="doc std std-doc">command system</span></a> compares commands by key and/or aliases. If <em>any</em> key or alias match, the two commands are considered <em>identical</em>. When the cmdsets merge, priority will then decide which of these ‘identical’ commandss replace which.</p>
|
||||
<p>So the above example would work fine as long as there were <em>no Exits at all</em> in the room. But when we enter a room with an exit “north”, its Exit-command (which has a higher priority) will override the single <code class="docutils literal notranslate"><span class="pre">CmdExitError</span></code> with its alias ‘north’. So the <code class="docutils literal notranslate"><span class="pre">CmdExitError</span></code> will be gone and while “north” will work, we’ll again get the normal “Command not recognized” error for the other directions.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
|
@ -243,14 +229,14 @@ with its alias ‘north’. So the <code class="docutils literal notranslate"><s
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-NPCs-listening.html" title="Tutorial NPCs listening"
|
||||
<a href="Howto-Add-Object-Weight.html" title="Give objects weight"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Howto-Command-Duration.html" title="Command Duration"
|
||||
<a href="Howto-Command-Duration.html" title="Commands that take time to finish"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Default Exit Errors</a></li>
|
||||
<li class="nav-item nav-item-this"><a href="">Return custom errors on missing Exits</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -116,8 +116,7 @@
|
|||
<section id="beginner-tutorial">
|
||||
<h2>Beginner Tutorial<a class="headerlink" href="#beginner-tutorial" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Recommended starting point! This will take you from absolute beginner to making
|
||||
a small, but full, game with Evennia. Even if you have a very different game style
|
||||
in mind for your own game, this will give you a good start.</p>
|
||||
a small but full game with Evennia. Other tutorials and howto’s tend to assume you are already familiar with the concepts explained in the Beginning tutorial.</p>
|
||||
<blockquote>
|
||||
<div><p>The latter parts of the beginner tutorial are still being worked on.</p>
|
||||
</div></blockquote>
|
||||
|
|
@ -201,10 +200,31 @@ in mind for your own game, this will give you a good start.</p>
|
|||
<h2>Howto’s<a class="headerlink" href="#howtos" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="toctree-wrapper compound">
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Howto-Command-Prompt.html">Command Prompt</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Howto-Command-Cooldown.html">Command Cooldown</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Howto-Command-Duration.html">Command Duration</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Howto-Default-Exit-Errors.html">Default Exit Errors</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Howto-Command-Prompt.html">Adding a Command Prompt</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Howto-Command-Prompt.html#a-fixed-location-prompt">A fixed-location prompt</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Howto-Command-Prompt.html#a-prompt-with-every-command">A prompt with every command</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Howto-Command-Cooldown.html">Adding Command Cooldowns</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Howto-Command-Cooldown.html#an-efficient-cooldown">An efficient cooldown</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Howto-Command-Cooldown.html#make-a-cooldown-aware-command-parent">Make a cooldown-aware command parent</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Howto-Command-Duration.html">Commands that take time to finish</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Howto-Command-Duration.html#pause-commands-with-yield">Pause commands with <code class="docutils literal notranslate"><span class="pre">yield</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Howto-Command-Duration.html#pause-commands-with-utils-delay">Pause commands with <code class="docutils literal notranslate"><span class="pre">utils.delay</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Howto-Command-Duration.html#making-a-blocking-command">Making a blocking command</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Howto-Command-Duration.html#make-a-command-possible-to-abort">Make a Command possible to Abort</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Howto-Default-Exit-Errors.html">Return custom errors on missing Exits</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Howto-Default-Exit-Errors.html#why-not-a-single-command">Why not a single command?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Howto-Add-Object-Weight.html">Give objects weight</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Howto-Add-Object-Weight.html#limit-inventory-by-weight-carried">Limit inventory by weight carried</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -212,9 +232,9 @@ in mind for your own game, this will give you a good start.</p>
|
|||
<h2>Mobs and NPCs<a class="headerlink" href="#mobs-and-npcs" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="toctree-wrapper compound">
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Tutorial-NPCs-listening.html">Tutorial NPCs listening</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Tutorial-Aggressive-NPCs.html">Tutorial Aggressive NPCs</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="NPC-shop-Tutorial.html">NPC shop Tutorial</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Tutorial-NPC-Listening.html">NPCs that listen to what is said</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Tutorial-NPC-Reacting.html">NPCs reacting to your presence</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Tutorial-NPC-Merchants.html">NPC merchants</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -233,13 +253,11 @@ in mind for your own game, this will give you a good start.</p>
|
|||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Tutorial-Persistent-Handler.html">Making a Persistent object Handler</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Gametime-Tutorial.html">Gametime Tutorial</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Mass-and-weight-for-objects.html">Mass and weight for objects</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Weather-Tutorial.html">Weather Tutorial</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Tutorial-Coordinates.html">Coordinates</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Tutorial-Coordinates.html#adding-room-coordinates-in-your-game">Adding room coordinates in your game</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Dynamic-In-Game-Map.html">Dynamic In Game Map</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Static-In-Game-Map.html">Static In Game Map</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Arxcode-Installation.html">Arxcode installing help</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Tutorial-Tweeting-Game-Stats.html">Tutorial Tweeting Game Stats</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -264,6 +282,7 @@ in mind for your own game, this will give you a good start.</p>
|
|||
<li class="toctree-l1"><a class="reference internal" href="Evennia-for-roleplaying-sessions.html">Evennia for roleplaying sessions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Evennia-for-Diku-Users.html">Evennia for Diku Users</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Evennia-for-MUSH-Users.html">Evennia for MUSH Users</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Arxcode-Installation.html">Arxcode installing help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Turn based Combat System" href="Turn-based-Combat-System.html" />
|
||||
<link rel="prev" title="Evennia for MUSH Users" href="Evennia-for-MUSH-Users.html" />
|
||||
<link rel="prev" title="Arxcode installing help" href="Arxcode-Installation.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
<a href="Turn-based-Combat-System.html" title="Turn based Combat System"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Evennia-for-MUSH-Users.html" title="Evennia for MUSH Users"
|
||||
<a href="Arxcode-Installation.html" title="Arxcode installing help"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howto’s</a> »</li>
|
||||
|
|
@ -75,8 +75,8 @@
|
|||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Evennia-for-MUSH-Users.html"
|
||||
title="previous chapter">Evennia for MUSH Users</a></p>
|
||||
<p class="topless"><a href="Arxcode-Installation.html"
|
||||
title="previous chapter">Arxcode installing help</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Turn-based-Combat-System.html"
|
||||
title="next chapter">Turn based Combat System</a></p>
|
||||
|
|
@ -390,7 +390,7 @@ your <code class="docutils literal notranslate"><span class="pre">rules</span></
|
|||
<a href="Turn-based-Combat-System.html" title="Turn based Combat System"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Evennia-for-MUSH-Users.html" title="Evennia for MUSH Users"
|
||||
<a href="Arxcode-Installation.html" title="Arxcode installing help"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||||
|
|
|
|||
|
|
@ -1,231 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Mass and weight for objects — Evennia 1.0-dev documentation</title>
|
||||
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<script src="../_static/language_data.js"></script>
|
||||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Weather Tutorial" href="Weather-Tutorial.html" />
|
||||
<link rel="prev" title="Gametime Tutorial" href="Gametime-Tutorial.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="../genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Weather-Tutorial.html" title="Weather Tutorial"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Gametime-Tutorial.html" title="Gametime Tutorial"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Mass and weight for objects</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
|
||||
<div class="documentwrapper">
|
||||
<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>
|
||||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Mass and weight for objects</a><ul>
|
||||
<li><a class="reference internal" href="#objects">Objects</a></li>
|
||||
<li><a class="reference internal" href="#characters-and-rooms">Characters and rooms</a></li>
|
||||
<li><a class="reference internal" href="#inventory">Inventory</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Gametime-Tutorial.html"
|
||||
title="previous chapter">Gametime Tutorial</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Weather-Tutorial.html"
|
||||
title="next chapter">Weather Tutorial</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Howtos/Mass-and-weight-for-objects.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div><h3>Links</h3>
|
||||
<ul>
|
||||
<li><a href="https://www.evennia.com">Home page</a> </li>
|
||||
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
|
||||
<li><a href="http://games.evennia.com">Game Index</a> </li>
|
||||
<li>
|
||||
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
|
||||
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
|
||||
<a href="https://evennia.blogspot.com/">Blog</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Mass-and-weight-for-objects.html">1.0-dev (develop branch)</a></li>
|
||||
<ul>
|
||||
<li><a href="../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="mass-and-weight-for-objects">
|
||||
<h1>Mass and weight for objects<a class="headerlink" href="#mass-and-weight-for-objects" title="Permalink to this headline">¶</a></h1>
|
||||
<p>An easy addition to add dynamic variety to your world objects is to give them some mass. Why mass
|
||||
and not weight? Weight varies in setting; for example things on the Moon weigh 1/6 as much. On
|
||||
Earth’s surface and in most environments, no relative weight factor is needed.</p>
|
||||
<p>In most settings, mass can be used as weight to spring a pressure plate trap or a floor giving way,
|
||||
determine a character’s burden weight for travel speed… The total mass of an object can
|
||||
contribute to the force of a weapon swing, or a speeding meteor to give it a potential striking
|
||||
force.</p>
|
||||
<section id="objects">
|
||||
<h2>Objects<a class="headerlink" href="#objects" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Now that we have reasons for keeping track of object mass, let’s look at the default object class
|
||||
inside your mygame/typeclasses/objects.py and see how easy it is to total up mass from an object and
|
||||
its contents.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># inside your mygame/typeclasses/objects.py</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">Object</span><span class="p">(</span><span class="n">DefaultObject</span><span class="p">):</span>
|
||||
<span class="c1"># [...]</span>
|
||||
<span class="k">def</span> <span class="nf">get_mass</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="n">mass</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'mass'</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="c1"># Default objects have 1 unit mass.</span>
|
||||
<span class="k">return</span> <span class="n">mass</span> <span class="o">+</span> <span class="nb">sum</span><span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">get_mass</span><span class="p">()</span> <span class="k">for</span> <span class="n">obj</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Adding the <code class="docutils literal notranslate"><span class="pre">get_mass</span></code> definition to the objects you want to sum up the masses for is done with
|
||||
Python’s “sum” function which operates on all the contents, in this case by summing them to
|
||||
return a total mass value.</p>
|
||||
<p>If you only wanted specific object types to have mass or have the new object type in a different
|
||||
module, see [[Adding-Object-Typeclass-Tutorial]] with its Heavy class object. You could set the
|
||||
default for Heavy types to something much larger than 1 gram or whatever unit you want to use. Any
|
||||
non-default mass would be stored on the <code class="docutils literal notranslate"><span class="pre">mass</span></code> [[Attributes]] of the objects.</p>
|
||||
</section>
|
||||
<section id="characters-and-rooms">
|
||||
<h2>Characters and rooms<a class="headerlink" href="#characters-and-rooms" title="Permalink to this headline">¶</a></h2>
|
||||
<p>You can add a <code class="docutils literal notranslate"><span class="pre">get_mass</span></code> definition to characters and rooms, also.</p>
|
||||
<p>If you were in a one metric-ton elevator with four other friends also wearing armor and carrying
|
||||
gold bricks, you might wonder if this elevator’s going to move, and how fast.</p>
|
||||
<p>Assuming the unit is grams and the elevator itself weights 1,000 kilograms, it would already be
|
||||
<code class="docutils literal notranslate"><span class="pre">@set</span> <span class="pre">elevator/mass=1000000</span></code>, we’re <code class="docutils literal notranslate"><span class="pre">@set</span> <span class="pre">me/mass=85000</span></code> and our armor is <code class="docutils literal notranslate"><span class="pre">@set</span> <span class="pre">armor/mass=50000</span></code>.
|
||||
We’re each carrying 20 gold bars each <code class="docutils literal notranslate"><span class="pre">@set</span> <span class="pre">gold</span> <span class="pre">bar/mass=12400</span></code> then step into the elevator and see
|
||||
the following message in the elevator’s appearance: <code class="docutils literal notranslate"><span class="pre">Elevator</span> <span class="pre">weight</span> <span class="pre">and</span> <span class="pre">contents</span> <span class="pre">should</span> <span class="pre">not</span> <span class="pre">exceed</span> <span class="pre">3</span> <span class="pre">metric</span> <span class="pre">tons.</span></code> Are we safe? Maybe not if you consider dynamic loading. But at rest:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># Elevator object knows when it checks itself:</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_mass</span><span class="p">()</span> <span class="o"><</span> <span class="mi">3000000</span><span class="p">:</span>
|
||||
<span class="k">pass</span> <span class="c1"># Elevator functions as normal.</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="k">pass</span> <span class="c1"># Danger! Alarm sounds, cable snaps, elevator stops...</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="inventory">
|
||||
<h2>Inventory<a class="headerlink" href="#inventory" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Example of listing mass of items in your inventory:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">CmdInventory</span><span class="p">(</span><span class="n">MuxCommand</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> view inventory</span>
|
||||
<span class="sd"> Usage:</span>
|
||||
<span class="sd"> inventory</span>
|
||||
<span class="sd"> inv</span>
|
||||
<span class="sd"> Switches:</span>
|
||||
<span class="sd"> /weight to display all available channels.</span>
|
||||
<span class="sd"> Shows your inventory: carrying, wielding, wearing, obscuring.</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"inventory"</span>
|
||||
<span class="n">aliases</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"inv"</span><span class="p">,</span> <span class="s2">"i"</span><span class="p">]</span>
|
||||
<span class="n">locks</span> <span class="o">=</span> <span class="s2">"cmd:all()"</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="s2">"check inventory"</span>
|
||||
<span class="n">items</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">contents</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">items</span><span class="p">:</span>
|
||||
<span class="n">string</span> <span class="o">=</span> <span class="s2">"You are not carrying anything."</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">table</span> <span class="o">=</span> <span class="n">prettytable</span><span class="o">.</span><span class="n">PrettyTable</span><span class="p">([</span><span class="s2">"name"</span><span class="p">,</span> <span class="s2">"desc"</span><span class="p">])</span>
|
||||
<span class="n">table</span><span class="o">.</span><span class="n">header</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
<span class="n">table</span><span class="o">.</span><span class="n">border</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">items</span><span class="p">:</span>
|
||||
<span class="n">second</span> <span class="o">=</span> <span class="n">item</span><span class="o">.</span><span class="n">get_mass</span><span class="p">()</span> \
|
||||
<span class="k">if</span> <span class="s2">"weight"</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">switches</span> <span class="k">else</span> <span class="n">item</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">desc</span>
|
||||
<span class="n">table</span><span class="o">.</span><span class="n">add_row</span><span class="p">([</span>
|
||||
<span class="nb">str</span><span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">get_display_name</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">sessions</span><span class="p">)),</span>
|
||||
<span class="n">second</span> <span class="ow">and</span> <span class="n">second</span> <span class="ow">or</span> <span class="s2">""</span><span class="p">,</span>
|
||||
<span class="p">])</span>
|
||||
<span class="n">string</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"|wYou are carrying:</span><span class="se">\n</span><span class="si">{</span><span class="n">table</span><span class="si">}</span><span class="s2">"</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">string</span><span class="p">)</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="../genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Weather-Tutorial.html" title="Weather Tutorial"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Gametime-Tutorial.html" title="Gametime Tutorial"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Mass and weight for objects</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2022, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,465 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>NPC shop Tutorial — Evennia 1.0-dev documentation</title>
|
||||
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<script src="../_static/language_data.js"></script>
|
||||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Building a mech tutorial" href="Building-a-mech-tutorial.html" />
|
||||
<link rel="prev" title="Tutorial Aggressive NPCs" href="Tutorial-Aggressive-NPCs.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="../genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Building-a-mech-tutorial.html" title="Building a mech tutorial"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-Aggressive-NPCs.html" title="Tutorial Aggressive NPCs"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">NPC shop Tutorial</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
|
||||
<div class="documentwrapper">
|
||||
<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>
|
||||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">NPC shop Tutorial</a><ul>
|
||||
<li><a class="reference internal" href="#the-shop-menu">The shop menu</a><ul>
|
||||
<li><a class="reference internal" href="#designing-the-menu">Designing the menu</a></li>
|
||||
<li><a class="reference internal" href="#coding-the-menu">Coding the menu</a></li>
|
||||
<li><a class="reference internal" href="#the-command-to-start-the-menu">The command to start the menu</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#building-the-shop">Building the shop</a></li>
|
||||
<li><a class="reference internal" href="#the-shop-is-open-for-business">The shop is open for business!</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Tutorial-Aggressive-NPCs.html"
|
||||
title="previous chapter">Tutorial Aggressive NPCs</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Building-a-mech-tutorial.html"
|
||||
title="next chapter">Building a mech tutorial</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Howtos/NPC-shop-Tutorial.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div><h3>Links</h3>
|
||||
<ul>
|
||||
<li><a href="https://www.evennia.com">Home page</a> </li>
|
||||
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
|
||||
<li><a href="http://games.evennia.com">Game Index</a> </li>
|
||||
<li>
|
||||
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
|
||||
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
|
||||
<a href="https://evennia.blogspot.com/">Blog</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="NPC-shop-Tutorial.html">1.0-dev (develop branch)</a></li>
|
||||
<ul>
|
||||
<li><a href="../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="npc-shop-tutorial">
|
||||
<h1>NPC shop Tutorial<a class="headerlink" href="#npc-shop-tutorial" title="Permalink to this headline">¶</a></h1>
|
||||
<p>This tutorial will describe how to make an NPC-run shop. We will make use of the <a class="reference internal" href="../Components/EvMenu.html"><span class="doc std std-doc">EvMenu</span></a>
|
||||
system to present shoppers with a menu where they can buy things from the store’s stock.</p>
|
||||
<p>Our shop extends over two rooms - a “front” room open to the shop’s customers and a locked “store
|
||||
room” holding the wares the shop should be able to sell. We aim for the following features:</p>
|
||||
<ul class="simple">
|
||||
<li><p>The front room should have an Attribute <code class="docutils literal notranslate"><span class="pre">storeroom</span></code> that points to the store room.</p></li>
|
||||
<li><p>Inside the front room, the customer should have a command <code class="docutils literal notranslate"><span class="pre">buy</span></code> or <code class="docutils literal notranslate"><span class="pre">browse</span></code>. This will open a
|
||||
menu listing all items available to buy from the store room.</p></li>
|
||||
<li><p>A customer should be able to look at individual items before buying.</p></li>
|
||||
<li><p>We use “gold” as an example currency. To determine cost, the system will look for an Attribute
|
||||
<code class="docutils literal notranslate"><span class="pre">gold_value</span></code> on the items in the store room. If not found, a fixed base value of 1 will be assumed.
|
||||
The wealth of the customer should be set as an Attribute <code class="docutils literal notranslate"><span class="pre">gold</span></code> on the Character. If not set, they
|
||||
have no gold and can’t buy anything.</p></li>
|
||||
<li><p>When the customer makes a purchase, the system will check the <code class="docutils literal notranslate"><span class="pre">gold_value</span></code> of the goods and
|
||||
compare it to the <code class="docutils literal notranslate"><span class="pre">gold</span></code> Attribute of the customer. If enough gold is available, this will be
|
||||
deducted and the goods transferred from the store room to the inventory of the customer.</p></li>
|
||||
<li><p>We will lock the store room so that only people with the right key can get in there.</p></li>
|
||||
</ul>
|
||||
<section id="the-shop-menu">
|
||||
<h2>The shop menu<a class="headerlink" href="#the-shop-menu" title="Permalink to this headline">¶</a></h2>
|
||||
<p>We want to show a menu to the customer where they can list, examine and buy items in the store. This
|
||||
menu should change depending on what is currently for sale. Evennia’s <em>EvMenu</em> utility will manage
|
||||
the menu for us. It’s a good idea to <a class="reference internal" href="../Components/EvMenu.html"><span class="doc std std-doc">read up on EvMenu</span></a> if you are not familiar with it.</p>
|
||||
<section id="designing-the-menu">
|
||||
<h3>Designing the menu<a class="headerlink" href="#designing-the-menu" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The shopping menu’s design is straightforward. First we want the main screen. You get this when you
|
||||
enter a shop and use the <code class="docutils literal notranslate"><span class="pre">browse</span></code> or <code class="docutils literal notranslate"><span class="pre">buy</span></code> command:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>*** Welcome to ye Old Sword shop! ***
|
||||
Things for sale (choose 1-3 to inspect, quit to exit):
|
||||
_________________________________________________________
|
||||
1. A rusty sword (5 gold)
|
||||
2. A sword with a leather handle (10 gold)
|
||||
3. Excalibur (100 gold)
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>There are only three items to buy in this example but the menu should expand to however many items
|
||||
are needed. When you make a selection you will get a new screen showing the options for that
|
||||
particular item:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">You</span> <span class="n">inspect</span> <span class="n">A</span> <span class="n">rusty</span> <span class="n">sword</span><span class="p">:</span>
|
||||
|
||||
<span class="n">This</span> <span class="ow">is</span> <span class="n">an</span> <span class="n">old</span> <span class="n">weapon</span> <span class="n">maybe</span> <span class="n">once</span> <span class="n">used</span> <span class="n">by</span> <span class="n">soldiers</span> <span class="ow">in</span> <span class="n">some</span>
|
||||
<span class="n">long</span> <span class="n">forgotten</span> <span class="n">army</span><span class="o">.</span> <span class="n">It</span> <span class="ow">is</span> <span class="n">rusty</span> <span class="ow">and</span> <span class="ow">in</span> <span class="n">bad</span> <span class="n">condition</span><span class="o">.</span>
|
||||
<span class="n">__________________________________________________________</span>
|
||||
<span class="mf">1.</span> <span class="n">Buy</span> <span class="n">A</span> <span class="n">rusty</span> <span class="n">sword</span> <span class="p">(</span><span class="mi">5</span> <span class="n">gold</span><span class="p">)</span>
|
||||
<span class="mf">2.</span> <span class="n">Look</span> <span class="k">for</span> <span class="n">something</span> <span class="k">else</span><span class="o">.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Finally, when you buy something, a brief message should pop up:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>You pay 5 gold and purchase A rusty sword!
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>or</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>You cannot afford 5 gold for A rusty sword!
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>After this you should be back to the top level of the shopping menu again and can continue browsing.</p>
|
||||
</section>
|
||||
<section id="coding-the-menu">
|
||||
<h3>Coding the menu<a class="headerlink" href="#coding-the-menu" title="Permalink to this headline">¶</a></h3>
|
||||
<p>EvMenu defines the <em>nodes</em> (each menu screen with options) as normal Python functions. Each node
|
||||
must be able to change on the fly depending on what items are currently for sale. EvMenu will
|
||||
automatically make the <code class="docutils literal notranslate"><span class="pre">quit</span></code> command available to us so we won’t add that manually. For compactness
|
||||
we will put everything needed for our shop in one module, <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/npcshop.py</span></code>.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/typeclasses/npcshop.py</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">evmenu</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">menunode_shopfront</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||||
<span class="s2">"This is the top-menu screen."</span>
|
||||
|
||||
<span class="n">shopname</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">location</span><span class="o">.</span><span class="n">key</span>
|
||||
<span class="n">wares</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">location</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">storeroom</span><span class="o">.</span><span class="n">contents</span>
|
||||
|
||||
<span class="c1"># Wares includes all items inside the storeroom, including the</span>
|
||||
<span class="c1"># door! Let's remove that from our for sale list.</span>
|
||||
<span class="n">wares</span> <span class="o">=</span> <span class="p">[</span><span class="n">ware</span> <span class="k">for</span> <span class="n">ware</span> <span class="ow">in</span> <span class="n">wares</span> <span class="k">if</span> <span class="n">ware</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">!=</span> <span class="s2">"door"</span><span class="p">]</span>
|
||||
|
||||
<span class="n">text</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"*** Welcome to </span><span class="si">{</span><span class="n">shopname</span><span class="si">}</span><span class="s2">! ***</span><span class="se">\n</span><span class="s2">"</span>
|
||||
<span class="k">if</span> <span class="n">wares</span><span class="p">:</span>
|
||||
<span class="n">text</span> <span class="o">+=</span> <span class="sa">f</span><span class="s2">" Things for sale (choose 1-</span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">wares</span><span class="p">)</span><span class="si">}</span><span class="s2"> to inspect); quit to exit:"</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">text</span> <span class="o">+=</span> <span class="s2">" There is nothing for sale; quit to exit."</span>
|
||||
|
||||
<span class="n">options</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="n">ware</span> <span class="ow">in</span> <span class="n">wares</span><span class="p">:</span>
|
||||
<span class="c1"># add an option for every ware in store</span>
|
||||
<span class="n">gold_val</span> <span class="o">=</span> <span class="n">ware</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">gold_value</span> <span class="ow">or</span> <span class="mi">1</span>
|
||||
<span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">"desc"</span><span class="p">:</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">ware</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> (</span><span class="si">{</span><span class="n">gold_val</span><span class="si">}</span><span class="s2"> gold)"</span><span class="p">,</span>
|
||||
<span class="s2">"goto"</span><span class="p">:</span> <span class="s2">"menunode_inspect_and_buy"</span><span class="p">})</span>
|
||||
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>In this code we assume the caller to be <em>inside</em> the shop when accessing the menu. This means we can
|
||||
access the shop room via <code class="docutils literal notranslate"><span class="pre">caller.location</span></code> and get its <code class="docutils literal notranslate"><span class="pre">key</span></code> to display as the shop’s name. We also
|
||||
assume the shop has an Attribute <code class="docutils literal notranslate"><span class="pre">storeroom</span></code> we can use to get to our stock. We loop over our goods
|
||||
to build up the menu’s options.</p>
|
||||
<p>Note that <em>all options point to the same menu node</em> called <code class="docutils literal notranslate"><span class="pre">menunode_inspect_and_buy</span></code>! We can’t know
|
||||
which goods will be available to sale so we rely on this node to modify itself depending on the
|
||||
circumstances. Let’s create it now.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># further down in mygame/typeclasses/npcshop.py</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">menunode_inspect_and_buy</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="s2">"Sets up the buy menu screen."</span>
|
||||
|
||||
<span class="n">wares</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">location</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">storeroom</span><span class="o">.</span><span class="n">contents</span>
|
||||
<span class="c1"># Don't forget, we will need to remove that pesky door again!</span>
|
||||
<span class="n">wares</span> <span class="o">=</span> <span class="p">[</span><span class="n">ware</span> <span class="k">for</span> <span class="n">ware</span> <span class="ow">in</span> <span class="n">wares</span> <span class="k">if</span> <span class="n">ware</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">!=</span> <span class="s2">"door"</span><span class="p">]</span>
|
||||
<span class="n">iware</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">raw_string</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="n">ware</span> <span class="o">=</span> <span class="n">wares</span><span class="p">[</span><span class="n">iware</span><span class="p">]</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="n">ware</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">gold_value</span> <span class="ow">or</span> <span class="mi">1</span>
|
||||
<span class="n">wealth</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">gold</span> <span class="ow">or</span> <span class="mi">0</span>
|
||||
<span class="n">text</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"You inspect </span><span class="si">{</span><span class="n">ware</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2">:</span><span class="se">\n\n</span><span class="si">{</span><span class="n">ware</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">desc</span><span class="si">}</span><span class="s2">"</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">buy_ware_result</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||||
<span class="s2">"This will be executed first when choosing to buy."</span>
|
||||
<span class="k">if</span> <span class="n">wealth</span> <span class="o">>=</span> <span class="n">value</span><span class="p">:</span>
|
||||
<span class="n">rtext</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"You pay </span><span class="si">{</span><span class="n">value</span><span class="si">}</span><span class="s2"> gold and purchase </span><span class="si">{</span><span class="n">ware</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2">!"</span>
|
||||
<span class="n">caller</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">gold</span> <span class="o">-=</span> <span class="n">value</span>
|
||||
<span class="n">ware</span><span class="o">.</span><span class="n">move_to</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">quiet</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">move_type</span><span class="o">=</span><span class="s2">"buy"</span><span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">rtext</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"You cannot afford </span><span class="si">{</span><span class="n">value</span><span class="si">}</span><span class="s2"> gold for </span><span class="si">{</span><span class="n">ware</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2">!"</span>
|
||||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">rtext</span><span class="p">)</span>
|
||||
|
||||
<span class="n">gold_val</span> <span class="o">=</span> <span class="n">ware</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">gold_value</span> <span class="ow">or</span> <span class="mi">1</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="sa">f</span><span class="s2">"Buy </span><span class="si">{</span><span class="n">ware</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> for </span><span class="si">{</span><span class="n">gold_val</span><span class="si">}</span><span class="s2"> gold"</span><span class="p">,</span>
|
||||
<span class="s2">"goto"</span><span class="p">:</span> <span class="s2">"menunode_shopfront"</span><span class="p">,</span>
|
||||
<span class="s2">"exec"</span><span class="p">:</span> <span class="n">buy_ware_result</span><span class="p">,</span>
|
||||
<span class="p">},</span> <span class="p">{</span>
|
||||
<span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"Look for something else"</span><span class="p">,</span>
|
||||
<span class="s2">"goto"</span><span class="p">:</span> <span class="s2">"menunode_shopfront"</span><span class="p">,</span>
|
||||
<span class="p">})</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>In this menu node we make use of the <code class="docutils literal notranslate"><span class="pre">raw_string</span></code> argument to the node. This is the text the menu
|
||||
user entered on the <em>previous</em> node to get here. Since we only allow numbered options in our menu,
|
||||
<code class="docutils literal notranslate"><span class="pre">raw_input</span></code> must be an number for the player to get to this point. So we convert it to an integer
|
||||
index (menu lists start from 1, whereas Python indices always starts at 0, so we need to subtract
|
||||
1). We then use the index to get the corresponding item from storage.</p>
|
||||
<p>We just show the customer the <code class="docutils literal notranslate"><span class="pre">desc</span></code> of the item. In a more elaborate setup you might want to show
|
||||
things like weapon damage and special stats here as well.</p>
|
||||
<p>When the user choose the “buy” option, EvMenu will execute the <code class="docutils literal notranslate"><span class="pre">exec</span></code> instruction <em>before</em> we go
|
||||
back to the top node (the <code class="docutils literal notranslate"><span class="pre">goto</span></code> instruction). For this we make a little inline function
|
||||
<code class="docutils literal notranslate"><span class="pre">buy_ware_result</span></code>. EvMenu will call the function given to <code class="docutils literal notranslate"><span class="pre">exec</span></code> like any menu node but it does not
|
||||
need to return anything. In <code class="docutils literal notranslate"><span class="pre">buy_ware_result</span></code> we determine if the customer can afford the cost and
|
||||
give proper return messages. This is also where we actually move the bought item into the inventory
|
||||
of the customer.</p>
|
||||
</section>
|
||||
<section id="the-command-to-start-the-menu">
|
||||
<h3>The command to start the menu<a class="headerlink" href="#the-command-to-start-the-menu" title="Permalink to this headline">¶</a></h3>
|
||||
<p>We could <em>in principle</em> launch the shopping menu the moment a customer steps into our shop room, but
|
||||
this would probably be considered pretty annoying. It’s better to create a <a class="reference internal" href="../Components/Commands.html"><span class="doc std std-doc">Command</span></a> for
|
||||
customers to explicitly wanting to shop around.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/typeclasses/npcshop.py</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">CmdBuy</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> Start to do some shopping</span>
|
||||
|
||||
<span class="sd"> Usage:</span>
|
||||
<span class="sd"> buy</span>
|
||||
<span class="sd"> shop</span>
|
||||
<span class="sd"> browse</span>
|
||||
|
||||
<span class="sd"> This will allow you to browse the wares of the</span>
|
||||
<span class="sd"> current shop and buy items you want.</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"buy"</span>
|
||||
<span class="n">aliases</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"shop"</span><span class="p">,</span> <span class="s2">"browse"</span><span class="p">)</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="s2">"Starts the shop EvMenu instance"</span>
|
||||
<span class="n">evmenu</span><span class="o">.</span><span class="n">EvMenu</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">,</span>
|
||||
<span class="s2">"typeclasses.npcshop"</span><span class="p">,</span>
|
||||
<span class="n">startnode</span><span class="o">=</span><span class="s2">"menunode_shopfront"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This will launch the menu. The <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> instance is initialized with the path to this very module -
|
||||
since the only global functions available in this module are our menu nodes, this will work fine
|
||||
(you could also have put those in a separate module). We now just need to put this command in a
|
||||
<a class="reference internal" href="../Components/Command-Sets.html"><span class="doc std std-doc">CmdSet</span></a> so we can add it correctly to the game:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">CmdSet</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">ShopCmdSet</span><span class="p">(</span><span class="n">CmdSet</span><span class="p">):</span>
|
||||
<span class="k">def</span> <span class="nf">at_cmdset_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">CmdBuy</span><span class="p">())</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="building-the-shop">
|
||||
<h2>Building the shop<a class="headerlink" href="#building-the-shop" title="Permalink to this headline">¶</a></h2>
|
||||
<p>There are really only two things that separate our shop from any other Room:</p>
|
||||
<ul class="simple">
|
||||
<li><p>The shop has the <code class="docutils literal notranslate"><span class="pre">storeroom</span></code> Attribute set on it, pointing to a second (completely normal) room.</p></li>
|
||||
<li><p>It has the <code class="docutils literal notranslate"><span class="pre">ShopCmdSet</span></code> stored on itself. This makes the <code class="docutils literal notranslate"><span class="pre">buy</span></code> command available to users entering
|
||||
the shop.</p></li>
|
||||
</ul>
|
||||
<p>For testing we could easily add these features manually to a room using <code class="docutils literal notranslate"><span class="pre">@py</span></code> or other admin
|
||||
commands. Just to show how it can be done we’ll instead make a custom <a class="reference internal" href="../Components/Typeclasses.html"><span class="doc std std-doc">Typeclass</span></a> for
|
||||
the shop room and make a small command that builders can use to build both the shop and the
|
||||
storeroom at once.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># bottom of mygame/typeclasses/npcshop.py</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">DefaultRoom</span><span class="p">,</span> <span class="n">DefaultExit</span><span class="p">,</span> <span class="n">DefaultObject</span>
|
||||
<span class="kn">from</span> <span class="nn">evennia.utils.create</span> <span class="kn">import</span> <span class="n">create_object</span>
|
||||
|
||||
<span class="c1"># class for our front shop room</span>
|
||||
<span class="k">class</span> <span class="nc">NPCShop</span><span class="p">(</span><span class="n">DefaultRoom</span><span class="p">):</span>
|
||||
<span class="k">def</span> <span class="nf">at_object_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="c1"># we could also use add(ShopCmdSet, persistent=True)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">add_default</span><span class="p">(</span><span class="n">ShopCmdSet</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">storeroom</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
|
||||
<span class="c1"># command to build a complete shop (the Command base class</span>
|
||||
<span class="c1"># should already have been imported earlier in this file)</span>
|
||||
<span class="k">class</span> <span class="nc">CmdBuildShop</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> Build a new shop</span>
|
||||
|
||||
<span class="sd"> Usage:</span>
|
||||
<span class="sd"> @buildshop shopname</span>
|
||||
|
||||
<span class="sd"> This will create a new NPCshop room</span>
|
||||
<span class="sd"> as well as a linked store room (named</span>
|
||||
<span class="sd"> simply <storename>-storage) for the</span>
|
||||
<span class="sd"> wares on sale. The store room will be</span>
|
||||
<span class="sd"> accessed through a locked door in</span>
|
||||
<span class="sd"> the shop.</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"@buildshop"</span>
|
||||
<span class="n">locks</span> <span class="o">=</span> <span class="s2">"cmd:perm(Builders)"</span>
|
||||
<span class="n">help_category</span> <span class="o">=</span> <span class="s2">"Builders"</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="s2">"Create the shop rooms"</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Usage: @buildshop <storename>"</span><span class="p">)</span>
|
||||
<span class="k">return</span>
|
||||
<span class="c1"># create the shop and storeroom</span>
|
||||
<span class="n">shopname</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
|
||||
<span class="n">shop</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="n">NPCShop</span><span class="p">,</span>
|
||||
<span class="n">key</span><span class="o">=</span><span class="n">shopname</span><span class="p">,</span>
|
||||
<span class="n">location</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||||
<span class="n">storeroom</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="n">DefaultRoom</span><span class="p">,</span>
|
||||
<span class="n">key</span><span class="o">=</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">shopname</span><span class="si">}</span><span class="s2">-storage"</span><span class="p">,</span>
|
||||
<span class="n">location</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||||
<span class="n">shop</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">storeroom</span> <span class="o">=</span> <span class="n">storeroom</span>
|
||||
<span class="c1"># create a door between the two</span>
|
||||
<span class="n">shop_exit</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="n">DefaultExit</span><span class="p">,</span>
|
||||
<span class="n">key</span><span class="o">=</span><span class="s2">"back door"</span><span class="p">,</span>
|
||||
<span class="n">aliases</span><span class="o">=</span><span class="p">[</span><span class="s2">"storage"</span><span class="p">,</span> <span class="s2">"store room"</span><span class="p">],</span>
|
||||
<span class="n">location</span><span class="o">=</span><span class="n">shop</span><span class="p">,</span>
|
||||
<span class="n">destination</span><span class="o">=</span><span class="n">storeroom</span><span class="p">)</span>
|
||||
<span class="n">storeroom_exit</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="n">DefaultExit</span><span class="p">,</span>
|
||||
<span class="n">key</span><span class="o">=</span><span class="s2">"door"</span><span class="p">,</span>
|
||||
<span class="n">location</span><span class="o">=</span><span class="n">storeroom</span><span class="p">,</span>
|
||||
<span class="n">destination</span><span class="o">=</span><span class="n">shop</span><span class="p">)</span>
|
||||
<span class="c1"># make a key for accessing the store room</span>
|
||||
<span class="n">storeroom_key_name</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">shopname</span><span class="si">}</span><span class="s2">-storekey"</span>
|
||||
<span class="n">storeroom_key</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="n">DefaultObject</span><span class="p">,</span>
|
||||
<span class="n">key</span><span class="o">=</span><span class="n">storeroom_key_name</span><span class="p">,</span>
|
||||
<span class="n">location</span><span class="o">=</span><span class="n">shop</span><span class="p">)</span>
|
||||
<span class="c1"># only allow chars with this key to enter the store room</span>
|
||||
<span class="n">shop_exit</span><span class="o">.</span><span class="n">locks</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">f</span><span class="s2">"traverse:holds(</span><span class="si">{</span><span class="n">storeroom_key_name</span><span class="si">}</span><span class="s2">)"</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># inform the builder about progress</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="sa">f</span><span class="s2">"The shop </span><span class="si">{</span><span class="n">shop</span><span class="si">}</span><span class="s2"> was created!"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Our typeclass is simple and so is our <code class="docutils literal notranslate"><span class="pre">buildshop</span></code> command. The command (which is for Builders only)
|
||||
just takes the name of the shop and builds the front room and a store room to go with it (always
|
||||
named <code class="docutils literal notranslate"><span class="pre">"<shopname>-storage"</span></code>. It connects the rooms with a two-way exit. You need to add
|
||||
<code class="docutils literal notranslate"><span class="pre">CmdBuildShop</span></code> [to the default cmdset](Starting/Adding-Command-Tutorial#step-2-adding-the-command-to-a-
|
||||
default-cmdset) before you can use it. Once having created the shop you can now <code class="docutils literal notranslate"><span class="pre">@teleport</span></code> to it or
|
||||
<code class="docutils literal notranslate"><span class="pre">@open</span></code> a new exit to it. You could also easily expand the above command to automatically create
|
||||
exits to and from the new shop from your current location.</p>
|
||||
<p>To avoid customers walking in and stealing everything, we create a <a class="reference internal" href="../Components/Locks.html"><span class="doc std std-doc">Lock</span></a> on the storage
|
||||
door. It’s a simple lock that requires the one entering to carry an object named
|
||||
<code class="docutils literal notranslate"><span class="pre"><shopname>-storekey</span></code>. We even create such a key object and drop it in the shop for the new shop
|
||||
keeper to pick up.</p>
|
||||
<blockquote>
|
||||
<div><p>If players are given the right to name their own objects, this simple lock is not very secure and
|
||||
you need to come up with a more robust lock-key solution.</p>
|
||||
</div></blockquote>
|
||||
<blockquote>
|
||||
<div><p>We don’t add any descriptions to all these objects so looking “at” them will not be too thrilling.
|
||||
You could add better default descriptions as part of the <code class="docutils literal notranslate"><span class="pre">@buildshop</span></code> command or leave descriptions
|
||||
this up to the Builder.</p>
|
||||
</div></blockquote>
|
||||
</section>
|
||||
<section id="the-shop-is-open-for-business">
|
||||
<h2>The shop is open for business!<a class="headerlink" href="#the-shop-is-open-for-business" title="Permalink to this headline">¶</a></h2>
|
||||
<p>We now have a functioning shop and an easy way for Builders to create it. All you need now is to
|
||||
<code class="docutils literal notranslate"><span class="pre">@open</span></code> a new exit from the rest of the game into the shop and put some sell-able items in the store
|
||||
room. Our shop does have some shortcomings:</p>
|
||||
<ul class="simple">
|
||||
<li><p>For Characters to be able to buy stuff they need to also have the <code class="docutils literal notranslate"><span class="pre">gold</span></code> Attribute set on
|
||||
themselves.</p></li>
|
||||
<li><p>We manually remove the “door” exit from our items for sale. But what if there are other unsellable
|
||||
items in the store room? What if the shop owner walks in there for example - anyone in the store
|
||||
could then buy them for 1 gold.</p></li>
|
||||
<li><p>What if someone else were to buy the item we’re looking at just before we decide to buy it? It
|
||||
would then be gone and the counter be wrong - the shop would pass us the next item in the list.</p></li>
|
||||
</ul>
|
||||
<p>Fixing these issues are left as an exercise.</p>
|
||||
<p>If you want to keep the shop fully NPC-run you could add a <a class="reference internal" href="../Components/Scripts.html"><span class="doc std std-doc">Script</span></a> to restock the shop’s
|
||||
store room regularly. This shop example could also easily be owned by a human Player (run for them
|
||||
by a hired NPC) - the shop owner would get the key to the store room and be responsible for keeping
|
||||
it well stocked.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="../genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Building-a-mech-tutorial.html" title="Building a mech tutorial"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-Aggressive-NPCs.html" title="Tutorial Aggressive NPCs"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">NPC shop Tutorial</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2022, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Arxcode installing help" href="Arxcode-Installation.html" />
|
||||
<link rel="next" title="Tutorial Tweeting Game Stats" href="Tutorial-Tweeting-Game-Stats.html" />
|
||||
<link rel="prev" title="Dynamic In Game Map" href="Dynamic-In-Game-Map.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Arxcode-Installation.html" title="Arxcode installing help"
|
||||
<a href="Tutorial-Tweeting-Game-Stats.html" title="Tutorial Tweeting Game Stats"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Dynamic-In-Game-Map.html" title="Dynamic In Game Map"
|
||||
|
|
@ -77,8 +77,8 @@
|
|||
<p class="topless"><a href="Dynamic-In-Game-Map.html"
|
||||
title="previous chapter">Dynamic In Game Map</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Arxcode-Installation.html"
|
||||
title="next chapter">Arxcode installing help</a></p>
|
||||
<p class="topless"><a href="Tutorial-Tweeting-Game-Stats.html"
|
||||
title="next chapter">Tutorial Tweeting Game Stats</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -494,7 +494,7 @@ Prompt use <code class="docutils literal notranslate"><span class="pre">evennia<
|
|||
easily new game defining features can be added to Evennia.</p>
|
||||
<p>You can easily build from this tutorial by expanding the map and creating more rooms to explore. Why
|
||||
not add more features to your game by trying other tutorials: [Add weather to your world](Weather-
|
||||
Tutorial), <a class="reference internal" href="Tutorial-Aggressive-NPCs.html"><span class="doc std std-doc">fill your world with NPC’s</span></a> or
|
||||
Tutorial), <a class="reference internal" href="Tutorial-NPC-Reacting.html"><span class="doc std std-doc">fill your world with NPC’s</span></a> or
|
||||
<a class="reference internal" href="Turn-based-Combat-System.html"><span class="doc std std-doc">implement a combat system</span></a>.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
|
@ -515,7 +515,7 @@ Tutorial), <a class="reference internal" href="Tutorial-Aggressive-NPCs.html"><s
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Arxcode-Installation.html" title="Arxcode installing help"
|
||||
<a href="Tutorial-Tweeting-Game-Stats.html" title="Tutorial Tweeting Game Stats"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Dynamic-In-Game-Map.html" title="Dynamic In Game Map"
|
||||
|
|
|
|||
|
|
@ -1,242 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Tutorial Aggressive NPCs — Evennia 1.0-dev documentation</title>
|
||||
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<script src="../_static/language_data.js"></script>
|
||||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="NPC shop Tutorial" href="NPC-shop-Tutorial.html" />
|
||||
<link rel="prev" title="Tutorial NPCs listening" href="Tutorial-NPCs-listening.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="../genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="NPC-shop-Tutorial.html" title="NPC shop Tutorial"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-NPCs-listening.html" title="Tutorial NPCs listening"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Tutorial Aggressive NPCs</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
|
||||
<div class="documentwrapper">
|
||||
<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>
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Tutorial-NPCs-listening.html"
|
||||
title="previous chapter">Tutorial NPCs listening</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="NPC-shop-Tutorial.html"
|
||||
title="next chapter">NPC shop Tutorial</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Howtos/Tutorial-Aggressive-NPCs.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div><h3>Links</h3>
|
||||
<ul>
|
||||
<li><a href="https://www.evennia.com">Home page</a> </li>
|
||||
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
|
||||
<li><a href="http://games.evennia.com">Game Index</a> </li>
|
||||
<li>
|
||||
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
|
||||
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
|
||||
<a href="https://evennia.blogspot.com/">Blog</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Tutorial-Aggressive-NPCs.html">1.0-dev (develop branch)</a></li>
|
||||
<ul>
|
||||
<li><a href="../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="tutorial-aggressive-npcs">
|
||||
<h1>Tutorial Aggressive NPCs<a class="headerlink" href="#tutorial-aggressive-npcs" title="Permalink to this headline">¶</a></h1>
|
||||
<p>This tutorial shows the implementation of an NPC object that responds to characters entering their
|
||||
location. In this example the NPC has the option to respond aggressively or not, but any actions
|
||||
could be triggered this way.</p>
|
||||
<p>One could imagine using a <a class="reference internal" href="../Components/Scripts.html"><span class="doc std std-doc">Script</span></a> that is constantly checking for newcomers. This would be
|
||||
highly inefficient (most of the time its check would fail). Instead we handle this on-demand by
|
||||
using a couple of existing object hooks to inform the NPC that a Character has entered.</p>
|
||||
<p>It is assumed that you already know how to create custom room and character typeclasses, please see
|
||||
the <a class="reference internal" href="Tutorial-for-basic-MUSH-like-game.html"><span class="doc std std-doc">Basic Game tutorial</span></a> if you haven’t already done this.</p>
|
||||
<p>What we will need is the following:</p>
|
||||
<ul class="simple">
|
||||
<li><p>An NPC typeclass that can react when someone enters.</p></li>
|
||||
<li><p>A custom <a class="reference internal" href="../Components/Objects.html#rooms"><span class="std std-doc">Room</span></a> typeclass that can tell the NPC that someone entered.</p></li>
|
||||
<li><p>We will also tweak our default <code class="docutils literal notranslate"><span class="pre">Character</span></code> typeclass a little.</p></li>
|
||||
</ul>
|
||||
<p>To begin with, we need to create an NPC typeclass. Create a new file inside of your typeclasses
|
||||
folder and name it <code class="docutils literal notranslate"><span class="pre">npcs.py</span></code> and then add the following code:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typeclasses.characters</span> <span class="kn">import</span> <span class="n">Character</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">NPC</span><span class="p">(</span><span class="n">Character</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> A NPC typeclass which extends the character class.</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">def</span> <span class="nf">at_char_entered</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">character</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> A simple is_aggressive check.</span>
|
||||
<span class="sd"> Can be expanded upon later.</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">is_aggressive</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">execute_cmd</span><span class="p">(</span><span class="sa">f</span><span class="s2">"say Graaah, die </span><span class="si">{</span><span class="n">character</span><span class="si">}</span><span class="s2">!"</span><span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">execute_cmd</span><span class="p">(</span><span class="sa">f</span><span class="s2">"say Greetings, </span><span class="si">{</span><span class="n">character</span><span class="si">}</span><span class="s2">!"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>We will define our custom <code class="docutils literal notranslate"><span class="pre">Character</span></code> typeclass below. As for the new <code class="docutils literal notranslate"><span class="pre">at_char_entered</span></code> method we’ve
|
||||
just defined, we’ll ensure that it will be called by the room where the NPC is located, when a
|
||||
player enters that room. You’ll notice that right now, the NPC merely speaks. You can expand this
|
||||
part as you like and trigger all sorts of effects here (like combat code, fleeing, bartering or
|
||||
quest-giving) as your game design dictates.</p>
|
||||
<p>Now your <code class="docutils literal notranslate"><span class="pre">typeclasses.rooms</span></code> module needs to have the following added:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># Add this import to the top of your file.</span>
|
||||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">utils</span>
|
||||
|
||||
<span class="c1"># Add this hook in any empty area within your Room class.</span>
|
||||
<span class="k">def</span> <span class="nf">at_object_receive</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="n">source_location</span><span class="p">):</span>
|
||||
<span class="k">if</span> <span class="n">utils</span><span class="o">.</span><span class="n">inherits_from</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="s1">'typeclasses.npcs.NPC'</span><span class="p">):</span> <span class="c1"># An NPC has entered</span>
|
||||
<span class="k">return</span>
|
||||
<span class="k">elif</span> <span class="n">utils</span><span class="o">.</span><span class="n">inherits_from</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="s1">'typeclasses.characters.Character'</span><span class="p">):</span>
|
||||
<span class="c1"># A PC has entered.</span>
|
||||
<span class="c1"># Cause the player's character to look around.</span>
|
||||
<span class="n">obj</span><span class="o">.</span><span class="n">execute_cmd</span><span class="p">(</span><span class="s1">'look'</span><span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="n">utils</span><span class="o">.</span><span class="n">inherits_from</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="s1">'typeclasses.npcs.NPC'</span><span class="p">):</span>
|
||||
<span class="c1"># An NPC is in the room</span>
|
||||
<span class="n">item</span><span class="o">.</span><span class="n">at_char_entered</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">inherits_from</span></code> must be given the full path of the class. If the object inherited a class from your
|
||||
<code class="docutils literal notranslate"><span class="pre">world.races</span></code> module, then you would check inheritance with <code class="docutils literal notranslate"><span class="pre">world.races.Human</span></code>, for example. There
|
||||
is no need to import these prior, as we are passing in the full path. As a matter of a fact,
|
||||
<code class="docutils literal notranslate"><span class="pre">inherits_from</span></code> does not properly work if you import the class and only pass in the name of the
|
||||
class.</p>
|
||||
<blockquote>
|
||||
<div><p>Note:
|
||||
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/objects/objects.py#L1529">at_object_receive</a>
|
||||
is a default hook of the <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> typeclass (and its children). Here we are overriding this
|
||||
hook in our customized room typeclass to suit our needs.</p>
|
||||
</div></blockquote>
|
||||
<p>This room checks the typeclass of objects entering it (using <code class="docutils literal notranslate"><span class="pre">utils.inherits_from</span></code> and responds to
|
||||
<code class="docutils literal notranslate"><span class="pre">Characters</span></code>, ignoring other NPCs or objects. When triggered the room will look through its
|
||||
contents and inform any <code class="docutils literal notranslate"><span class="pre">NPCs</span> <span class="pre">inside</span> <span class="pre">by</span> <span class="pre">calling</span> <span class="pre">their</span> </code>at_char_entered` method.</p>
|
||||
<p>You’ll also see that we have added a ‘look’ into this code. This is because, by default, the
|
||||
<code class="docutils literal notranslate"><span class="pre">at_object_receive</span></code> is carried out <em>before</em> the character’s <code class="docutils literal notranslate"><span class="pre">at_post_move</span></code> which, we will now
|
||||
overload. This means that a character entering would see the NPC perform its actions before the
|
||||
‘look’ command. Deactivate the look command in the default <code class="docutils literal notranslate"><span class="pre">Character</span></code> class within the
|
||||
<code class="docutils literal notranslate"><span class="pre">typeclasses.characters</span></code> module:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># Add this hook in any blank area within your Character class.</span>
|
||||
<span class="k">def</span> <span class="nf">at_post_move</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">source_location</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> Default is to look around after a move</span>
|
||||
<span class="sd"> Note: This has been moved to Room.at_object_receive</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="c1"># self.execute_cmd('look')</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Now let’s create an NPC and make it aggressive. Type the following commands into your MUD client:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">reload</span>
|
||||
<span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">Orc</span><span class="p">:</span><span class="n">npcs</span><span class="o">.</span><span class="n">NPC</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<blockquote>
|
||||
<div><p>Note: You could also give the path as <code class="docutils literal notranslate"><span class="pre">typeclasses.npcs.NPC</span></code>, but Evennia will look into the
|
||||
<code class="docutils literal notranslate"><span class="pre">typeclasses</span></code> folder automatically, so this is a little shorter.</p>
|
||||
</div></blockquote>
|
||||
<p>When you enter the aggressive NPC’s location, it will default to using its peaceful action (say your
|
||||
name is Anna):</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Orc</span> <span class="n">says</span><span class="p">,</span> <span class="s2">"Greetings, Anna!"</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Now we turn on the aggressive mode (we do it manually but it could also be triggered by some sort of
|
||||
AI code).</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">set</span> <span class="n">orc</span><span class="o">/</span><span class="n">is_aggressive</span> <span class="o">=</span> <span class="kc">True</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Now it will perform its aggressive action whenever a character enters.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Orc</span> <span class="n">says</span><span class="p">,</span> <span class="s2">"Graaah, die, Anna!"</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="../genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="NPC-shop-Tutorial.html" title="NPC shop Tutorial"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-NPCs-listening.html" title="Tutorial NPCs listening"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Tutorial Aggressive NPCs</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2022, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Tutorial NPCs listening — Evennia 1.0-dev documentation</title>
|
||||
<title>NPCs that listen to what is said — 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>
|
||||
|
|
@ -17,8 +17,8 @@
|
|||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Tutorial Aggressive NPCs" href="Tutorial-Aggressive-NPCs.html" />
|
||||
<link rel="prev" title="Default Exit Errors" href="Howto-Default-Exit-Errors.html" />
|
||||
<link rel="next" title="NPCs reacting to your presence" href="Tutorial-NPC-Reacting.html" />
|
||||
<link rel="prev" title="Give objects weight" href="Howto-Add-Object-Weight.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -30,14 +30,14 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-Aggressive-NPCs.html" title="Tutorial Aggressive NPCs"
|
||||
<a href="Tutorial-NPC-Reacting.html" title="NPCs reacting to your presence"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Howto-Default-Exit-Errors.html" title="Default Exit Errors"
|
||||
<a href="Howto-Add-Object-Weight.html" title="Give objects weight"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Tutorial NPCs listening</a></li>
|
||||
<li class="nav-item nav-item-this"><a href="">NPCs that listen to what is said</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
|
@ -62,22 +62,22 @@
|
|||
<script>$('#searchbox').show(0);</script>
|
||||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Tutorial NPCs listening</a><ul>
|
||||
<li><a class="reference internal" href="#">NPCs that listen to what is said</a><ul>
|
||||
<li><a class="reference internal" href="#assorted-notes">Assorted notes</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Howto-Default-Exit-Errors.html"
|
||||
title="previous chapter">Default Exit Errors</a></p>
|
||||
<p class="topless"><a href="Howto-Add-Object-Weight.html"
|
||||
title="previous chapter">Give objects weight</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Tutorial-Aggressive-NPCs.html"
|
||||
title="next chapter">Tutorial Aggressive NPCs</a></p>
|
||||
<p class="topless"><a href="Tutorial-NPC-Reacting.html"
|
||||
title="next chapter">NPCs reacting to your presence</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Howtos/Tutorial-NPCs-listening.md.txt"
|
||||
<li><a href="../_sources/Howtos/Tutorial-NPC-Listening.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div><h3>Links</h3>
|
||||
|
|
@ -93,7 +93,7 @@
|
|||
</ul>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Tutorial-NPCs-listening.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="Tutorial-NPC-Listening.html">1.0-dev (develop branch)</a></li>
|
||||
<ul>
|
||||
<li><a href="../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
|
||||
|
||||
|
|
@ -104,17 +104,18 @@
|
|||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="tutorial-npcs-listening">
|
||||
<h1>Tutorial NPCs listening<a class="headerlink" href="#tutorial-npcs-listening" title="Permalink to this headline">¶</a></h1>
|
||||
<p>This tutorial shows the implementation of an NPC object that responds to characters speaking in
|
||||
their location. In this example the NPC parrots what is said, but any actions could be triggered
|
||||
this way.</p>
|
||||
<p>It is assumed that you already know how to create custom room and character typeclasses, please see
|
||||
the <a class="reference internal" href="Tutorial-for-basic-MUSH-like-game.html"><span class="doc std std-doc">Basic Game tutorial</span></a> if you haven’t already done this.</p>
|
||||
<p>What we will need is simply a new NPC typeclass that can react when someone speaks.</p>
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="npcs-that-listen-to-what-is-said">
|
||||
<h1>NPCs that listen to what is said<a class="headerlink" href="#npcs-that-listen-to-what-is-said" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> say hi
|
||||
You say, "hi"
|
||||
The troll under the bridge answers, "well, well. Hello."
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This howto explains how to make an NPC that reacts to characters speaking in their current location. The principle applies to other situations, such as enemies joining a fight or reacting to a character drawing a weapon.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/typeclasses/npc.py</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">characters</span> <span class="kn">import</span> <span class="n">Character</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">Npc</span><span class="p">(</span><span class="n">Character</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> A NPC typeclass which extends the character class.</span>
|
||||
|
|
@ -133,9 +134,38 @@ the <a class="reference internal" href="Tutorial-for-basic-MUSH-like-game.html">
|
|||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">from_obj</span><span class="si">}</span><span class="s2"> said: '</span><span class="si">{</span><span class="n">message</span><span class="si">}</span><span class="s2">'"</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>We add a simple method <code class="docutils literal notranslate"><span class="pre">at_heard_say</span></code> that formats what it hears. We assume that the message that enters it is on the form <code class="docutils literal notranslate"><span class="pre">Someone</span> <span class="pre">says,</span> <span class="pre">"Hello"</span></code>, and we make sure to only get <code class="docutils literal notranslate"><span class="pre">Hello</span></code> in that example.</p>
|
||||
<p>We are not actually calling <code class="docutils literal notranslate"><span class="pre">at_heard_say</span></code> yet. We’ll handle that next.</p>
|
||||
<p>When someone in the room speaks to this NPC, its <code class="docutils literal notranslate"><span class="pre">msg</span></code> method will be called. We will modify the
|
||||
NPCs <code class="docutils literal notranslate"><span class="pre">.msg</span></code> method to catch says so the NPC can respond.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/typeclasses/npc.py</span>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
|
||||
<span class="normal"> 2</span>
|
||||
<span class="normal"> 3</span>
|
||||
<span class="normal"> 4</span>
|
||||
<span class="normal"> 5</span>
|
||||
<span class="normal"> 6</span>
|
||||
<span class="normal"> 7</span>
|
||||
<span class="normal"> 8</span>
|
||||
<span class="normal"> 9</span>
|
||||
<span class="normal">10</span>
|
||||
<span class="normal">11</span>
|
||||
<span class="normal">12</span>
|
||||
<span class="normal">13</span>
|
||||
<span class="normal">14</span>
|
||||
<span class="normal">15</span>
|
||||
<span class="normal">16</span>
|
||||
<span class="normal">17</span>
|
||||
<span class="normal">18</span>
|
||||
<span class="normal">19</span>
|
||||
<span class="normal">20</span>
|
||||
<span class="normal">21</span>
|
||||
<span class="normal">22</span>
|
||||
<span class="normal">23</span>
|
||||
<span class="normal">24</span>
|
||||
<span class="normal">25</span>
|
||||
<span class="normal">26</span>
|
||||
<span class="normal">27</span>
|
||||
<span class="normal">28</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1"># mygame/typeclasses/npc.py</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">characters</span> <span class="kn">import</span> <span class="n">Character</span>
|
||||
<span class="k">class</span> <span class="nc">Npc</span><span class="p">(</span><span class="n">Character</span><span class="p">):</span>
|
||||
|
|
@ -163,29 +193,18 @@ NPCs <code class="docutils literal notranslate"><span class="pre">.msg</span></c
|
|||
<span class="c1"># this is needed if anyone ever puppets this NPC - without it you would never</span>
|
||||
<span class="c1"># get any feedback from the server (not even the results of look)</span>
|
||||
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">text</span><span class="o">=</span><span class="n">text</span><span class="p">,</span> <span class="n">from_obj</span><span class="o">=</span><span class="n">from_obj</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</pre></div></td></tr></table></div>
|
||||
</div>
|
||||
<p>So if the NPC gets a say and that say is not coming from the NPC itself, it will echo it using the
|
||||
<code class="docutils literal notranslate"><span class="pre">at_heard_say</span></code> hook. Some things of note in the above example:</p>
|
||||
<ul class="simple">
|
||||
<li><p>The <code class="docutils literal notranslate"><span class="pre">text</span></code> input can be on many different forms depending on where this <code class="docutils literal notranslate"><span class="pre">msg</span></code> is called from.
|
||||
Instead of trying to analyze <code class="docutils literal notranslate"><span class="pre">text</span></code> in detail with a range of <code class="docutils literal notranslate"><span class="pre">if</span></code> statements we just assume the
|
||||
form we want and catch the error if it does not match. This simplifies the code considerably. It’s
|
||||
called ‘leap before you look’ and is a Python paradigm that may feel unfamiliar if you are used to
|
||||
other languages. Here we ‘swallow’ the error silently, which is fine when the code checked is
|
||||
simple. If not we may want to import <code class="docutils literal notranslate"><span class="pre">evennia.logger.log_trace</span></code> and add <code class="docutils literal notranslate"><span class="pre">log_trace()</span></code> in the
|
||||
<code class="docutils literal notranslate"><span class="pre">except</span></code> clause.</p></li>
|
||||
<li><p>We use <code class="docutils literal notranslate"><span class="pre">execute_cmd</span></code> to fire the <code class="docutils literal notranslate"><span class="pre">say</span></code> command back. We could also have called
|
||||
<code class="docutils literal notranslate"><span class="pre">self.location.msg_contents</span></code> directly but using the Command makes sure all hooks are called (so
|
||||
those seeing the NPC’s <code class="docutils literal notranslate"><span class="pre">say</span></code> can in turn react if they want).</p></li>
|
||||
<li><p>Note the comments about <code class="docutils literal notranslate"><span class="pre">super</span></code> at the end. This will trigger the ‘default’ <code class="docutils literal notranslate"><span class="pre">msg</span></code> (in the parent
|
||||
class) as well. It’s not really necessary as long as no one puppets the NPC (by <code class="docutils literal notranslate"><span class="pre">@ic</span> <span class="pre"><npcname></span></code>) but
|
||||
it’s wise to keep in there since the puppeting player will be totally blind if <code class="docutils literal notranslate"><span class="pre">msg()</span></code> is never
|
||||
returning anything to them!</p></li>
|
||||
<li><p><strong>Line 15</strong> The <code class="docutils literal notranslate"><span class="pre">text</span></code> input can be on many different forms depending on where this <code class="docutils literal notranslate"><span class="pre">msg</span></code> is called from. If you look at the <a class="reference internal" href="../api/evennia.commands.default.general.html#evennia.commands.default.general.CmdSay" title="evennia.commands.default.general.CmdSay"><span class="xref myst py py-class">code of the ‘say’ command</span></a> you’d find that it will call <code class="docutils literal notranslate"><span class="pre">.msg</span></code> with <code class="docutils literal notranslate"><span class="pre">("Hello",</span> <span class="pre">{"type":</span> <span class="pre">"say"})</span></code>. We use this knowledge to figure out if this comes from a <code class="docutils literal notranslate"><span class="pre">say</span></code> or not.</p></li>
|
||||
<li><p><strong>Line 24</strong>: We use <code class="docutils literal notranslate"><span class="pre">execute_cmd</span></code> to fire the NPCs own <code class="docutils literal notranslate"><span class="pre">say</span></code> command back. This works because the NPC is actually a child of <code class="docutils literal notranslate"><span class="pre">DefaultCharacter</span></code> - so it has the <code class="docutils literal notranslate"><span class="pre">CharacterCmdSet</span></code> on it! Normally you should use <code class="docutils literal notranslate"><span class="pre">execute_cmd</span></code> only sparingly; it’s usually more efficient to call the actual code used by the Command directly. For this tutorial, invoking the command is shorter to write while making sure all hooks are called</p></li>
|
||||
<li><p><strong>Line26</strong>: Note the comments about <code class="docutils literal notranslate"><span class="pre">super</span></code> at the end. This will trigger the ‘default’ <code class="docutils literal notranslate"><span class="pre">msg</span></code> (in the parent class) as well. It’s not really necessary as long as no one puppets the NPC (by <code class="docutils literal notranslate"><span class="pre">@ic</span> <span class="pre"><npcname></span></code>) but it’s wise to keep in there since the puppeting player will be totally blind if <code class="docutils literal notranslate"><span class="pre">msg()</span></code> is never returning anything to them!</p></li>
|
||||
</ul>
|
||||
<p>Now that’s done, let’s create an NPC and see what it has to say for itself.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@reload</span>
|
||||
<span class="nd">@create</span><span class="o">/</span><span class="n">drop</span> <span class="n">Guild</span> <span class="n">Master</span><span class="p">:</span><span class="n">npc</span><span class="o">.</span><span class="n">Npc</span>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">reload</span>
|
||||
<span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">Guild</span> <span class="n">Master</span><span class="p">:</span><span class="n">npc</span><span class="o">.</span><span class="n">Npc</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>(you could also give the path as <code class="docutils literal notranslate"><span class="pre">typeclasses.npc.Npc</span></code>, but Evennia will look into the <code class="docutils literal notranslate"><span class="pre">typeclasses</span></code>
|
||||
|
|
@ -201,8 +220,7 @@ Guild Master says, "Anna said: 'hi'"
|
|||
<code class="docutils literal notranslate"><span class="pre">msg</span></code> would be to modify the <code class="docutils literal notranslate"><span class="pre">at_say</span></code> hook on the <em>Character</em> instead. It could detect that it’s
|
||||
sending to an NPC and call the <code class="docutils literal notranslate"><span class="pre">at_heard_say</span></code> hook directly.</p>
|
||||
<p>While the tutorial solution has the advantage of being contained only within the NPC class,
|
||||
combining this with using the Character class gives more direct control over how the NPC will react.
|
||||
Which way to go depends on the design requirements of your particular game.</p>
|
||||
combining this with using the Character class gives more direct control over how the NPC will react. Which way to go depends on the design requirements of your particular game.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
|
@ -222,14 +240,14 @@ Which way to go depends on the design requirements of your particular game.</p>
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-Aggressive-NPCs.html" title="Tutorial Aggressive NPCs"
|
||||
<a href="Tutorial-NPC-Reacting.html" title="NPCs reacting to your presence"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Howto-Default-Exit-Errors.html" title="Default Exit Errors"
|
||||
<a href="Howto-Add-Object-Weight.html" title="Give objects weight"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Tutorial NPCs listening</a></li>
|
||||
<li class="nav-item nav-item-this"><a href="">NPCs that listen to what is said</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
386
docs/1.0-dev/Howtos/Tutorial-NPC-Merchants.html
Normal file
386
docs/1.0-dev/Howtos/Tutorial-NPC-Merchants.html
Normal file
|
|
@ -0,0 +1,386 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>NPC merchants — Evennia 1.0-dev documentation</title>
|
||||
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<script src="../_static/language_data.js"></script>
|
||||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Building a mech tutorial" href="Building-a-mech-tutorial.html" />
|
||||
<link rel="prev" title="NPCs reacting to your presence" href="Tutorial-NPC-Reacting.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="../genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Building-a-mech-tutorial.html" title="Building a mech tutorial"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-NPC-Reacting.html" title="NPCs reacting to your presence"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">NPC merchants</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
|
||||
<div class="documentwrapper">
|
||||
<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>
|
||||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">NPC merchants</a><ul>
|
||||
<li><a class="reference internal" href="#making-the-merchant-class">Making the merchant class</a></li>
|
||||
<li><a class="reference internal" href="#coding-the-shopping-menu">Coding the shopping menu</a></li>
|
||||
<li><a class="reference internal" href="#the-shop-is-open-for-business">The shop is open for business!</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Tutorial-NPC-Reacting.html"
|
||||
title="previous chapter">NPCs reacting to your presence</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Building-a-mech-tutorial.html"
|
||||
title="next chapter">Building a mech tutorial</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Howtos/Tutorial-NPC-Merchants.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div><h3>Links</h3>
|
||||
<ul>
|
||||
<li><a href="https://www.evennia.com">Home page</a> </li>
|
||||
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
|
||||
<li><a href="http://games.evennia.com">Game Index</a> </li>
|
||||
<li>
|
||||
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
|
||||
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
|
||||
<a href="https://evennia.blogspot.com/">Blog</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Tutorial-NPC-Merchants.html">1.0-dev (develop branch)</a></li>
|
||||
<ul>
|
||||
<li><a href="../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="npc-merchants">
|
||||
<h1>NPC merchants<a class="headerlink" href="#npc-merchants" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>*** Welcome to ye Old Sword shop! ***
|
||||
Things for sale (choose 1-3 to inspect, quit to exit):
|
||||
_________________________________________________________
|
||||
1. A rusty sword (5 gold)
|
||||
2. A sword with a leather handle (10 gold)
|
||||
3. Excalibur (100 gold)
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This will introduce an NPC able to sell things. In practice this means that when you interact with them you’ll get shown a <em>menu</em> of choices. Evennia provides the <a class="reference internal" href="../Components/EvMenu.html"><span class="doc std std-doc">EvMenu</span></a> utility to easily create in-game menus.</p>
|
||||
<p>We will store all the merchant’s wares in their inventory. This means that they may stand in an actual shop room, at a market or wander the road. We will also use ‘gold’ as an example currency.<br />
|
||||
To enter the shop, you’ll just need to stand in the same room and use the <code class="docutils literal notranslate"><span class="pre">buy/shop</span></code> command.</p>
|
||||
<section id="making-the-merchant-class">
|
||||
<h2>Making the merchant class<a class="headerlink" href="#making-the-merchant-class" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The merchant will respond to you giving the <code class="docutils literal notranslate"><span class="pre">shop</span></code> or <code class="docutils literal notranslate"><span class="pre">buy</span></code> command in their presence.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in for example mygame/typeclasses/merchants.py </span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">typeclasses.objects</span> <span class="kn">import</span> <span class="n">Object</span>
|
||||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">Command</span><span class="p">,</span> <span class="n">CmdSet</span><span class="p">,</span> <span class="n">EvMenu</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">CmdOpenShop</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> Open the shop! </span>
|
||||
|
||||
<span class="sd"> Usage:</span>
|
||||
<span class="sd"> shop/buy </span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"shop"</span>
|
||||
<span class="n">aliases</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"buy"</span><span class="p">]</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="c1"># this will sit on the Merchant, which is self.obj. </span>
|
||||
<span class="c1"># the self.caller is the player wanting to buy stuff. </span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="o">.</span><span class="n">open_shop</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">)</span>
|
||||
|
||||
|
||||
<span class="k">class</span> <span class="nc">MerchantCmdSet</span><span class="p">(</span><span class="n">CmdSet</span><span class="p">):</span>
|
||||
<span class="k">def</span> <span class="nf">at_cmdset_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">CmdOpenShop</span><span class="p">())</span>
|
||||
|
||||
|
||||
<span class="k">class</span> <span class="nc">NPCMerchant</span><span class="p">(</span><span class="n">Object</span><span class="p">):</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">at_object_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">add_default</span><span class="p">(</span><span class="n">MerchantCmdSet</span><span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">open_shop</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">shopper</span><span class="p">):</span>
|
||||
<span class="n">menunodes</span> <span class="o">=</span> <span class="p">{}</span> <span class="c1"># TODO! </span>
|
||||
<span class="n">shopname</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">shopname</span> <span class="ow">or</span> <span class="s2">"The shop"</span>
|
||||
<span class="n">EvMenu</span><span class="p">(</span><span class="n">shopper</span><span class="p">,</span> <span class="n">menunodes</span><span class="p">,</span> <span class="n">startnode</span><span class="o">=</span><span class="s2">"shop_start"</span><span class="p">,</span>
|
||||
<span class="n">shopname</span><span class="o">=</span><span class="n">shopname</span><span class="p">,</span> <span class="n">shopkeeper</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span> <span class="n">wares</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">)</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>We could also have put the commands in a separate module, but for compactness, we put it all with the merchant typeclass.</p>
|
||||
<p>Note that we make the merchant an <code class="docutils literal notranslate"><span class="pre">Object</span></code>! Since we don’t give them any other commands, it makes little sense to let them be a <code class="docutils literal notranslate"><span class="pre">Character</span></code>.</p>
|
||||
<p>We make a very simple <code class="docutils literal notranslate"><span class="pre">shop</span></code>/<code class="docutils literal notranslate"><span class="pre">buy</span></code> Command and make sure to add it on the merchant in its own cmdset.</p>
|
||||
<p>We initialize <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> on the <code class="docutils literal notranslate"><span class="pre">shopper</span></code> but we haven’t created any <code class="docutils literal notranslate"><span class="pre">menunodes</span></code> yet, so this will not actually do much at this point. It’s important that we we pass <code class="docutils literal notranslate"><span class="pre">shopname</span></code>, <code class="docutils literal notranslate"><span class="pre">shopkeeper</span></code> and <code class="docutils literal notranslate"><span class="pre">wares</span></code> into the menu, it means they will be made available as properties on the EvMenu instance - we will be able to access them from inside the menu.</p>
|
||||
</section>
|
||||
<section id="coding-the-shopping-menu">
|
||||
<h2>Coding the shopping menu<a class="headerlink" href="#coding-the-shopping-menu" title="Permalink to this headline">¶</a></h2>
|
||||
<p><a class="reference internal" href="../Components/EvMenu.html"><span class="doc std std-doc">EvMenu</span></a> splits the menu into <em>nodes</em> represented by Python functions. Each node represents a stop in the menu where the user has to make a choice.</p>
|
||||
<p>For simplicity, we’ll code the shop interface above the <code class="docutils literal notranslate"><span class="pre">NPCMerchant</span></code> class in the same module.</p>
|
||||
<p>The start node of the shop named “ye Old Sword shop!” will look like this if there are only 3 wares to sell:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>*** Welcome to ye Old Sword shop! ***
|
||||
Things for sale (choose 1-3 to inspect, quit to exit):
|
||||
_________________________________________________________
|
||||
1. A rusty sword (5 gold)
|
||||
2. A sword with a leather handle (10 gold)
|
||||
3. Excalibur (100 gold)
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/typeclasses/merchants.py</span>
|
||||
|
||||
<span class="c1"># top of module, above NPCMerchant class.</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">node_shopfront</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">"This is the top-menu screen."</span>
|
||||
|
||||
<span class="c1"># made available since we passed them to EvMenu on start </span>
|
||||
<span class="n">menu</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_evmenu</span>
|
||||
<span class="n">shopname</span> <span class="o">=</span> <span class="n">menu</span><span class="o">.</span><span class="n">shopname</span>
|
||||
<span class="n">shopkeeper</span> <span class="o">=</span> <span class="n">menu</span><span class="o">.</span><span class="n">shopkeeper</span>
|
||||
<span class="n">wares</span> <span class="o">=</span> <span class="n">menu</span><span class="o">.</span><span class="n">wares</span>
|
||||
|
||||
<span class="n">text</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"*** Welcome to </span><span class="si">{</span><span class="n">shopname</span><span class="si">}</span><span class="s2">! ***</span><span class="se">\n</span><span class="s2">"</span>
|
||||
<span class="k">if</span> <span class="n">wares</span><span class="p">:</span>
|
||||
<span class="n">text</span> <span class="o">+=</span> <span class="sa">f</span><span class="s2">" Things for sale (choose 1-</span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">wares</span><span class="p">)</span><span class="si">}</span><span class="s2"> to inspect); quit to exit:"</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">text</span> <span class="o">+=</span> <span class="s2">" There is nothing for sale; quit to exit."</span>
|
||||
|
||||
<span class="n">options</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="n">ware</span> <span class="ow">in</span> <span class="n">wares</span><span class="p">:</span>
|
||||
<span class="c1"># add an option for every ware in store</span>
|
||||
<span class="n">gold_val</span> <span class="o">=</span> <span class="n">ware</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">gold_value</span> <span class="ow">or</span> <span class="mi">1</span>
|
||||
<span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">"desc"</span><span class="p">:</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">ware</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> (</span><span class="si">{</span><span class="n">gold_val</span><span class="si">}</span><span class="s2"> gold)"</span><span class="p">,</span>
|
||||
<span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span><span class="s2">"inspect_and_buy"</span><span class="p">,</span>
|
||||
<span class="p">{</span><span class="s2">"selected_ware"</span><span class="p">:</span> <span class="n">ware</span><span class="p">})</span>
|
||||
<span class="p">})</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Inside the node we can access the menu on the caller as <code class="docutils literal notranslate"><span class="pre">caller.ndb._evmenu</span></code>. The extra keywords we passed into <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> are available on this menu instance. Armed with this we can easily present a shop interface. Each option will become a numbered choice on this screen.</p>
|
||||
<p>Note how we pass the <code class="docutils literal notranslate"><span class="pre">ware</span></code> with each option and label it <code class="docutils literal notranslate"><span class="pre">selected_ware</span></code>. This will be accessible in the next node’s <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> argument</p>
|
||||
<p>If a player choose one of the wares, they should be able to inspect it. Here’s how it should look if they selected <code class="docutils literal notranslate"><span class="pre">1</span></code> in ye Old Sword shop:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">You</span> <span class="n">inspect</span> <span class="n">A</span> <span class="n">rusty</span> <span class="n">sword</span><span class="p">:</span>
|
||||
|
||||
<span class="n">This</span> <span class="ow">is</span> <span class="n">an</span> <span class="n">old</span> <span class="n">weapon</span> <span class="n">maybe</span> <span class="n">once</span> <span class="n">used</span> <span class="n">by</span> <span class="n">soldiers</span> <span class="ow">in</span> <span class="n">some</span>
|
||||
<span class="n">long</span> <span class="n">forgotten</span> <span class="n">army</span><span class="o">.</span> <span class="n">It</span> <span class="ow">is</span> <span class="n">rusty</span> <span class="ow">and</span> <span class="ow">in</span> <span class="n">bad</span> <span class="n">condition</span><span class="o">.</span>
|
||||
<span class="n">__________________________________________________________</span>
|
||||
<span class="mf">1.</span> <span class="n">Buy</span> <span class="n">A</span> <span class="n">rusty</span> <span class="n">sword</span> <span class="p">(</span><span class="mi">5</span> <span class="n">gold</span><span class="p">)</span>
|
||||
<span class="mf">2.</span> <span class="n">Look</span> <span class="k">for</span> <span class="n">something</span> <span class="k">else</span><span class="o">.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If you buy, you’ll see</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>You pay 5 gold and purchase A rusty sword!
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>or</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>You cannot afford 5 gold for A rusty sword!
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Either way you should end up back at the top level of the shopping menu again and can continue browsing or quit the menu with <code class="docutils literal notranslate"><span class="pre">quit</span></code>.</p>
|
||||
<p>Here’s how it looks in code:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/typeclasses/merchants.py </span>
|
||||
|
||||
<span class="c1"># right after the other node</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_buy_item</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">"Called if buyer chooses to buy"</span>
|
||||
<span class="n">selected_ware</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s2">"selected_ware"</span><span class="p">]</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="n">selected_ware</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">gold_value</span> <span class="ow">or</span> <span class="mi">1</span>
|
||||
<span class="n">wealth</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">gold</span> <span class="ow">or</span> <span class="mi">0</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">wealth</span> <span class="o">>=</span> <span class="n">value</span><span class="p">:</span>
|
||||
<span class="n">rtext</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"You pay </span><span class="si">{</span><span class="n">value</span><span class="si">}</span><span class="s2"> gold and purchase </span><span class="si">{</span><span class="n">ware</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2">!"</span>
|
||||
<span class="n">caller</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">gold</span> <span class="o">-=</span> <span class="n">value</span>
|
||||
<span class="n">move_to</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">quiet</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">move_type</span><span class="o">=</span><span class="s2">"buy"</span><span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">rtext</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"You cannot afford </span><span class="si">{</span><span class="n">value</span><span class="si">}</span><span class="s2"> gold for </span><span class="si">{</span><span class="n">ware</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2">!"</span>
|
||||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">rtext</span><span class="p">)</span>
|
||||
<span class="c1"># no matter what, we return to the top level of the shop</span>
|
||||
<span class="k">return</span> <span class="s2">"shopfront"</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">node_inspect_and_buy</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">"Sets up the buy menu screen."</span>
|
||||
|
||||
<span class="c1"># passed from the option we chose </span>
|
||||
<span class="n">selected_ware</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s2">"selected_ware"</span><span class="p">]</span>
|
||||
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="n">selected_ware</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">gold_value</span> <span class="ow">or</span> <span class="mi">1</span>
|
||||
<span class="n">text</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"You inspect </span><span class="si">{</span><span class="n">ware</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2">:</span><span class="se">\n\n</span><span class="si">{</span><span class="n">ware</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">desc</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="n">gold_val</span> <span class="o">=</span> <span class="n">ware</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">gold_value</span> <span class="ow">or</span> <span class="mi">1</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="sa">f</span><span class="s2">"Buy </span><span class="si">{</span><span class="n">ware</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> for </span><span class="si">{</span><span class="n">gold_val</span><span class="si">}</span><span class="s2"> gold"</span><span class="p">,</span>
|
||||
<span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span><span class="n">_buy_item</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">)</span>
|
||||
<span class="p">},</span> <span class="p">{</span>
|
||||
<span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"Look for something else"</span><span class="p">,</span>
|
||||
<span class="s2">"goto"</span><span class="p">:</span> <span class="s2">"shopfront"</span><span class="p">,</span>
|
||||
<span class="p">})</span>
|
||||
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>In this node we grab the <code class="docutils literal notranslate"><span class="pre">selected_ware</span></code> from <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> - this we pased along from the option on the previous node. We display its description and value. If the user buys, we reroute through the <code class="docutils literal notranslate"><span class="pre">_buy_item</span></code> helper function (this is not a node, it’s just a callable that must return the name of the next node to go to.). In <code class="docutils literal notranslate"><span class="pre">_buy_item</span></code> we check if the buyer can affort the ware, and if it can we move it to their inventory. Either way, this method returns <code class="docutils literal notranslate"><span class="pre">shop_front</span></code> as the next node.</p>
|
||||
<p>We have been referring to two nodes here: <code class="docutils literal notranslate"><span class="pre">"shopfront"</span></code> and <code class="docutils literal notranslate"><span class="pre">"inspect_and_buy"</span></code> , we should map them to the code in the menu. Scroll down to the <code class="docutils literal notranslate"><span class="pre">NPCMerchant</span></code> class in the same module and find that unfinished <code class="docutils literal notranslate"><span class="pre">open_shop</span></code> method again:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in /mygame/typeclasses/merchants.py</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">node_shopfront</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"># ... </span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_buy_item</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"># ...</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">node_inspect_and_buy</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"># ... </span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">NPCMerchant</span><span class="p">(</span><span class="n">Object</span><span class="p">):</span>
|
||||
|
||||
<span class="c1"># ...</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">open_shop</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">shopper</span><span class="p">):</span>
|
||||
<span class="n">menunodes</span> <span class="o">=</span> <span class="p">{</span>
|
||||
<span class="s2">"shopfront"</span><span class="p">:</span> <span class="n">node_shopfront</span><span class="p">,</span>
|
||||
<span class="s2">"inspect_and_buy"</span><span class="p">:</span> <span class="n">node_inspect_and_buy</span>
|
||||
<span class="p">}</span>
|
||||
<span class="n">shopname</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">shopname</span> <span class="ow">or</span> <span class="s2">"The shop"</span>
|
||||
<span class="n">EvMenu</span><span class="p">(</span><span class="n">shopper</span><span class="p">,</span> <span class="n">menunodes</span><span class="p">,</span> <span class="n">startnode</span><span class="o">=</span><span class="s2">"shop_start"</span><span class="p">,</span>
|
||||
<span class="n">shopname</span><span class="o">=</span><span class="n">shopname</span><span class="p">,</span> <span class="n">shopkeeper</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span> <span class="n">wares</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">)</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>We now added the nodes to the Evmenu under their right labels. The merchant is now ready!</p>
|
||||
</section>
|
||||
<section id="the-shop-is-open-for-business">
|
||||
<h2>The shop is open for business!<a class="headerlink" href="#the-shop-is-open-for-business" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Make sure to <code class="docutils literal notranslate"><span class="pre">reload</span></code>.</p>
|
||||
<p>Let’s try it out by creating the merchant and a few wares in-game. Remember that we also must create some gold get this economy going.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">></span> <span class="nb">set</span> <span class="bp">self</span><span class="o">/</span><span class="n">gold</span> <span class="o">=</span> <span class="mi">8</span>
|
||||
|
||||
<span class="o">></span> <span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">Stan</span> <span class="n">S</span><span class="o">.</span> <span class="n">Stanman</span><span class="p">;</span><span class="n">stan</span><span class="p">:</span><span class="n">typeclasses</span><span class="o">.</span><span class="n">merchants</span><span class="o">.</span><span class="n">NPCMerchant</span>
|
||||
<span class="o">></span> <span class="nb">set</span> <span class="n">stan</span><span class="o">/</span><span class="n">shopname</span> <span class="o">=</span> <span class="n">Stan</span><span class="s1">'s previously owned vessles</span>
|
||||
|
||||
<span class="o">></span> <span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">A</span> <span class="n">proud</span> <span class="n">vessel</span><span class="p">;</span><span class="n">ship</span>
|
||||
<span class="o">></span> <span class="nb">set</span> <span class="n">ship</span><span class="o">/</span><span class="n">desc</span> <span class="o">=</span> <span class="n">The</span> <span class="n">thing</span> <span class="n">has</span> <span class="n">holes</span> <span class="ow">in</span> <span class="n">it</span><span class="o">.</span>
|
||||
<span class="o">></span> <span class="nb">set</span> <span class="n">ship</span><span class="o">/</span><span class="n">gold_value</span> <span class="o">=</span> <span class="mi">5</span>
|
||||
|
||||
<span class="o">></span> <span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">A</span> <span class="n">classic</span> <span class="n">speedster</span><span class="p">;</span><span class="n">rowboat</span>
|
||||
<span class="o">></span> <span class="nb">set</span> <span class="n">rowboat</span><span class="o">/</span><span class="n">gold_value</span> <span class="o">=</span> <span class="mi">2</span>
|
||||
<span class="o">></span> <span class="nb">set</span> <span class="n">rowboat</span><span class="o">/</span><span class="n">desc</span> <span class="o">=</span> <span class="n">It</span><span class="s1">'s not going anywhere fast.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Note that a builder without any access to Python code can now set up a personalized merchant with just in-game commands. With the shop all set up, we just need to be in the same room to start consuming!</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>> buy
|
||||
*** Welcome to Stan's previously owned vessels! ***
|
||||
Things for sale (choose 1-3 to inspect, quit to exit):
|
||||
_________________________________________________________
|
||||
1. A proud vessel (5 gold)
|
||||
2. A classic speedster (2 gold)
|
||||
|
||||
> 1
|
||||
|
||||
You inspect A proud vessel:
|
||||
|
||||
The thing has holes in it.
|
||||
__________________________________________________________
|
||||
1. Buy A proud vessel (5 gold)
|
||||
2. Look for something else.
|
||||
|
||||
> 1
|
||||
You pay 5 gold and purchase A proud vessel!
|
||||
|
||||
*** Welcome to Stan's previously owned vessels! ***
|
||||
Things for sale (choose 1-3 to inspect, quit to exit):
|
||||
_________________________________________________________
|
||||
1. A classic speedster (2 gold)
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="../genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Building-a-mech-tutorial.html" title="Building a mech tutorial"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-NPC-Reacting.html" title="NPCs reacting to your presence"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">NPC merchants</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2022, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
214
docs/1.0-dev/Howtos/Tutorial-NPC-Reacting.html
Normal file
214
docs/1.0-dev/Howtos/Tutorial-NPC-Reacting.html
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>NPCs reacting to your presence — Evennia 1.0-dev documentation</title>
|
||||
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<script src="../_static/language_data.js"></script>
|
||||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="NPC merchants" href="Tutorial-NPC-Merchants.html" />
|
||||
<link rel="prev" title="NPCs that listen to what is said" href="Tutorial-NPC-Listening.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="../genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-NPC-Merchants.html" title="NPC merchants"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-NPC-Listening.html" title="NPCs that listen to what is said"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">NPCs reacting to your presence</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
|
||||
<div class="documentwrapper">
|
||||
<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>
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Tutorial-NPC-Listening.html"
|
||||
title="previous chapter">NPCs that listen to what is said</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Tutorial-NPC-Merchants.html"
|
||||
title="next chapter">NPC merchants</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Howtos/Tutorial-NPC-Reacting.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div><h3>Links</h3>
|
||||
<ul>
|
||||
<li><a href="https://www.evennia.com">Home page</a> </li>
|
||||
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
|
||||
<li><a href="http://games.evennia.com">Game Index</a> </li>
|
||||
<li>
|
||||
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
|
||||
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
|
||||
<a href="https://evennia.blogspot.com/">Blog</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Tutorial-NPC-Reacting.html">1.0-dev (develop branch)</a></li>
|
||||
<ul>
|
||||
<li><a href="../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="npcs-reacting-to-your-presence">
|
||||
<h1>NPCs reacting to your presence<a class="headerlink" href="#npcs-reacting-to-your-presence" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> north
|
||||
------------------------------------
|
||||
Meadow
|
||||
You are standing in a green meadow.
|
||||
A bandit is here.
|
||||
------------------------------------
|
||||
Bandit gives you a menacing look!
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This tutorial shows the implementation of an NPC object that responds to characters entering their
|
||||
location.</p>
|
||||
<p>What we will need is the following:</p>
|
||||
<ul class="simple">
|
||||
<li><p>An NPC typeclass that can react when someone enters.</p></li>
|
||||
<li><p>A custom <a class="reference internal" href="../Components/Objects.html#rooms"><span class="std std-doc">Room</span></a> typeclass that can tell the NPC that someone entered.</p></li>
|
||||
<li><p>We will also tweak our default <code class="docutils literal notranslate"><span class="pre">Character</span></code> typeclass a little.</p></li>
|
||||
</ul>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/typeclasses/npcs.py (for example)</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">typeclasses.characters</span> <span class="kn">import</span> <span class="n">Character</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">NPC</span><span class="p">(</span><span class="n">Character</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> A NPC typeclass which extends the character class.</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">def</span> <span class="nf">at_char_entered</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">character</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> A simple is_aggressive check.</span>
|
||||
<span class="sd"> Can be expanded upon later.</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">is_aggressive</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">execute_cmd</span><span class="p">(</span><span class="sa">f</span><span class="s2">"say Graaah! Die, </span><span class="si">{</span><span class="n">character</span><span class="si">}</span><span class="s2">!"</span><span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">execute_cmd</span><span class="p">(</span><span class="sa">f</span><span class="s2">"say Greetings, </span><span class="si">{</span><span class="n">character</span><span class="si">}</span><span class="s2">!"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Here we make a simple method on the <code class="docutils literal notranslate"><span class="pre">NPC</span></code>˙. We expect it to be called when a (player-)character enters the room. We don’t actually set the <code class="docutils literal notranslate"><span class="pre">is_aggressive</span></code> <a class="reference internal" href="../Components/Attributes.html"><span class="doc std std-doc">Attribute</span></a> beforehand; if it’s not set, the NPC is simply non-hostile.</p>
|
||||
<p>Whenever <em>something</em> enters the <code class="docutils literal notranslate"><span class="pre">Room</span></code>, its <a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultObject.at_object_receive" title="evennia.objects.objects.DefaultObject.at_object_receive"><span class="xref myst py py-meth">at_object_receive</span></a> hook will be called. So we should override it.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/typeclasses/rooms.py</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">utils</span>
|
||||
|
||||
<span class="c1"># ... </span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">Room</span><span class="p">(</span><span class="n">ObjectParent</span><span class="p">,</span> <span class="n">DefaultRoom</span><span class="p">):</span>
|
||||
|
||||
<span class="c1"># ... </span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">at_object_receive</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arriving_obj</span><span class="p">,</span> <span class="n">source_location</span><span class="p">):</span>
|
||||
<span class="k">if</span> <span class="n">arriving_obj</span><span class="o">.</span><span class="n">account</span><span class="p">:</span>
|
||||
<span class="c1"># this has an active acccount - a player character</span>
|
||||
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">:</span>
|
||||
<span class="c1"># get all npcs in the room and inform them</span>
|
||||
<span class="k">if</span> <span class="n">utils</span><span class="o">.</span><span class="n">inherits_from</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="s2">"typeclasses.npcs.NPC"</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">at_char_entered</span><span class="p">(</span><span class="n">arriving_obj</span><span class="p">)</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<aside class="sidebar">
|
||||
<p class="sidebar-title">Universal Object methods</p>
|
||||
<p>Remember that Rooms are <code class="docutils literal notranslate"><span class="pre">Objects</span></code>. So the same <code class="docutils literal notranslate"><span class="pre">at_object_receive</span></code> hook will fire for you when you pick something up (making you ‘receive’ it). Or for a box when putting something inside it.</p>
|
||||
</aside>
|
||||
<p>A currently puppeted Character will have an <code class="docutils literal notranslate"><span class="pre">.account</span></code> attached to it. We use that to know that the thing arriving is a Character. We then use Evennia’s <a class="reference internal" href="../api/evennia.utils.utils.html#evennia.utils.utils.inherits_from" title="evennia.utils.utils.inherits_from"><span class="xref myst py py-func">utils.inherits_from</span></a> helper utility to get every NPC in the room can each of their newly created <code class="docutils literal notranslate"><span class="pre">at_char_entered</span></code> method.</p>
|
||||
<p>Make sure to <code class="docutils literal notranslate"><span class="pre">reload</span></code>.</p>
|
||||
<p>Let’s create an NPC and make it aggressive. For the sake of this example, let’s assume your name is “Anna” and that there is a room to the north of your current location.</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> create/drop Orc:typeclasses.npcs.NPC
|
||||
> north
|
||||
> south
|
||||
Orc says, Greetings, Anna!
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Now let’s turn the orc aggressive.</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> set orc/is_aggressive = True
|
||||
> north
|
||||
> south
|
||||
Orc says, Graah! Die, Anna!
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>That’s one easily aggravated Orc!</p>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="../genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-NPC-Merchants.html" title="NPC merchants"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Tutorial-NPC-Listening.html" title="NPCs that listen to what is said"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">NPCs reacting to your presence</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2022, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Add a wiki on your website" href="Web-Add-a-wiki.html" />
|
||||
<link rel="prev" title="Arxcode installing help" href="Arxcode-Installation.html" />
|
||||
<link rel="prev" title="Static In Game Map" href="Static-In-Game-Map.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
<a href="Web-Add-a-wiki.html" title="Add a wiki on your website"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Arxcode-Installation.html" title="Arxcode installing help"
|
||||
<a href="Static-In-Game-Map.html" title="Static In Game Map"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howto’s</a> »</li>
|
||||
|
|
@ -61,8 +61,8 @@
|
|||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Arxcode-Installation.html"
|
||||
title="previous chapter">Arxcode installing help</a></p>
|
||||
<p class="topless"><a href="Static-In-Game-Map.html"
|
||||
title="previous chapter">Static In Game Map</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Web-Add-a-wiki.html"
|
||||
title="next chapter">Add a wiki on your website</a></p>
|
||||
|
|
@ -209,7 +209,7 @@ as <code class="docutils literal notranslate"><span class="pre">mygame/typeclass
|
|||
<a href="Web-Add-a-wiki.html" title="Add a wiki on your website"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Arxcode-Installation.html" title="Arxcode installing help"
|
||||
<a href="Static-In-Game-Map.html" title="Static In Game Map"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Coordinates" href="Tutorial-Coordinates.html" />
|
||||
<link rel="prev" title="Mass and weight for objects" href="Mass-and-weight-for-objects.html" />
|
||||
<link rel="prev" title="Gametime Tutorial" href="Gametime-Tutorial.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
<a href="Tutorial-Coordinates.html" title="Coordinates"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Mass-and-weight-for-objects.html" title="Mass and weight for objects"
|
||||
<a href="Gametime-Tutorial.html" title="Gametime Tutorial"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howto’s</a> »</li>
|
||||
|
|
@ -61,8 +61,8 @@
|
|||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Mass-and-weight-for-objects.html"
|
||||
title="previous chapter">Mass and weight for objects</a></p>
|
||||
<p class="topless"><a href="Gametime-Tutorial.html"
|
||||
title="previous chapter">Gametime Tutorial</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Tutorial-Coordinates.html"
|
||||
title="next chapter">Coordinates</a></p>
|
||||
|
|
@ -163,7 +163,7 @@ weather came before it. Expanding it to be more realistic is a useful exercise.<
|
|||
<a href="Tutorial-Coordinates.html" title="Coordinates"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Mass-and-weight-for-objects.html" title="Mass and weight for objects"
|
||||
<a href="Gametime-Tutorial.html" title="Gametime Tutorial"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@
|
|||
<span class="kn">import</span> <span class="nn">re</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">django.conf</span> <span class="kn">import</span> <span class="n">settings</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">evennia.typeclasses.attributes</span> <span class="kn">import</span> <span class="n">NickTemplateInvalid</span>
|
||||
<span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">utils</span>
|
||||
|
||||
|
|
@ -402,7 +401,10 @@
|
|||
<span class="k">if</span> <span class="n">replstring</span> <span class="o">==</span> <span class="n">old_replstring</span><span class="p">:</span>
|
||||
<span class="n">string</span> <span class="o">+=</span> <span class="sa">f</span><span class="s2">"</span><span class="se">\n</span><span class="s2">Identical </span><span class="si">{</span><span class="n">nicktypestr</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="si">}</span><span class="s2"> already set."</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">string</span> <span class="o">+=</span> <span class="sa">f</span><span class="s2">"</span><span class="se">\n</span><span class="si">{</span><span class="n">nicktypestr</span><span class="si">}</span><span class="s2"> '|w</span><span class="si">{</span><span class="n">old_nickstring</span><span class="si">}</span><span class="s2">|n' updated to map to '|w</span><span class="si">{</span><span class="n">replstring</span><span class="si">}</span><span class="s2">|n'."</span>
|
||||
<span class="n">string</span> <span class="o">+=</span> <span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"</span><span class="se">\n</span><span class="si">{</span><span class="n">nicktypestr</span><span class="si">}</span><span class="s2"> '|w</span><span class="si">{</span><span class="n">old_nickstring</span><span class="si">}</span><span class="s2">|n' updated to map to"</span>
|
||||
<span class="sa">f</span><span class="s2">" '|w</span><span class="si">{</span><span class="n">replstring</span><span class="si">}</span><span class="s2">|n'."</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">string</span> <span class="o">+=</span> <span class="sa">f</span><span class="s2">"</span><span class="se">\n</span><span class="si">{</span><span class="n">nicktypestr</span><span class="si">}</span><span class="s2"> '|w</span><span class="si">{</span><span class="n">nickstring</span><span class="si">}</span><span class="s2">|n' mapped to '|w</span><span class="si">{</span><span class="n">replstring</span><span class="si">}</span><span class="s2">|n'."</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
|
|
|
|||
|
|
@ -1115,7 +1115,7 @@ function - for example you can't use other Python keywords like `if` inside the
|
|||
|
||||
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 [NPC shop tutorial](../Howtos/NPC-shop-Tutorial.md) for an example of this.
|
||||
function more clever. See the [NPC shop tutorial](../Howtos/Tutorial-NPC-Merchants.md) for an example of this.
|
||||
|
||||
|
||||
## Ask for simple input
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ state. They do not fire callbacks, so are not a good fit for use cases
|
|||
where something needs to happen on a specific schedule (use delay or
|
||||
a TickerHandler for that instead).
|
||||
|
||||
See also the evennia documentation for command cooldowns
|
||||
(https://github.com/evennia/evennia/wiki/Command-Cooldown) for more information
|
||||
See also the evennia [howto](../Howtos/Howto-Command-Cooldown.md) for more information
|
||||
about the concept.
|
||||
|
||||
## Installation
|
||||
|
|
|
|||
|
|
@ -1,36 +1,32 @@
|
|||
# Arxcode installing help
|
||||
|
||||
[Arx - After the Reckoning](https://play.arxmush.org/) is a big and very popular
|
||||
[Evennia](https://www.evennia.com)-based game. Arx is heavily roleplaying-centric, relying on game
|
||||
masters to drive the story. Technically it's maybe best described as "a MUSH, but with more coded
|
||||
systems". In August of 2018, the game's developer, Tehom, generously released the [source code of
|
||||
Arx on github](https://github.com/Arx-Game/arxcode). This is a treasure-trove for developers wanting
|
||||
to pick ideas or even get a starting game to build on.
|
||||
```{warning} Arxcode is separately maintained.
|
||||
|
||||
> These instructions are based on the Arx-code released as of *Aug 12, 2018*. They will probably
|
||||
> not work 100% out of the box anymore. Report any differences and changes needed.
|
||||
While Arxcode uses Evennia, it is _not_ part of Evennia itself; we include this documentation only as a service to users. Also, while Arxcode is still actively maintained (2022), these instructions are based on the Arx-code released as of *Aug 12, 2018*. They will probably not work 100% out of the box anymore.
|
||||
|
||||
Arxcode bugs should be directed to [the Arxcode github issue tracker](https://github.com/Arx-Game/arxcode/issues).
|
||||
```
|
||||
|
||||
[Arx - After the Reckoning](https://play.arxmush.org/) is a big and very popular [Evennia](https://www.evennia.com)-based game. Arx is heavily roleplaying-centric, relying on game masters to drive the story. Technically it's maybe best described as "a MUSH, but with more coded systems". In August of 2018, the game's developer, Tehom, generously released the [source code of Arx on github](https://github.com/Arx-Game/arxcode). This is a treasure-trove for developers wanting to pick ideas or even get a starting game to build on.
|
||||
|
||||
It's not too hard to run Arx from the sources (of course you'll start with an empty database) but
|
||||
since part of Arx has grown organically, it doesn't follow standard Evennia paradigms everywhere.
|
||||
This page covers one take on installing and setting things up while making your new Arx-based game
|
||||
better match with the vanilla Evennia install.
|
||||
This page covers one take on installing and setting things up while making your new Arx-based game better match with the vanilla Evennia install.
|
||||
|
||||
## Installing Evennia
|
||||
|
||||
Firstly, set aside a folder/directory on your drive for everything to follow.
|
||||
|
||||
You need to start by installing [Evennia](https://www.evennia.com) by following most of the
|
||||
[Git-installation instructions](../Setup/Installation-Git.md) for your OS. The difference is that you
|
||||
need to `git clone https://github.com/TehomCD/evennia.git` instead of Evennia's repo because Arx
|
||||
uses TehomCD's older Evennia 0.8 [fork](https://github.com/TehomCD/evennia), notably still using
|
||||
Python2. This detail is important if referring to newer Evennia documentation.
|
||||
You need to start by installing [Evennia](https://www.evennia.com) by following most of the [Git-installation instructions](../Setup/Installation-Git.md) for your OS. The difference is that instead of cloning from upstream Evennia, you should do
|
||||
|
||||
If you are new to Evennia it's *highly* recommended that you run through the normal install
|
||||
instructions in full - including initializing and starting a new empty game and connecting to it.
|
||||
git clone https://github.com/TehomCD/evennia.git
|
||||
|
||||
This is because Arx uses TehomCD's older Evennia 0.8 [fork](https://github.com/TehomCD/evennia), notably still using Python2. This detail is important if referring to newer Evennia documentation.
|
||||
|
||||
If you are new to Evennia it's *highly* recommended that you run through the normal install instructions in full - including initializing and starting a new empty game and connecting to it.
|
||||
That way you can be sure Evennia works correctly as a baseline.
|
||||
|
||||
After installing you should have a `virtualenv` running and you should have the following file
|
||||
structure in your set-aside folder:
|
||||
After installing you should have a `virtualenv` running and you should have the following file structure in your set-aside folder:
|
||||
|
||||
```
|
||||
muddev/
|
||||
|
|
@ -53,8 +49,7 @@ to compare to.
|
|||
A new folder `myarx` should appear next to the ones you already had. You could rename this to
|
||||
something else if you want.
|
||||
|
||||
`cd` into `myarx`. If you wonder about the structure of the game dir, you can
|
||||
[read more about it here](Beginner-Tutorial/Part1/Beginner-Tutorial-Gamedir-Overview.md).
|
||||
`cd` into `myarx`. If you wonder about the structure of the game dir, you can [read more about it here](Beginner-Tutorial/Part1/Beginner-Tutorial-Gamedir-Overview.md).
|
||||
|
||||
### Clean up settings
|
||||
|
||||
|
|
@ -79,13 +74,9 @@ except ImportError:
|
|||
print("secret_settings.py file not found or failed to import.")
|
||||
```
|
||||
|
||||
> Note: Indents and capitalization matter in Python. Make indents 4 spaces (not tabs) for your own
|
||||
> sanity. If you want a starter on Python in Evennia, [you can look here](Python-basic-
|
||||
introduction).
|
||||
> Note: Indents and capitalization matter in Python. Make indents 4 spaces (not tabs) for your own sanity. If you want a starter on Python in Evennia, [you can look here](Beginner-Tutorial-Python-basic- introduction).
|
||||
|
||||
This will import Arx' base settings and override them with the Evennia-default telnet port and give
|
||||
the game a name. The slogan changes the sub-text shown under the name of your game in the website
|
||||
header. You can tweak these to your own liking later.
|
||||
This will import Arx' base settings and override them with the Evennia-default telnet port and give the game a name. The slogan changes the sub-text shown under the name of your game in the website header. You can tweak these to your own liking later.
|
||||
|
||||
Next, create a new, empty file `secret_settings.py` in the same location as the `settings.py` file.
|
||||
This can just contain the following:
|
||||
|
|
@ -95,17 +86,11 @@ SECRET_KEY = "sefsefiwwj3 jnwidufhjw4545_oifej whewiu hwejfpoiwjrpw09&4er43233fw
|
|||
|
||||
```
|
||||
|
||||
Replace the long random string with random ASCII characters of your own. The secret key should not
|
||||
be shared.
|
||||
Replace the long random string with random ASCII characters of your own. The secret key should not be shared.
|
||||
|
||||
Next, open `myarx/server/conf/base_settings.py` in your text editor. We want to remove/comment out
|
||||
all mentions of the `decouple` package, which Evennia doesn't use (we use `private_settings.py` to
|
||||
hide away settings that should not be shared).
|
||||
Next, open `myarx/server/conf/base_settings.py` in your text editor. We want to remove/comment out all mentions of the `decouple` package, which Evennia doesn't use (we use `private_settings.py` to hide away settings that should not be shared).
|
||||
|
||||
Comment out `from decouple import config` by adding a `#` to the start of the line: `# from decouple
|
||||
import config`. Then search for `config(` in the file and comment out all lines where this is used.
|
||||
Many of these are specific to the server environment where the original Arx runs, so is not that
|
||||
relevant to us.
|
||||
Comment out `from decouple import config` by adding a `#` to the start of the line: `# from decouple import config`. Then search for `config(` in the file and comment out all lines where this is used. Many of these are specific to the server environment where the original Arx runs, so is not that relevant to us.
|
||||
|
||||
### Install Arx dependencies
|
||||
|
||||
|
|
@ -141,10 +126,7 @@ This creates the database and will step through all database migrations needed.
|
|||
|
||||
evennia start
|
||||
|
||||
If all goes well Evennia will now start up, running Arx! You can connect to it on `localhost` (or
|
||||
`127.0.0.1` if your platform doesn't alias `localhost`), port `4000` using a Telnet client.
|
||||
Alternatively, you can use your web browser to browse to `http://localhost:4001` to see the game's
|
||||
website and get to the web client.
|
||||
If all goes well Evennia will now start up, running Arx! You can connect to it on `localhost` (or `127.0.0.1` if your platform doesn't alias `localhost`), port `4000` using a Telnet client. Alternatively, you can use your web browser to browse to `http://localhost:4001` to see the game's website and get to the web client.
|
||||
|
||||
When you log in you'll get the standard Evennia greeting (since the database is empty), but you can
|
||||
try `help` to see that it's indeed Arx that is running.
|
||||
|
|
@ -162,101 +144,87 @@ run steps 7-8 and 10 to create and connect to your in-came Character.
|
|||
3. Navigate to the `Accounts` section.
|
||||
4. Add a new Account named for the new staffer. Use a place holder password and dummy e-mail
|
||||
address.
|
||||
5. Flag account as `Staff` and apply the `Admin` permission group (This assumes you have already set
|
||||
up an Admin Group in Django).
|
||||
5. Flag account as `Staff` and apply the `Admin` permission group (This assumes you have already set up an Admin Group in Django).
|
||||
6. Add Tags named `player` and `developer`.
|
||||
7. Log into the game using the web client (or a third-party telnet client) using your superuser
|
||||
account. Move to where you want the new staffer character to appear.
|
||||
8. In the game client, run `@create/drop <staffername>:typeclasses.characters.Character`, where
|
||||
`<staffername>` is usually the same name you used for the Staffer account you created in the
|
||||
Admin earlier (if you are creating a Character for your superuser, use your superuser account
|
||||
name).
|
||||
This creates a new in-game Character and places it in your current location.
|
||||
7. Log into the game using the web client (or a third-party telnet client) using your superuser account. Move to where you want the new staffer character to appear.
|
||||
8. In the game client, run `@create/drop <staffername>:typeclasses.characters.Character`, where `<staffername>` is usually the same name you used for the Staffer account you created in the Admin earlier (if you are creating a Character for your superuser, use your superuser account name). This creates a new in-game Character and places it in your current location.
|
||||
9. Have the new Admin player log into the game.
|
||||
10. Have the new Admin puppet the character with `@ic StafferName`.
|
||||
11. Have the new Admin change their password - `@password <old password> = <new password>`.
|
||||
|
||||
Now that you have a Character and an Account object, there's a few additional things you may need to
|
||||
do in order for some commands to function properly. You can either execute these as in-game commands
|
||||
while `ic` (controlling your character object).
|
||||
Now that you have a Character and an Account object, there's a few additional things you may need to do in order for some commands to function properly. You can either execute these as in-game commands while `ic` (controlling your character object).
|
||||
|
||||
1. `py from web.character.models import RosterEntry;RosterEntry.objects.create(player=self.player,
|
||||
character=self)`
|
||||
2. `py from world.dominion.models import PlayerOrNpc, AssetOwner;dompc =
|
||||
PlayerOrNpc.objects.create(player = self.player);AssetOwner.objects.create(player=dompc)`
|
||||
py from web.character.models import RosterEntry;RosterEntry.objects.create(player=self.player, character=self)
|
||||
|
||||
Those steps will give you a 'RosterEntry', 'PlayerOrNpc', and 'AssetOwner' objects. RosterEntry
|
||||
py from world.dominion.models import PlayerOrNpc, AssetOwner;dompc = PlayerOrNpc.objects.create(player=self.player);AssetOwner.objects.create(player=dompc)
|
||||
|
||||
Those steps will give you 'RosterEntry', 'PlayerOrNpc', and 'AssetOwner' objects. RosterEntry
|
||||
explicitly connects a character and account object together, even while offline, and contains
|
||||
additional information about a character's current presence in game (such as which 'roster' they're
|
||||
in, if you choose to use an active roster of characters). PlayerOrNpc are more character extensions,
|
||||
as well as support for npcs with no in-game presence and just represented by a name which can be
|
||||
offscreen members of a character's family. It also allows for membership in Organizations.
|
||||
AssetOwner holds information about a character or organization's money and resources.
|
||||
in, if you choose to use an active roster of characters). PlayerOrNpc are more character extensions, as well as support for npcs with no in-game presence and just represented by a name which can be offscreen members of a character's family. It also allows for membership in Organizations. AssetOwner holds information about a character or organization's money and resources.
|
||||
|
||||
## Alternate Windows install guide
|
||||
|
||||
_Contributed by Pax_
|
||||
|
||||
If for some reason you cannot use the Windows Subsystem for Linux (which would use instructions
|
||||
identical to the ones above), it's possible to get Evennia/Arx running under Anaconda for Windows. The
|
||||
process is a little bit trickier.
|
||||
If for some reason you cannot use the Windows Subsystem for Linux (which would use instructions identical to the ones above), it's possible to get Evennia/Arx running under Anaconda for Windows. The process is a little bit trickier.
|
||||
|
||||
Make sure you have:
|
||||
* Git for Windows https://git-scm.com/download/win
|
||||
* Anaconda for Windows https://www.anaconda.com/distribution/
|
||||
* VC++ Compiler for Python 2.7 https://aka.ms/vcpython27
|
||||
|
||||
conda update conda
|
||||
conda create -n arx python=2.7
|
||||
source activate arx
|
||||
conda update conda
|
||||
conda create -n arx python=2.7
|
||||
source activate arx
|
||||
|
||||
Set up a convenient repository place for things.
|
||||
Set up a convenient repository place for things.
|
||||
|
||||
cd ~
|
||||
mkdir Source
|
||||
cd Source
|
||||
mkdir Arx
|
||||
cd Arx
|
||||
cd ~
|
||||
mkdir Source
|
||||
cd Source
|
||||
mkdir Arx
|
||||
cd Arx
|
||||
|
||||
Replace the SSH git clone links below with your own github forks.
|
||||
If you don't plan to change Evennia at all, you can use the
|
||||
evennia/evennia.git repo instead of a forked one.
|
||||
Replace the SSH git clone links below with your own github forks.
|
||||
If you don't plan to change Evennia at all, you can use the
|
||||
evennia/evennia.git repo instead of a forked one.
|
||||
|
||||
git clone git@github.com:<youruser>/evennia.git
|
||||
git clone git@github.com:<youruser>/arxcode.git
|
||||
git clone git@github.com:<youruser>/evennia.git
|
||||
git clone git@github.com:<youruser>/arxcode.git
|
||||
|
||||
Evennia is a package itself, so we want to install it and all of its
|
||||
prerequisites, after switching to the appropriately-tagged branch for
|
||||
Arxcode.
|
||||
Evennia is a package itself, so we want to install it and all of its
|
||||
prerequisites, after switching to the appropriately-tagged branch for
|
||||
Arxcode.
|
||||
|
||||
cd evennia
|
||||
git checkout tags/v0.7 -b arx-master
|
||||
pip install -e .
|
||||
cd evennia
|
||||
git checkout tags/v0.7 -b arx-master
|
||||
pip install -e .
|
||||
|
||||
Arx has some dependencies of its own, so now we'll go install them
|
||||
As it is not a package, we'll use the normal requirements file.
|
||||
Arx has some dependencies of its own, so now we'll go install them
|
||||
As it is not a package, we'll use the normal requirements file.
|
||||
|
||||
cd ../arxcode
|
||||
pip install -r requirements.txt
|
||||
cd ../arxcode
|
||||
pip install -r requirements.txt
|
||||
|
||||
The git repo doesn't include the empty log directory and Evennia is unhappy if you
|
||||
don't have it, so while still in the arxcode directory...
|
||||
The git repo doesn't include the empty log directory and Evennia is unhappy if you
|
||||
don't have it, so while still in the arxcode directory...
|
||||
|
||||
mkdir server/logs
|
||||
mkdir server/logs
|
||||
|
||||
Now hit https://github.com/evennia/evennia/wiki/Arxcode-installing-help and
|
||||
change the setup stuff as in the 'Clean up settings' section.
|
||||
Now hit https://github.com/evennia/evennia/wiki/Arxcode-installing-help and
|
||||
change the setup stuff as in the 'Clean up settings' section.
|
||||
|
||||
Then we will create our default database...
|
||||
Then we will create our default database...
|
||||
|
||||
../evennia/bin/windows/evennia.bat migrate
|
||||
../evennia/bin/windows/evennia.bat migrate
|
||||
|
||||
...and do the first run. You need winpty because Windows does not have a TTY/PTY
|
||||
by default, and so the Python console input commands (used for prompts on first
|
||||
run) will fail and you will end up in an unhappy place. Future runs, you should
|
||||
not need winpty.
|
||||
|
||||
winpty ../evennia/bin/windows/evennia.bat start
|
||||
winpty ../evennia/bin/windows/evennia.bat start
|
||||
|
||||
Once this is done, you should have your Evennia server running Arxcode up
|
||||
on localhost at port 4000, and the webserver at http://localhost:4001/
|
||||
on localhost at port 4000, and the webserver at http://localhost:4001/.
|
||||
113
docs/1.0-dev/_sources/Howtos/Howto-Add-Object-Weight.md.txt
Normal file
113
docs/1.0-dev/_sources/Howtos/Howto-Add-Object-Weight.md.txt
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
# Give objects weight
|
||||
|
||||
All in-game objets you can touch usually has some weight. What weight does varies from game to game. Commonly it limits how much you can carry. A heavy stone may also hurt you more than a ballon, if it falls on you. If you want to get fancy, a pressure plate may only trigger if the one stepping on it is heavy enough.
|
||||
|
||||
```{code-block} python
|
||||
:linenos:
|
||||
:emphasize-lines: 6,8,10,12
|
||||
|
||||
# inside your mygame/typeclasses/objects.py
|
||||
|
||||
from evennia import DefaultObject
|
||||
from evennia import AttributeProperty
|
||||
|
||||
class ObjectParent:
|
||||
|
||||
weight = AttributeProperty(default=1, autocreate=False)
|
||||
|
||||
@property
|
||||
def total_weight(self):
|
||||
return self.weight + sum(obj.total_weight for obj in self.contents)
|
||||
|
||||
|
||||
class Object(ObjectParent, DefaultObject):
|
||||
# ...
|
||||
```
|
||||
|
||||
```{sidebar} Why not mass?
|
||||
Yes, we know weight varies with gravity. 'Mass' is more scientifically correct. But 'mass' is less commonly used in RPGs, so we stick to 'weight' here. Just know if if your sci-fi characters can vacation on the Moon (1/6 gravity of Earth) you should consider using `mass` everywhere and calculate the current weight on the fly.
|
||||
```
|
||||
|
||||
- **Line 6**: We use the `ObjectParent` mixin. Since this mixin is used for `Characters`, `Exits` and `Rooms` as well as for `Object`, it means all of those will automatically _also_ have weight!
|
||||
- **Line 8**: We use an [AttributeProperty](../Components/Attributes.md#using-attributeproperty) to set up the 'default' weight of 1 (whatever that is). Setting `autocreate=False` means no actual `Attribute` will be created until the weight is actually changed from the default of 1. See the `AttributeProperty` documentation for caveats with this.
|
||||
- **Line 10 and 11**: Using the `@property` decorator on `total_weight` means that we will be able to call `obj.total_weight` instead of `obj.total_weight()` later.
|
||||
- **Line 12**: We sum up all weights from everything "in" this object, by looping over `self.contents`. Since _all_ objects will have weight now, this should always work!
|
||||
|
||||
Let's check out the weight of some trusty boxes
|
||||
```
|
||||
> create/drop box1
|
||||
> py self.search("box1").weight
|
||||
1
|
||||
> py self.search("box1").total_weight
|
||||
1
|
||||
```
|
||||
|
||||
Let's put another box into the first one.
|
||||
|
||||
```
|
||||
> create/drop box2
|
||||
> py self.search("box2").total_weight
|
||||
1
|
||||
> py self.search("box2").location = self.search("box1")
|
||||
> py self.search(box1).total_weight
|
||||
2
|
||||
```
|
||||
|
||||
|
||||
## Limit inventory by weight carried
|
||||
|
||||
To limit how much you can carry, you first need to know your own strength
|
||||
|
||||
```python
|
||||
# in mygame/typeclasses/characters.py
|
||||
|
||||
from evennia import AttributeProperty
|
||||
|
||||
# ...
|
||||
|
||||
class Character(ObjectParent, DefaultCharacter):
|
||||
|
||||
carrying_capacity = AttributeProperty(10, autocreate=False)
|
||||
|
||||
@property
|
||||
def carried_weight(self):
|
||||
return self.total_weight - self.weight
|
||||
|
||||
```
|
||||
|
||||
Here we make sure to add another `AttributeProperty` telling us how much to carry. In a real game, this may be based on how strong the Character is. When we consider how much weight we already carry, we should not include _our own_ weight, so we subtract that.
|
||||
|
||||
To honor this limit, we'll need to override the default `get` command.
|
||||
|
||||
|
||||
```{sidebar} Overriding default commands
|
||||
|
||||
In this example, we implement the beginning of the `CmdGet` and then call the full `CmdGet()` at the end. This is not very efficient, because the parent `CmdGet` will again have to do the `caller.search()` again. To be more efficient, you will likely want to copy the entirety of the `CmdGet` code into your own version and modify it.
|
||||
```
|
||||
|
||||
```python
|
||||
# in mygame/commands/command.py
|
||||
|
||||
# ...
|
||||
from evennia import default_cmds
|
||||
|
||||
# ...
|
||||
|
||||
class WeightAwareCmdGet(default_cmds.CmdGet):
|
||||
|
||||
def func(self):
|
||||
caller = self.caller
|
||||
if not self.args:
|
||||
caller.msg("Get what?")
|
||||
return
|
||||
|
||||
obj = caller.search(self.args)
|
||||
|
||||
if (obj.weight + caller.carried_weight
|
||||
> caller.carrying_capacity):
|
||||
caller.msg("You can't carry that much!")
|
||||
return
|
||||
super().func()
|
||||
```
|
||||
|
||||
Here we add an extra check for the weight of the thing we are trying to pick up, then we call the normal `CmdGet` with `super().func()`.
|
||||
|
|
@ -1,30 +1,27 @@
|
|||
# Command Cooldown
|
||||
# Adding Command Cooldowns
|
||||
|
||||
> hit goblin with sword
|
||||
You strike goblin with the sword. It dodges!
|
||||
> hit goblin with sword
|
||||
You are off-balance and can't attack again yet.
|
||||
|
||||
Some types of games want to limit how often a command can be run. If a
|
||||
character casts the spell *Firestorm*, you might not want them to spam that
|
||||
command over and over. Or in an advanced combat system, a massive swing may
|
||||
command over and over. In an advanced combat system, a massive swing may
|
||||
offer a chance of lots of damage at the cost of not being able to re-do it for
|
||||
a while. Such effects are called *cooldowns*.
|
||||
a while.
|
||||
|
||||
This page exemplifies a very resource-efficient way to do cooldowns. A more
|
||||
'active' way is to use asynchronous delays as in the [](Howto-Command-Duration.md#blocking-commands), the two might be useful to
|
||||
combine if you want to echo some message to the user after the cooldown ends.
|
||||
Such effects are called *command cooldowns*.
|
||||
|
||||
## The Cooldown Contrib
|
||||
```{sidebar}
|
||||
The [Cooldown contrib](../Contribs/Contrib-Cooldowns.md) is a ready-made solution for command cooldowns. It is based on this howto and implements a [handler](Tutorial-Peristent-Handler) on the object to conveniently manage and store the cooldowns.
|
||||
```
|
||||
This howto exemplifies a very resource-efficient way to do cooldowns. A more
|
||||
'active' way is to use asynchronous delays as in the [Command-Duration howto](./Howto-Command-Duration.md#blocking-commands) suggests. The two howto's might be useful to combine if you want to echo some message to the user after the cooldown ends.
|
||||
|
||||
The [Cooldown contrib](../Contribs/Contrib-Cooldowns.md) is a ready-made solution for
|
||||
command cooldowns you can use. It implements a _handler_ on the object to
|
||||
conveniently manage and store the cooldowns in a similar manner exemplified in
|
||||
this tutorial.
|
||||
## An efficient cooldown
|
||||
|
||||
## Non-persistent cooldown
|
||||
|
||||
This little recipe will limit how often a particular command can be run. Since
|
||||
Commands are class instances, and those are cached in memory, a command
|
||||
instance will remember things you store on it. So just store the current time
|
||||
of execution! Next time the command is run, it just needs to check if it has
|
||||
that time stored, and compare it with the current time to see if a desired
|
||||
delay has passed.
|
||||
The idea is that when a [Command](../Components/Commands.md) runs, we store the time it runs. When it next runs, we check again the current time. The command is only allowed to run if enough time passed since now and the previous run. This is a _very_ efficient implementation that only checks on-demand.
|
||||
|
||||
```python
|
||||
# in, say, mygame/commands/spells.py
|
||||
|
|
@ -49,7 +46,7 @@ class CmdSpellFirestorm(default_cmds.MuxCommand):
|
|||
"Implement the spell"
|
||||
|
||||
now = time.time()
|
||||
last_cast = caller.ndb.firestorm_last_cast # could be None
|
||||
last_cast = caller.db.firestorm_last_cast # could be None
|
||||
if last_cast and (now - last_cast < self.rate_of_fire):
|
||||
message = "You cannot cast this spell again yet."
|
||||
self.caller.msg(message)
|
||||
|
|
@ -58,22 +55,21 @@ class CmdSpellFirestorm(default_cmds.MuxCommand):
|
|||
# [the spell effect is implemented]
|
||||
|
||||
# if the spell was successfully cast, store the casting time
|
||||
self.caller.ndb.firestorm_last_cast = now
|
||||
self.caller.db.firestorm_last_cast = now
|
||||
```
|
||||
|
||||
We specify `rate_of_fire` and then just check for a NAtrribute
|
||||
`firestorm_last_cast` and update it if everything works out.
|
||||
We specify `rate_of_fire` and then just check for an [Attribute](../Components/Attributes.md) `firestorm_last_cast` on the `caller.` It is either `None` (because the spell was never cast before) or an timestamp representing the last time the spell was cast.
|
||||
|
||||
Simple and very effective since everything is just stored in memory. The
|
||||
drawback of this simple scheme is that it's non-persistent. If you do
|
||||
`reload`, the cache is cleaned and all such ongoing cooldowns will be
|
||||
forgotten.
|
||||
### Non-Persistent cooldown
|
||||
|
||||
## Persistent cooldown
|
||||
The above implementation will survive a reload. If you don't want that, you can just switch to let `firestorm_last_cast` be a [NAtrribute](../Components/Attributes.md#in-memory-attributes-nattributes) instead. For example:
|
||||
|
||||
To make a cooldown _persistent_ (so it survives a server reload), just
|
||||
use the same technique, but use [Attributes](../Components/Attributes.md) (that is, `.db` instead
|
||||
of `.ndb` storage to save the last-cast time.
|
||||
```python
|
||||
last_cast = caller.ndb.firestorm_last_cast
|
||||
# ...
|
||||
self.caller.ndb.firestorm_last_cast = now
|
||||
```
|
||||
That is, use `.ndb` instead of `.db`. Since a `NAttribute`s are purely in-memory, they can be faster to read and write to than an `Attribute`. So this can be more optimal if your intervals are short and need to change often. The drawback is that they'll reset if the server reloads.
|
||||
|
||||
## Make a cooldown-aware command parent
|
||||
|
||||
|
|
@ -154,5 +150,5 @@ you can have all fire-related spells store the cooldown with the same
|
|||
`cooldown_storage_key` (like `fire_spell_last_used`). That would mean casting
|
||||
of *Firestorm* would block all other fire-related spells for a while.
|
||||
|
||||
Similarly, when you take that that big sword swing, other types of attacks could
|
||||
Similarly, when you take that big sword swing, other types of attacks could
|
||||
be blocked before you can recover your balance.
|
||||
|
|
|
|||
|
|
@ -1,24 +1,41 @@
|
|||
# Command Duration
|
||||
# Commands that take time to finish
|
||||
|
||||
|
||||
Before reading this tutorial, if you haven't done so already, you might want to
|
||||
read [the documentation on commands](../Components/Commands.md) to get a basic understanding of
|
||||
how commands work in Evennia.
|
||||
> craft fine sword
|
||||
You start crafting a fine sword.
|
||||
> north
|
||||
You are too focused on your crafting, and can't move!
|
||||
You create the blade of the sword.
|
||||
You create the pommel of the sword.
|
||||
You finish crafting a Fine Sword.
|
||||
|
||||
In some types of games a command should not start and finish immediately.
|
||||
|
||||
Loading a crossbow might take a bit of time to do - time you don't have when
|
||||
the enemy comes rushing at you. Crafting that armour will not be immediate
|
||||
either. For some types of games the very act of moving or changing pose all
|
||||
comes with a certain time associated with it.
|
||||
|
||||
## The simple way to pause commands with yield
|
||||
There are two main suitable ways to introduce a 'delay' in a [Command](../Components/Commands.md)'s execution:
|
||||
|
||||
Evennia allows a shortcut in syntax to create simple pauses in commands. This
|
||||
syntax uses the `yield` keyword. The `yield` keyword is used in Python to
|
||||
create generators, although you don't need to know what generators are to use
|
||||
this syntax. A short example will probably make it clear:
|
||||
- Using `yield` in the Command's `func` method.
|
||||
- Using the `evennia.utils.delay` utility function.
|
||||
|
||||
We'll simplify both below.
|
||||
|
||||
## Pause commands with `yield`
|
||||
|
||||
The `yield` keyword is a reserved word in Python. It's used to create [generators](https://realpython.com/introduction-to-python-generators/), which are interesting in their own right. For the purpose of this howto though, we just need to know that Evennia will use it to 'pause' the execution of the command for a certain time.
|
||||
|
||||
```{sidebar} This only works in Command.func!
|
||||
|
||||
This `yield` functionality will *only* work in the `func` method of
|
||||
Commands. It works because Evennia has especially catered for it as a convenient shortcut. Trying to use it elsewhere will not work. If you want the same functionality elsewhere you should look up the [interactive decorator](../Concepts/Async-Process.md#the-interactive-decorator).
|
||||
```
|
||||
|
||||
```{code-block} python
|
||||
:linenos:
|
||||
:emphasize-lines: 15
|
||||
|
||||
```python
|
||||
class CmdTest(Command):
|
||||
|
||||
"""
|
||||
|
|
@ -30,53 +47,55 @@ class CmdTest(Command):
|
|||
"""
|
||||
|
||||
key = "test"
|
||||
locks = "cmd:all()"
|
||||
|
||||
def func(self):
|
||||
self.msg("Before ten seconds...")
|
||||
yield 10
|
||||
self.msg("Afterwards.")
|
||||
```
|
||||
> Important: The `yield` functionality will *only* work in the `func` method of
|
||||
> Commands. It only works because Evennia has especially
|
||||
> catered for it in Commands. If you want the same functionality elsewhere you
|
||||
> must use the [interactive decorator](../Concepts/Async-Process.md#the-interactive-decorator).
|
||||
|
||||
The important line is the `yield 10`. It tells Evennia to "pause" the command
|
||||
- **Line 15** : This is the important line. The `yield 10` tells Evennia to "pause" the command
|
||||
and to wait for 10 seconds to execute the rest. If you add this command and
|
||||
run it, you'll see the first message, then, after a pause of ten seconds, the
|
||||
next message. You can use `yield` several times in your command.
|
||||
|
||||
This syntax will not "freeze" all commands. While the command is "pausing",
|
||||
you can execute other commands (or even call the same command again). And
|
||||
other players aren't frozen either.
|
||||
This syntax will not "freeze" all commands. While the command is "pausing", you can execute other commands (or even call the same command again). And other players aren't frozen either.
|
||||
|
||||
> Note: this will not save anything in the database. If you reload the game
|
||||
> while a command is "paused", it will not resume after the server has
|
||||
> reloaded.
|
||||
> Using `yield` is non-persistent. If you `reload` the game while a command is "paused", that pause state is lost and it will _not_ resume after the server has reloaded.
|
||||
|
||||
## Pause commands with `utils.delay`
|
||||
|
||||
## The more advanced way with utils.delay
|
||||
The `yield` syntax is easy to read, easy to understand, easy to use. But it's non-persistent and not that flexible if you want more advanced options.
|
||||
|
||||
The `yield` syntax is easy to read, easy to understand, easy to use. But it's not that flexible if
|
||||
you want more advanced options. Learning to use alternatives might be much worth it in the end.
|
||||
The `evennia.utils.delay` represents is a more powerful way to introduce delays. Unlike `yield`, it
|
||||
can be made persistent and also works outside of `Command.func`. It's however a little more cumbersome to write since unlike `yield` it will not actually stop at the line it's called.
|
||||
|
||||
Below is a simple command example for adding a duration for a command to finish.
|
||||
```{code-block} python
|
||||
:linenos:
|
||||
:emphasize-lines: 14,30
|
||||
|
||||
```python
|
||||
from evennia import default_cmds, utils
|
||||
|
||||
class CmdEcho(default_cmds.MuxCommand):
|
||||
"""
|
||||
wait for an echo
|
||||
Wait for an echo
|
||||
|
||||
Usage:
|
||||
echo <string>
|
||||
|
||||
Calls and waits for an echo
|
||||
Calls and waits for an echo.
|
||||
"""
|
||||
key = "echo"
|
||||
locks = "cmd:all()"
|
||||
|
||||
def echo(self):
|
||||
"Called after 10 seconds."
|
||||
shout = self.args
|
||||
self.caller.msg(
|
||||
"You hear an echo: "
|
||||
f"{shout.upper()} ... "
|
||||
f"{shout.capitalize()} ... "
|
||||
f"{shout.lower()}"
|
||||
)
|
||||
|
||||
def func(self):
|
||||
"""
|
||||
|
|
@ -86,50 +105,39 @@ class CmdEcho(default_cmds.MuxCommand):
|
|||
# this waits non-blocking for 10 seconds, then calls self.echo
|
||||
utils.delay(10, self.echo) # call echo after 10 seconds
|
||||
|
||||
def echo(self):
|
||||
"Called after 10 seconds."
|
||||
shout = self.args
|
||||
self.caller.msg(
|
||||
f"You hear an echo: {shout.upper()} ... {shout.capitalize()} ... {shout.lower()}"
|
||||
)
|
||||
```
|
||||
|
||||
Import this new echo command into the default command set and reload the server. You will find that
|
||||
it will take 10 seconds before you see your shout coming back. You will also find that this is a
|
||||
*non-blocking* effect; you can issue other commands in the interim and the game will go on as usual.
|
||||
The echo will come back to you in its own time.
|
||||
Import this new echo command into the default command set and reload the server. You will find that it will take 10 seconds before you see your shout coming back.
|
||||
|
||||
### About utils.delay()
|
||||
- **Line 14**: We add a new method `echo`. This is a _callback_ - a method/function we will call after a certain time.
|
||||
- **Line 30**: Here we use `utils.delay` to tell Evennia "Please wait for 10 seconds, then call "`self.echo`". Note how we pass `self.echo` and _not_ `self.echo()`! If we did the latter, `echo` would fire _immediately_. Instead we let Evennia do this call for us ten seconds later.
|
||||
|
||||
`utils.delay(timedelay, callback, persistent=False, *args, **kwargs)` is a useful function. It will
|
||||
wait `timedelay` seconds, then call the `callback` function, optionally passing to it the arguments
|
||||
provided to utils.delay by way of *args and/or **kwargs`.
|
||||
You will also find that this is a *non-blocking* effect; you can issue other commands in the interim and the game will go on as usual. The echo will come back to you in its own time.
|
||||
|
||||
> Note: The callback argument should be provided with a python path to the desired function, for
|
||||
instance `my_object.my_function` instead of `my_object.my_function()`. Otherwise my_function would
|
||||
get called and run immediately upon attempting to pass it to the delay function.
|
||||
If you want to provide arguments for utils.delay to use, when calling your callback function, you
|
||||
have to do it separatly, for instance using the utils.delay *args and/or **kwargs, as mentioned
|
||||
above.
|
||||
The call signature for `utils.delay` is:
|
||||
|
||||
> If you are not familiar with the syntax `*args` and `**kwargs`, [see the Python documentation
|
||||
here](https://docs.python.org/2/tutorial/controlflow.html#arbitrary-argument-lists).
|
||||
```python
|
||||
utils.delay(timedelay, callback, persistent=False, *args, **kwargs)
|
||||
```
|
||||
|
||||
Looking at it you might think that `utils.delay(10, callback)` in the code above is just an
|
||||
alternative to some more familiar thing like `time.sleep(10)`. This is *not* the case. If you do
|
||||
`time.sleep(10)` you will in fact freeze the *entire server* for ten seconds! The `utils.delay()`is
|
||||
a thin wrapper around a Twisted
|
||||
[Deferred](https://twistedmatrix.com/documents/11.0.0/core/howto/defer.html) that will delay
|
||||
execution until 10 seconds have passed, but will do so asynchronously, without bothering anyone else
|
||||
(not even you - you can continue to do stuff normally while it waits to continue).
|
||||
```{sidebar} *args and **kwargs
|
||||
|
||||
The point to remember here is that the `delay()` call will not "pause" at that point when it is
|
||||
These are used to indicate any number of arguments or keyword-arguments should be picked up here. In code they are treated as a `tuple` and a `dict` respectively.
|
||||
|
||||
`*args` and `**kwargs` are used in many places in Evennia. [See an online tutorial here](https://realpython.com/python-kwargs-and-args).
|
||||
```
|
||||
If you set `persistent=True`, this delay will survive a `reload`. If you pass `*args` and/or `**kwargs`, they will be passed on into the `callback`. So this way you can pass more complex arguments to the delayed function.
|
||||
|
||||
It's important to remember that the `delay()` call will not "pause" at that point when it is
|
||||
called (the way `yield` does in the previous section). The lines after the `delay()` call will
|
||||
actually execute *right away*. What you must do is to tell it which function to call *after the time
|
||||
has passed* (its "callback"). This may sound strange at first, but it is normal practice in
|
||||
asynchronous systems. You can also link such calls together as seen below:
|
||||
asynchronous systems. You can also link such calls together:
|
||||
|
||||
```{code-block}
|
||||
:linenos:
|
||||
:emphasize-lines: 19,22,28,34
|
||||
|
||||
```python
|
||||
from evennia import default_cmds, utils
|
||||
|
||||
class CmdEcho(default_cmds.MuxCommand):
|
||||
|
|
@ -142,7 +150,6 @@ class CmdEcho(default_cmds.MuxCommand):
|
|||
Calls and waits for an echo
|
||||
"""
|
||||
key = "echo"
|
||||
locks = "cmd:all()"
|
||||
|
||||
def func(self):
|
||||
"This sets off a chain of delayed calls"
|
||||
|
|
@ -172,25 +179,36 @@ class CmdEcho(default_cmds.MuxCommand):
|
|||
The above version will have the echoes arrive one after another, each separated by a two second
|
||||
delay.
|
||||
|
||||
> echo Hello!
|
||||
... HELLO!
|
||||
... Hello!
|
||||
... hello! ...
|
||||
- **Line 19**: This sets off the chain, telling Evennia to wait 2 seconds before calling `self.echo1`.
|
||||
- **Line 22**: This is called after 2 seconds. It tells Evennia to wait another 2 seconds before calling `self.echo2`.
|
||||
- **Line 28**: This is called after yet another 2 seonds (4s total). It tells Evennia to wait another 2 seconds before calling, `self.echo3`.
|
||||
- **Line34** Called after another 2 seconds (6s total). This ends the delay-chain.
|
||||
|
||||
## Blocking commands
|
||||
```
|
||||
> echo Hello!
|
||||
... HELLO!
|
||||
... Hello!
|
||||
... hello! ...
|
||||
```
|
||||
|
||||
As mentioned, a great thing about the delay introduced by `yield` or `utils.delay()` is that it does
|
||||
not block. It just goes on in the background and you are free to play normally in the interim. In
|
||||
some cases this is not what you want however. Some commands should simply "block" other commands
|
||||
while they are running. If you are in the process of crafting a helmet you shouldn't be able to also
|
||||
start crafting a shield at the same time, or if you just did a huge power-swing with your weapon you
|
||||
should not be able to do it again immediately.
|
||||
```{warning} What about time.sleep?
|
||||
|
||||
The simplest way of implementing blocking is to use the technique covered in the [](Howto-Command-Cooldown.md) tutorial. In that tutorial we implemented cooldowns by having the
|
||||
Command store the current time. Next time the Command was called, we compared the current time to
|
||||
the stored time to determine if enough time had passed for a renewed use. This is a *very*
|
||||
efficient, reliable and passive solution. The drawback is that there is nothing to tell the Player
|
||||
when enough time has passed unless they keep trying.
|
||||
You may be aware of the `time.sleep` function coming with Python. Doing `time.sleep(10) pauses Python for 10 seconds. **Do not use this**, it will not work with Evennia. If you use it, you will block the _entire server_ (everyone!) for ten seconds!
|
||||
|
||||
If you want specifics, `utils.delay` is a thin wrapper around a [Twisted Deferred](https://docs.twisted.org/en/twisted-22.1.0/core/howto/defer.html). This is an [asynchronous concept](../Concepts/Async-Process.md).
|
||||
```
|
||||
|
||||
## Making a blocking command
|
||||
|
||||
Both `yield` or `utils.delay()` pauses the command but allows the user to use other commands while the first one waits to finish.
|
||||
|
||||
In some cases you want to instead have that command 'block' other commands from running. An example is crafting a helmet: most likely you should not be able to start crafting a shield at the same time. Or even walk out of the smithy.
|
||||
|
||||
The simplest way of implementing blocking is to use the technique covered in the [How to implement a Command Cooldown](./Howto-Command-Cooldown.md) tutorial. In that tutorial we cooldowns are implemented by comparing the current time with the last time the command was used. This is the best approach if you can get away with it. It could work well for our crafting example ... _if_ you don't want to automatically update the player on their progress.
|
||||
|
||||
In short:
|
||||
- If you are fine with the player making an active input to check their status, compare timestamps as done in the Command-cooldown tutorial. On-demand is by far the most efficent.
|
||||
- If you want Evennia to tell the user their status without them taking a further action, you need to use `yield` , `delay` (or some other active time-keeping method).
|
||||
|
||||
Here is an example where we will use `utils.delay` to tell the player when the cooldown has passed:
|
||||
|
||||
|
|
@ -238,11 +256,9 @@ Note how, after the cooldown, the user will get a message telling them they are
|
|||
another swing.
|
||||
|
||||
By storing the `off_balance` flag on the character (rather than on, say, the Command instance
|
||||
itself) it can be accessed by other Commands too. Other attacks may also not work when you are off
|
||||
balance. You could also have an enemy Command check your `off_balance` status to gain bonuses, to
|
||||
take another example.
|
||||
itself) it can be accessed by other Commands too. Other attacks may also not work when you are off balance. You could also have an enemy Command check your `off_balance` status to gain bonuses, to take another example.
|
||||
|
||||
## Abortable commands
|
||||
## Make a Command possible to Abort
|
||||
|
||||
One can imagine that you will want to abort a long-running command before it has a time to finish.
|
||||
If you are in the middle of crafting your armor you will probably want to stop doing that when a
|
||||
|
|
@ -344,59 +360,4 @@ class CmdAttack(default_cmds.MuxCommand):
|
|||
|
||||
The above code creates a delayed crafting command that will gradually create the armour. If the
|
||||
`attack` command is issued during this process it will set a flag that causes the crafting to be
|
||||
quietly canceled next time it tries to update.
|
||||
|
||||
## Persistent delays
|
||||
|
||||
In the latter examples above we used `.ndb` storage. This is fast and easy but it will reset all
|
||||
cooldowns/blocks/crafting etc if you reload the server. If you don't want that you can replace
|
||||
`.ndb` with `.db`. But even this won't help because the `yield` keyword is not persisent and nor is
|
||||
the use of `delay` shown above. To resolve this you can use `delay` with the `persistent=True`
|
||||
keyword. But wait! Making something persistent will add some extra complications, because now you
|
||||
must make sure Evennia can properly store things to the database.
|
||||
|
||||
Here is the original echo-command reworked to function with persistence:
|
||||
```python
|
||||
from evennia import default_cmds, utils
|
||||
|
||||
# this is now in the outermost scope and takes two args!
|
||||
def echo(caller, args):
|
||||
"Called after 10 seconds."
|
||||
shout = args
|
||||
caller.msg(
|
||||
f"You hear an echo: {shout.upper()} ... {shout.capitalize()} ... {shout.lower()}"
|
||||
)
|
||||
|
||||
class CmdEcho(default_cmds.MuxCommand):
|
||||
"""
|
||||
wait for an echo
|
||||
|
||||
Usage:
|
||||
echo <string>
|
||||
|
||||
Calls and waits for an echo
|
||||
"""
|
||||
key = "echo"
|
||||
locks = "cmd:all()"
|
||||
|
||||
def func(self):
|
||||
"""
|
||||
This is called at the initial shout.
|
||||
"""
|
||||
self.caller.msg(f"You shout '{self.args}' and wait for an echo ...")
|
||||
# this waits non-blocking for 10 seconds, then calls echo(self.caller, self.args)
|
||||
utils.delay(10, echo, self.caller, self.args, persistent=True) # changes!
|
||||
|
||||
```
|
||||
|
||||
Above you notice two changes:
|
||||
- The callback (`echo`) was moved out of the class and became its own stand-alone function in the
|
||||
outermost scope of the module. It also now takes `caller` and `args` as arguments (it doesn't have
|
||||
access to them directly since this is now a stand-alone function).
|
||||
- `utils.delay` specifies the `echo` function (not `self.echo` - it's no longer a method!) and sends
|
||||
`self.caller` and `self.args` as arguments for it to use. We also set `persistent=True`.
|
||||
|
||||
The reason for this change is because Evennia needs to `pickle` the callback into storage and it
|
||||
cannot do this correctly when the method sits on the command class. Now this behave the same as the
|
||||
first version except if you reload (or even shut down) the server mid-delay it will still fire the
|
||||
callback when the server comes back up (it will resume the countdown and ignore the downtime).
|
||||
quietly canceled next time it tries to update.
|
||||
|
|
@ -1,24 +1,26 @@
|
|||
# Command Prompt
|
||||
# Adding a Command Prompt
|
||||
|
||||
A *prompt* is quite common in MUDs:
|
||||
|
||||
A *prompt* is quite common in MUDs. The prompt display useful details about your character that you
|
||||
are likely to want to keep tabs on at all times, such as health, magical power etc. It might also
|
||||
show things like in-game time, weather and so on. Many modern MUD clients (including Evennia's own
|
||||
webclient) allows for identifying the prompt and have it appear in a correct location (usually just
|
||||
above the input line). Usually it will remain like that until it is explicitly updated.
|
||||
HP: 5, MP: 2, SP: 8
|
||||
>
|
||||
|
||||
## Sending a prompt
|
||||
The prompt display useful details about your character that you are likely to want to keep tabs on at all times. It could be health, magical power, gold and current location. It might also show things like in-game time, weather and so on.
|
||||
|
||||
Traditionally, the prompt (changed or not) was returned with every reply from the server and just displayed on its own line. Many modern MUD clients (including Evennia's own webclient) allows for identifying the prompt and have it appear in a fixed location that gets updated in-place (usually just above the input line).
|
||||
|
||||
## A fixed-location prompt
|
||||
|
||||
A prompt is sent using the `prompt` keyword to the `msg()` method on objects. The prompt will be
|
||||
sent without any line breaks.
|
||||
|
||||
```python
|
||||
self.msg(prompt="HP: 5, MP: 2, SP: 8")
|
||||
self.msg(prompt="HP: 5, MP: 2, SP: 8")
|
||||
```
|
||||
You can combine the sending of normal text with the sending (updating of the prompt):
|
||||
|
||||
```python
|
||||
self.msg("This is a text", prompt="This is a prompt")
|
||||
self.msg("This is a text", prompt="This is a prompt")
|
||||
```
|
||||
|
||||
You can update the prompt on demand, this is normally done using [OOB](../Concepts/OOB.md)-tracking of the relevant
|
||||
|
|
@ -63,18 +65,11 @@ Here is a simple example of the prompt sent/updated from a command class:
|
|||
prompt = f"{hp} HP, {mp} MP, {sp} SP"
|
||||
self.caller.msg(text, prompt=prompt)
|
||||
```
|
||||
## A prompt sent with every command
|
||||
## A prompt with every command
|
||||
|
||||
The prompt sent as described above uses a standard telnet instruction (the Evennia web client gets a
|
||||
special flag). Most MUD telnet clients will understand and allow users to catch this and keep the
|
||||
prompt in place until it updates. So *in principle* you'd not need to update the prompt every
|
||||
command.
|
||||
The prompt sent as described above uses a standard telnet instruction (the Evennia web client gets a special flag). Most MUD telnet clients will understand and allow users to catch this and keep the prompt in place until it updates. So *in principle* you'd not need to update the prompt every command.
|
||||
|
||||
However, with a varying user base it can be unclear which clients are used and which skill level the
|
||||
users have. So sending a prompt with every command is a safe catch-all. You don't need to manually
|
||||
go in and edit every command you have though. Instead you edit the base command class for your
|
||||
custom commands (like `MuxCommand` in your `mygame/commands/command.py` folder) and overload the
|
||||
`at_post_cmd()` hook. This hook is always called *after* the main `func()` method of the Command.
|
||||
However, with a varying user base it can be unclear which clients are used and which skill level the users have. So sending a prompt with every command is a safe catch-all. You don't need to manually go in and edit every command you have though. Instead you edit the base command class for your custom commands (like `MuxCommand` in your `mygame/commands/command.py` folder) and overload the `at_post_cmd()` hook. This hook is always called *after* the main `func()` method of the Command.
|
||||
|
||||
```python
|
||||
from evennia import default_cmds
|
||||
|
|
@ -91,8 +86,7 @@ class MuxCommand(default_cmds.MuxCommand):
|
|||
|
||||
### Modifying default commands
|
||||
|
||||
If you want to add something small like this to Evennia's default commands without modifying them
|
||||
directly the easiest way is to just wrap those with a multiple inheritance to your own base class:
|
||||
If you want to add something small like this to Evennia's default commands without modifying them directly the easiest way is to just wrap those with a multiple inheritance to your own base class:
|
||||
|
||||
```python
|
||||
# in (for example) mygame/commands/mycommands.py
|
||||
|
|
|
|||
|
|
@ -1,36 +1,33 @@
|
|||
# Default Exit Errors
|
||||
# Return custom errors on missing Exits
|
||||
|
||||
Evennia allows for exits to have any name. The command "kitchen" is a valid exit name as well as "jump out the window"
|
||||
or "north". An exit actually consists of two parts: an [Exit Object](../Components/Objects.md) and
|
||||
|
||||
> north
|
||||
Ouch! You bump into a wall!
|
||||
> out
|
||||
But you are already outside ...?
|
||||
|
||||
Evennia allows for exits to have any name. The command "kitchen" is a valid exit name as well as "jump out the window" or "north". An exit actually consists of two parts: an [Exit Object](../Components/Objects.md) and
|
||||
an [Exit Command](../Components/Commands.md) stored on said exit object. The command has the same key and aliases as the
|
||||
exit-object, which is why you can see the exit in the room and just write its name to traverse it.
|
||||
|
||||
So if you try to enter the name of a non-existing exit, Evennia treats is the same way as if you were trying to
|
||||
use a non-existing command:
|
||||
So if you try to enter the name of a non-existing exit, Evennia treats is the same way as if you were trying to use a non-existing command:
|
||||
|
||||
> jump out the window
|
||||
Command 'jump out the window' is not available. Type "help" for help.
|
||||
|
||||
Many games don't need this type of freedom however. They define only the cardinal directions as valid exit names (
|
||||
Evennia's `tunnel` command also offers this functionality). In this case, the error starts to look less logical:
|
||||
Many games don't need this type of freedom. They define only the cardinal directions as valid exit names ( Evennia's `tunnel` command also offers this functionality). In this case, the error starts to look less logical:
|
||||
|
||||
> west
|
||||
Command 'west' is not available. Maybe you meant "set" or "reset"?
|
||||
|
||||
Since we for our particular game *know* that west is an exit direction, it would be better if the error message just
|
||||
told us that we couldn't go there.
|
||||
Since we for our particular game *know* that west is an exit direction, it would be better if the error message just told us that we couldn't go there.
|
||||
|
||||
> west
|
||||
You cannot move west.
|
||||
|
||||
The way to do this is to give Evennia an _alternative_ Command to use when no Exit-Command is found in the room. See [Adding Commands](Beginner-Tutorial/Part1/Beginner-Tutorial-Adding-Commands.md) for more info about the process of adding new Commands to Evennia.
|
||||
|
||||
## Adding default error commands
|
||||
|
||||
The way to do this is to give Evennia an _alternative_ Command to use when no Exit-Command is found
|
||||
in the room. See [Adding Commands](Beginner-Tutorial/Part1/Beginner-Tutorial-Adding-Commands.md) for more info about the
|
||||
process of adding new Commands to Evennia.
|
||||
|
||||
In this example all we'll do is echo an error message.
|
||||
In this example we will just echo an error message, but you could do everything (maybe you lose health if you bump into a wall?)
|
||||
|
||||
```python
|
||||
# for example in a file mygame/commands/movecommands.py
|
||||
|
|
@ -75,9 +72,7 @@ class MovementFailCmdSet(CmdSet):
|
|||
self.add(CmdExitErrorSouth())
|
||||
```
|
||||
|
||||
We pack our commands in a new little cmdset; if we add this to our
|
||||
`CharacterCmdSet`, we can just add more errors to `MovementFailCmdSet`
|
||||
later without having to change code in two places.
|
||||
We pack our commands in a new little cmdset; if we add this to our `CharacterCmdSet`, we can just add more errors to `MovementFailCmdSet` later without having to change code in two places.
|
||||
|
||||
```python
|
||||
# in mygame/commands/default_cmdsets.py
|
||||
|
|
@ -93,15 +88,12 @@ class CharacterCmdSet(default_cmds.CharacterCmdSet):
|
|||
self.add(movecommands.MovementFailCmdSet)
|
||||
```
|
||||
|
||||
`reload` the server. What happens henceforth is that if you are in a room with an Exitobject (let's say it's "north"),
|
||||
the proper Exit-command will _overload_ your error command (also named "north"). But if you enter a direction without
|
||||
having a matching exit for it, you will fall back to your default error commands:
|
||||
`reload` the server. What happens henceforth is that if you are in a room with an Exitobject (let's say it's "north"), the proper Exit-command will _overload_ your error command (also named "north"). But if you enter a direction without having a matching exit for it, you will fall back to your default error commands:
|
||||
|
||||
> east
|
||||
You cannot move east.
|
||||
|
||||
Further expansions by the exit system (including manipulating the way the Exit command itself is created) can be done by
|
||||
modifying the [Exit typeclass](../Components/Typeclasses.md) directly.
|
||||
Further expansions by the exit system (including manipulating the way the Exit command itself is created) can be done by modifying the [Exit typeclass](../Components/Typeclasses.md) directly.
|
||||
|
||||
## Why not a single command?
|
||||
|
||||
|
|
@ -118,13 +110,8 @@ class CmdExitError(default_cmds.MuxCommand):
|
|||
#[...]
|
||||
```
|
||||
|
||||
The reason is that this would *not* work. Understanding why is important.
|
||||
This would *not* work the way we want. Understanding why is important.
|
||||
|
||||
Evennia's [command system](../Components/Commands.md) compares commands by key and/or aliases. If _any_ key or alias
|
||||
match, the two commands are considered _identical_. When the cmdsets merge, priority will then decide which of these
|
||||
'identical' commandss replace which.
|
||||
Evennia's [command system](../Components/Commands.md) compares commands by key and/or aliases. If _any_ key or alias match, the two commands are considered _identical_. When the cmdsets merge, priority will then decide which of these 'identical' commandss replace which.
|
||||
|
||||
So the above example would work fine as long as there were _no Exits at all_ in the room. But when we enter
|
||||
a room with an exit "north", its Exit-command (which has a higher priority) will override the single `CmdExitError`
|
||||
with its alias 'north'. So the `CmdExitError` will be gone and while "north" will work, we'll again get the normal
|
||||
"Command not recognized" error for the other directions.
|
||||
So the above example would work fine as long as there were _no Exits at all_ in the room. But when we enter a room with an exit "north", its Exit-command (which has a higher priority) will override the single `CmdExitError` with its alias 'north'. So the `CmdExitError` will be gone and while "north" will work, we'll again get the normal "Command not recognized" error for the other directions.
|
||||
|
|
@ -5,8 +5,7 @@ All Evennia tutorials. They will often refer to the [components](../Components/C
|
|||
## Beginner Tutorial
|
||||
|
||||
Recommended starting point! This will take you from absolute beginner to making
|
||||
a small, but full, game with Evennia. Even if you have a very different game style
|
||||
in mind for your own game, this will give you a good start.
|
||||
a small but full game with Evennia. Other tutorials and howto's tend to assume you are already familiar with the concepts explained in the Beginning tutorial.
|
||||
|
||||
> The latter parts of the beginner tutorial are still being worked on.
|
||||
|
||||
|
|
@ -20,25 +19,26 @@ in mind for your own game, this will give you a good start.
|
|||
./Beginner-Tutorial/Part5/Beginner-Tutorial-Part5-Intro
|
||||
```
|
||||
|
||||
|
||||
## Howto's
|
||||
|
||||
```{toctree}
|
||||
:maxdepth: 1
|
||||
:maxdepth: 2
|
||||
|
||||
Howto-Command-Prompt.md
|
||||
Howto-Command-Cooldown.md
|
||||
Howto-Command-Duration.md
|
||||
Howto-Default-Exit-Errors.md
|
||||
|
||||
Howto-Add-Object-Weight.md
|
||||
```
|
||||
## Mobs and NPCs
|
||||
|
||||
```{toctree}
|
||||
:maxdepth: 1
|
||||
|
||||
Tutorial-NPCs-listening.md
|
||||
Tutorial-Aggressive-NPCs.md
|
||||
NPC-shop-Tutorial.md
|
||||
Tutorial-NPC-Listening.md
|
||||
Tutorial-NPC-Reacting.md
|
||||
Tutorial-NPC-Merchants.md
|
||||
```
|
||||
|
||||
## Vehicles
|
||||
|
|
@ -56,14 +56,11 @@ Tutorial-Vehicles.md
|
|||
|
||||
Tutorial-Persistent-Handler.md
|
||||
Gametime-Tutorial.md
|
||||
Mass-and-weight-for-objects.md
|
||||
Weather-Tutorial.md
|
||||
Tutorial-Coordinates.md
|
||||
Dynamic-In-Game-Map.md
|
||||
Static-In-Game-Map.md
|
||||
Arxcode-Installation.md
|
||||
Tutorial-Tweeting-Game-Stats.md
|
||||
|
||||
```
|
||||
|
||||
## Web-related tutorials
|
||||
|
|
@ -87,6 +84,7 @@ Tutorial-Understanding-Color-Tags.md
|
|||
Evennia-for-roleplaying-sessions.md
|
||||
Evennia-for-Diku-Users.md
|
||||
Evennia-for-MUSH-Users.md
|
||||
Arxcode-Installation.md
|
||||
```
|
||||
|
||||
## Old tutorials
|
||||
|
|
|
|||
|
|
@ -1,98 +0,0 @@
|
|||
# Mass and weight for objects
|
||||
|
||||
|
||||
An easy addition to add dynamic variety to your world objects is to give them some mass. Why mass
|
||||
and not weight? Weight varies in setting; for example things on the Moon weigh 1/6 as much. On
|
||||
Earth's surface and in most environments, no relative weight factor is needed.
|
||||
|
||||
In most settings, mass can be used as weight to spring a pressure plate trap or a floor giving way,
|
||||
determine a character's burden weight for travel speed... The total mass of an object can
|
||||
contribute to the force of a weapon swing, or a speeding meteor to give it a potential striking
|
||||
force.
|
||||
|
||||
## Objects
|
||||
|
||||
Now that we have reasons for keeping track of object mass, let's look at the default object class
|
||||
inside your mygame/typeclasses/objects.py and see how easy it is to total up mass from an object and
|
||||
its contents.
|
||||
|
||||
```python
|
||||
# inside your mygame/typeclasses/objects.py
|
||||
|
||||
class Object(DefaultObject):
|
||||
# [...]
|
||||
def get_mass(self):
|
||||
mass = self.attributes.get('mass', 1) # Default objects have 1 unit mass.
|
||||
return mass + sum(obj.get_mass() for obj in self.contents)
|
||||
```
|
||||
|
||||
Adding the `get_mass` definition to the objects you want to sum up the masses for is done with
|
||||
Python's "sum" function which operates on all the contents, in this case by summing them to
|
||||
return a total mass value.
|
||||
|
||||
If you only wanted specific object types to have mass or have the new object type in a different
|
||||
module, see [[Adding-Object-Typeclass-Tutorial]] with its Heavy class object. You could set the
|
||||
default for Heavy types to something much larger than 1 gram or whatever unit you want to use. Any
|
||||
non-default mass would be stored on the `mass` [[Attributes]] of the objects.
|
||||
|
||||
|
||||
## Characters and rooms
|
||||
|
||||
You can add a `get_mass` definition to characters and rooms, also.
|
||||
|
||||
If you were in a one metric-ton elevator with four other friends also wearing armor and carrying
|
||||
gold bricks, you might wonder if this elevator's going to move, and how fast.
|
||||
|
||||
Assuming the unit is grams and the elevator itself weights 1,000 kilograms, it would already be
|
||||
`@set elevator/mass=1000000`, we're `@set me/mass=85000` and our armor is `@set armor/mass=50000`.
|
||||
We're each carrying 20 gold bars each `@set gold bar/mass=12400` then step into the elevator and see
|
||||
the following message in the elevator's appearance: `Elevator weight and contents should not exceed
|
||||
3 metric tons.` Are we safe? Maybe not if you consider dynamic loading. But at rest:
|
||||
|
||||
```python
|
||||
# Elevator object knows when it checks itself:
|
||||
if self.get_mass() < 3000000:
|
||||
pass # Elevator functions as normal.
|
||||
else:
|
||||
pass # Danger! Alarm sounds, cable snaps, elevator stops...
|
||||
```
|
||||
|
||||
## Inventory
|
||||
Example of listing mass of items in your inventory:
|
||||
|
||||
```python
|
||||
class CmdInventory(MuxCommand):
|
||||
"""
|
||||
view inventory
|
||||
Usage:
|
||||
inventory
|
||||
inv
|
||||
Switches:
|
||||
/weight to display all available channels.
|
||||
Shows your inventory: carrying, wielding, wearing, obscuring.
|
||||
"""
|
||||
|
||||
key = "inventory"
|
||||
aliases = ["inv", "i"]
|
||||
locks = "cmd:all()"
|
||||
|
||||
def func(self):
|
||||
"check inventory"
|
||||
items = self.caller.contents
|
||||
if not items:
|
||||
string = "You are not carrying anything."
|
||||
else:
|
||||
table = prettytable.PrettyTable(["name", "desc"])
|
||||
table.header = False
|
||||
table.border = False
|
||||
for item in items:
|
||||
second = item.get_mass() \
|
||||
if "weight" in self.switches else item.db.desc
|
||||
table.add_row([
|
||||
str(item.get_display_name(self.caller.sessions)),
|
||||
second and second or "",
|
||||
])
|
||||
string = f"|wYou are carrying:\n{table}"
|
||||
self.caller.msg(string)
|
||||
|
||||
```
|
||||
|
|
@ -1,334 +0,0 @@
|
|||
# NPC shop Tutorial
|
||||
|
||||
This tutorial will describe how to make an NPC-run shop. We will make use of the [EvMenu](../Components/EvMenu.md)
|
||||
system to present shoppers with a menu where they can buy things from the store's stock.
|
||||
|
||||
Our shop extends over two rooms - a "front" room open to the shop's customers and a locked "store
|
||||
room" holding the wares the shop should be able to sell. We aim for the following features:
|
||||
|
||||
- The front room should have an Attribute `storeroom` that points to the store room.
|
||||
- Inside the front room, the customer should have a command `buy` or `browse`. This will open a
|
||||
menu listing all items available to buy from the store room.
|
||||
- A customer should be able to look at individual items before buying.
|
||||
- We use "gold" as an example currency. To determine cost, the system will look for an Attribute
|
||||
`gold_value` on the items in the store room. If not found, a fixed base value of 1 will be assumed.
|
||||
The wealth of the customer should be set as an Attribute `gold` on the Character. If not set, they
|
||||
have no gold and can't buy anything.
|
||||
- When the customer makes a purchase, the system will check the `gold_value` of the goods and
|
||||
compare it to the `gold` Attribute of the customer. If enough gold is available, this will be
|
||||
deducted and the goods transferred from the store room to the inventory of the customer.
|
||||
- We will lock the store room so that only people with the right key can get in there.
|
||||
|
||||
## The shop menu
|
||||
|
||||
We want to show a menu to the customer where they can list, examine and buy items in the store. This
|
||||
menu should change depending on what is currently for sale. Evennia's *EvMenu* utility will manage
|
||||
the menu for us. It's a good idea to [read up on EvMenu](../Components/EvMenu.md) if you are not familiar with it.
|
||||
|
||||
### Designing the menu
|
||||
|
||||
The shopping menu's design is straightforward. First we want the main screen. You get this when you
|
||||
enter a shop and use the `browse` or `buy` command:
|
||||
|
||||
```
|
||||
*** Welcome to ye Old Sword shop! ***
|
||||
Things for sale (choose 1-3 to inspect, quit to exit):
|
||||
_________________________________________________________
|
||||
1. A rusty sword (5 gold)
|
||||
2. A sword with a leather handle (10 gold)
|
||||
3. Excalibur (100 gold)
|
||||
```
|
||||
|
||||
There are only three items to buy in this example but the menu should expand to however many items
|
||||
are needed. When you make a selection you will get a new screen showing the options for that
|
||||
particular item:
|
||||
|
||||
```
|
||||
You inspect A rusty sword:
|
||||
|
||||
This is an old weapon maybe once used by soldiers in some
|
||||
long forgotten army. It is rusty and in bad condition.
|
||||
__________________________________________________________
|
||||
1. Buy A rusty sword (5 gold)
|
||||
2. Look for something else.
|
||||
```
|
||||
|
||||
Finally, when you buy something, a brief message should pop up:
|
||||
|
||||
```
|
||||
You pay 5 gold and purchase A rusty sword!
|
||||
```
|
||||
or
|
||||
```
|
||||
You cannot afford 5 gold for A rusty sword!
|
||||
```
|
||||
After this you should be back to the top level of the shopping menu again and can continue browsing.
|
||||
|
||||
### Coding the menu
|
||||
|
||||
EvMenu defines the *nodes* (each menu screen with options) as normal Python functions. Each node
|
||||
must be able to change on the fly depending on what items are currently for sale. EvMenu will
|
||||
automatically make the `quit` command available to us so we won't add that manually. For compactness
|
||||
we will put everything needed for our shop in one module, `mygame/typeclasses/npcshop.py`.
|
||||
|
||||
```python
|
||||
# mygame/typeclasses/npcshop.py
|
||||
|
||||
from evennia.utils import evmenu
|
||||
|
||||
def menunode_shopfront(caller):
|
||||
"This is the top-menu screen."
|
||||
|
||||
shopname = caller.location.key
|
||||
wares = caller.location.db.storeroom.contents
|
||||
|
||||
# Wares includes all items inside the storeroom, including the
|
||||
# door! Let's remove that from our for sale list.
|
||||
wares = [ware for ware in wares if ware.key.lower() != "door"]
|
||||
|
||||
text = f"*** Welcome to {shopname}! ***\n"
|
||||
if wares:
|
||||
text += f" Things for sale (choose 1-{len(wares)} to inspect); quit to exit:"
|
||||
else:
|
||||
text += " There is nothing for sale; quit to exit."
|
||||
|
||||
options = []
|
||||
for ware in wares:
|
||||
# add an option for every ware in store
|
||||
gold_val = ware.db.gold_value or 1
|
||||
options.append({"desc": f"{ware.key} ({gold_val} gold)",
|
||||
"goto": "menunode_inspect_and_buy"})
|
||||
return text, options
|
||||
```
|
||||
|
||||
In this code we assume the caller to be *inside* the shop when accessing the menu. This means we can
|
||||
access the shop room via `caller.location` and get its `key` to display as the shop's name. We also
|
||||
assume the shop has an Attribute `storeroom` we can use to get to our stock. We loop over our goods
|
||||
to build up the menu's options.
|
||||
|
||||
Note that *all options point to the same menu node* called `menunode_inspect_and_buy`! We can't know
|
||||
which goods will be available to sale so we rely on this node to modify itself depending on the
|
||||
circumstances. Let's create it now.
|
||||
|
||||
```python
|
||||
# further down in mygame/typeclasses/npcshop.py
|
||||
|
||||
def menunode_inspect_and_buy(caller, raw_string):
|
||||
"Sets up the buy menu screen."
|
||||
|
||||
wares = caller.location.db.storeroom.contents
|
||||
# Don't forget, we will need to remove that pesky door again!
|
||||
wares = [ware for ware in wares if ware.key.lower() != "door"]
|
||||
iware = int(raw_string) - 1
|
||||
ware = wares[iware]
|
||||
value = ware.db.gold_value or 1
|
||||
wealth = caller.db.gold or 0
|
||||
text = f"You inspect {ware.key}:\n\n{ware.db.desc}"
|
||||
|
||||
def buy_ware_result(caller):
|
||||
"This will be executed first when choosing to buy."
|
||||
if wealth >= value:
|
||||
rtext = f"You pay {value} gold and purchase {ware.key}!"
|
||||
caller.db.gold -= value
|
||||
ware.move_to(caller, quiet=True, move_type="buy")
|
||||
else:
|
||||
rtext = f"You cannot afford {value} gold for {ware.key}!"
|
||||
caller.msg(rtext)
|
||||
|
||||
gold_val = ware.db.gold_value or 1
|
||||
options = ({
|
||||
"desc": f"Buy {ware.key} for {gold_val} gold",
|
||||
"goto": "menunode_shopfront",
|
||||
"exec": buy_ware_result,
|
||||
}, {
|
||||
"desc": "Look for something else",
|
||||
"goto": "menunode_shopfront",
|
||||
})
|
||||
|
||||
return text, options
|
||||
```
|
||||
|
||||
In this menu node we make use of the `raw_string` argument to the node. This is the text the menu
|
||||
user entered on the *previous* node to get here. Since we only allow numbered options in our menu,
|
||||
`raw_input` must be an number for the player to get to this point. So we convert it to an integer
|
||||
index (menu lists start from 1, whereas Python indices always starts at 0, so we need to subtract
|
||||
1). We then use the index to get the corresponding item from storage.
|
||||
|
||||
We just show the customer the `desc` of the item. In a more elaborate setup you might want to show
|
||||
things like weapon damage and special stats here as well.
|
||||
|
||||
When the user choose the "buy" option, EvMenu will execute the `exec` instruction *before* we go
|
||||
back to the top node (the `goto` instruction). For this we make a little inline function
|
||||
`buy_ware_result`. EvMenu will call the function given to `exec` like any menu node but it does not
|
||||
need to return anything. In `buy_ware_result` we determine if the customer can afford the cost and
|
||||
give proper return messages. This is also where we actually move the bought item into the inventory
|
||||
of the customer.
|
||||
|
||||
### The command to start the menu
|
||||
|
||||
We could *in principle* launch the shopping menu the moment a customer steps into our shop room, but
|
||||
this would probably be considered pretty annoying. It's better to create a [Command](../Components/Commands.md) for
|
||||
customers to explicitly wanting to shop around.
|
||||
|
||||
```python
|
||||
# mygame/typeclasses/npcshop.py
|
||||
|
||||
from evennia import Command
|
||||
|
||||
class CmdBuy(Command):
|
||||
"""
|
||||
Start to do some shopping
|
||||
|
||||
Usage:
|
||||
buy
|
||||
shop
|
||||
browse
|
||||
|
||||
This will allow you to browse the wares of the
|
||||
current shop and buy items you want.
|
||||
"""
|
||||
key = "buy"
|
||||
aliases = ("shop", "browse")
|
||||
|
||||
def func(self):
|
||||
"Starts the shop EvMenu instance"
|
||||
evmenu.EvMenu(self.caller,
|
||||
"typeclasses.npcshop",
|
||||
startnode="menunode_shopfront")
|
||||
```
|
||||
|
||||
This will launch the menu. The `EvMenu` instance is initialized with the path to this very module -
|
||||
since the only global functions available in this module are our menu nodes, this will work fine
|
||||
(you could also have put those in a separate module). We now just need to put this command in a
|
||||
[CmdSet](../Components/Command-Sets.md) so we can add it correctly to the game:
|
||||
|
||||
```python
|
||||
from evennia import CmdSet
|
||||
|
||||
class ShopCmdSet(CmdSet):
|
||||
def at_cmdset_creation(self):
|
||||
self.add(CmdBuy())
|
||||
```
|
||||
|
||||
## Building the shop
|
||||
|
||||
There are really only two things that separate our shop from any other Room:
|
||||
|
||||
- The shop has the `storeroom` Attribute set on it, pointing to a second (completely normal) room.
|
||||
- It has the `ShopCmdSet` stored on itself. This makes the `buy` command available to users entering
|
||||
the shop.
|
||||
|
||||
For testing we could easily add these features manually to a room using `@py` or other admin
|
||||
commands. Just to show how it can be done we'll instead make a custom [Typeclass](../Components/Typeclasses.md) for
|
||||
the shop room and make a small command that builders can use to build both the shop and the
|
||||
storeroom at once.
|
||||
|
||||
```python
|
||||
# bottom of mygame/typeclasses/npcshop.py
|
||||
|
||||
from evennia import DefaultRoom, DefaultExit, DefaultObject
|
||||
from evennia.utils.create import create_object
|
||||
|
||||
# class for our front shop room
|
||||
class NPCShop(DefaultRoom):
|
||||
def at_object_creation(self):
|
||||
# we could also use add(ShopCmdSet, persistent=True)
|
||||
self.cmdset.add_default(ShopCmdSet)
|
||||
self.db.storeroom = None
|
||||
|
||||
# command to build a complete shop (the Command base class
|
||||
# should already have been imported earlier in this file)
|
||||
class CmdBuildShop(Command):
|
||||
"""
|
||||
Build a new shop
|
||||
|
||||
Usage:
|
||||
@buildshop shopname
|
||||
|
||||
This will create a new NPCshop room
|
||||
as well as a linked store room (named
|
||||
simply <storename>-storage) for the
|
||||
wares on sale. The store room will be
|
||||
accessed through a locked door in
|
||||
the shop.
|
||||
"""
|
||||
key = "@buildshop"
|
||||
locks = "cmd:perm(Builders)"
|
||||
help_category = "Builders"
|
||||
|
||||
def func(self):
|
||||
"Create the shop rooms"
|
||||
if not self.args:
|
||||
self.msg("Usage: @buildshop <storename>")
|
||||
return
|
||||
# create the shop and storeroom
|
||||
shopname = self.args.strip()
|
||||
shop = create_object(NPCShop,
|
||||
key=shopname,
|
||||
location=None)
|
||||
storeroom = create_object(DefaultRoom,
|
||||
key=f"{shopname}-storage",
|
||||
location=None)
|
||||
shop.db.storeroom = storeroom
|
||||
# create a door between the two
|
||||
shop_exit = create_object(DefaultExit,
|
||||
key="back door",
|
||||
aliases=["storage", "store room"],
|
||||
location=shop,
|
||||
destination=storeroom)
|
||||
storeroom_exit = create_object(DefaultExit,
|
||||
key="door",
|
||||
location=storeroom,
|
||||
destination=shop)
|
||||
# make a key for accessing the store room
|
||||
storeroom_key_name = f"{shopname}-storekey"
|
||||
storeroom_key = create_object(DefaultObject,
|
||||
key=storeroom_key_name,
|
||||
location=shop)
|
||||
# only allow chars with this key to enter the store room
|
||||
shop_exit.locks.add(f"traverse:holds({storeroom_key_name})")
|
||||
|
||||
# inform the builder about progress
|
||||
self.caller.msg(f"The shop {shop} was created!")
|
||||
```
|
||||
|
||||
Our typeclass is simple and so is our `buildshop` command. The command (which is for Builders only)
|
||||
just takes the name of the shop and builds the front room and a store room to go with it (always
|
||||
named `"<shopname>-storage"`. It connects the rooms with a two-way exit. You need to add
|
||||
`CmdBuildShop` [to the default cmdset](Starting/Adding-Command-Tutorial#step-2-adding-the-command-to-a-
|
||||
default-cmdset) before you can use it. Once having created the shop you can now `@teleport` to it or
|
||||
`@open` a new exit to it. You could also easily expand the above command to automatically create
|
||||
exits to and from the new shop from your current location.
|
||||
|
||||
To avoid customers walking in and stealing everything, we create a [Lock](../Components/Locks.md) on the storage
|
||||
door. It's a simple lock that requires the one entering to carry an object named
|
||||
`<shopname>-storekey`. We even create such a key object and drop it in the shop for the new shop
|
||||
keeper to pick up.
|
||||
|
||||
> If players are given the right to name their own objects, this simple lock is not very secure and
|
||||
you need to come up with a more robust lock-key solution.
|
||||
|
||||
> We don't add any descriptions to all these objects so looking "at" them will not be too thrilling.
|
||||
You could add better default descriptions as part of the `@buildshop` command or leave descriptions
|
||||
this up to the Builder.
|
||||
|
||||
## The shop is open for business!
|
||||
|
||||
We now have a functioning shop and an easy way for Builders to create it. All you need now is to
|
||||
`@open` a new exit from the rest of the game into the shop and put some sell-able items in the store
|
||||
room. Our shop does have some shortcomings:
|
||||
|
||||
- For Characters to be able to buy stuff they need to also have the `gold` Attribute set on
|
||||
themselves.
|
||||
- We manually remove the "door" exit from our items for sale. But what if there are other unsellable
|
||||
items in the store room? What if the shop owner walks in there for example - anyone in the store
|
||||
could then buy them for 1 gold.
|
||||
- What if someone else were to buy the item we're looking at just before we decide to buy it? It
|
||||
would then be gone and the counter be wrong - the shop would pass us the next item in the list.
|
||||
|
||||
Fixing these issues are left as an exercise.
|
||||
|
||||
If you want to keep the shop fully NPC-run you could add a [Script](../Components/Scripts.md) to restock the shop's
|
||||
store room regularly. This shop example could also easily be owned by a human Player (run for them
|
||||
by a hired NPC) - the shop owner would get the key to the store room and be responsible for keeping
|
||||
it well stocked.
|
||||
|
|
@ -412,5 +412,5 @@ easily new game defining features can be added to Evennia.
|
|||
|
||||
You can easily build from this tutorial by expanding the map and creating more rooms to explore. Why
|
||||
not add more features to your game by trying other tutorials: [Add weather to your world](Weather-
|
||||
Tutorial), [fill your world with NPC's](./Tutorial-Aggressive-NPCs.md) or
|
||||
Tutorial), [fill your world with NPC's](./Tutorial-NPC-Reacting.md) or
|
||||
[implement a combat system](./Turn-based-Combat-System.md).
|
||||
|
|
|
|||
|
|
@ -1,126 +0,0 @@
|
|||
# Tutorial Aggressive NPCs
|
||||
|
||||
|
||||
This tutorial shows the implementation of an NPC object that responds to characters entering their
|
||||
location. In this example the NPC has the option to respond aggressively or not, but any actions
|
||||
could be triggered this way.
|
||||
|
||||
One could imagine using a [Script](../Components/Scripts.md) that is constantly checking for newcomers. This would be
|
||||
highly inefficient (most of the time its check would fail). Instead we handle this on-demand by
|
||||
using a couple of existing object hooks to inform the NPC that a Character has entered.
|
||||
|
||||
It is assumed that you already know how to create custom room and character typeclasses, please see
|
||||
the [Basic Game tutorial](./Tutorial-for-basic-MUSH-like-game.md) if you haven't already done this.
|
||||
|
||||
What we will need is the following:
|
||||
|
||||
- An NPC typeclass that can react when someone enters.
|
||||
- A custom [Room](../Components/Objects.md#rooms) typeclass that can tell the NPC that someone entered.
|
||||
- We will also tweak our default `Character` typeclass a little.
|
||||
|
||||
To begin with, we need to create an NPC typeclass. Create a new file inside of your typeclasses
|
||||
folder and name it `npcs.py` and then add the following code:
|
||||
|
||||
```python
|
||||
from typeclasses.characters import Character
|
||||
|
||||
class NPC(Character):
|
||||
"""
|
||||
A NPC typeclass which extends the character class.
|
||||
"""
|
||||
def at_char_entered(self, character):
|
||||
"""
|
||||
A simple is_aggressive check.
|
||||
Can be expanded upon later.
|
||||
"""
|
||||
if self.db.is_aggressive:
|
||||
self.execute_cmd(f"say Graaah, die {character}!")
|
||||
else:
|
||||
self.execute_cmd(f"say Greetings, {character}!")
|
||||
```
|
||||
|
||||
We will define our custom `Character` typeclass below. As for the new `at_char_entered` method we've
|
||||
just defined, we'll ensure that it will be called by the room where the NPC is located, when a
|
||||
player enters that room. You'll notice that right now, the NPC merely speaks. You can expand this
|
||||
part as you like and trigger all sorts of effects here (like combat code, fleeing, bartering or
|
||||
quest-giving) as your game design dictates.
|
||||
|
||||
Now your `typeclasses.rooms` module needs to have the following added:
|
||||
|
||||
```python
|
||||
# Add this import to the top of your file.
|
||||
from evennia import utils
|
||||
|
||||
# Add this hook in any empty area within your Room class.
|
||||
def at_object_receive(self, obj, source_location):
|
||||
if utils.inherits_from(obj, 'typeclasses.npcs.NPC'): # An NPC has entered
|
||||
return
|
||||
elif utils.inherits_from(obj, 'typeclasses.characters.Character'):
|
||||
# A PC has entered.
|
||||
# Cause the player's character to look around.
|
||||
obj.execute_cmd('look')
|
||||
for item in self.contents:
|
||||
if utils.inherits_from(item, 'typeclasses.npcs.NPC'):
|
||||
# An NPC is in the room
|
||||
item.at_char_entered(obj)
|
||||
```
|
||||
|
||||
`inherits_from` must be given the full path of the class. If the object inherited a class from your
|
||||
`world.races` module, then you would check inheritance with `world.races.Human`, for example. There
|
||||
is no need to import these prior, as we are passing in the full path. As a matter of a fact,
|
||||
`inherits_from` does not properly work if you import the class and only pass in the name of the
|
||||
class.
|
||||
|
||||
> Note:
|
||||
[at_object_receive](https://github.com/evennia/evennia/blob/master/evennia/objects/objects.py#L1529)
|
||||
is a default hook of the `DefaultObject` typeclass (and its children). Here we are overriding this
|
||||
hook in our customized room typeclass to suit our needs.
|
||||
|
||||
This room checks the typeclass of objects entering it (using `utils.inherits_from` and responds to
|
||||
`Characters`, ignoring other NPCs or objects. When triggered the room will look through its
|
||||
contents and inform any `NPCs inside by calling their `at_char_entered` method.
|
||||
|
||||
You'll also see that we have added a 'look' into this code. This is because, by default, the
|
||||
`at_object_receive` is carried out *before* the character's `at_post_move` which, we will now
|
||||
overload. This means that a character entering would see the NPC perform its actions before the
|
||||
'look' command. Deactivate the look command in the default `Character` class within the
|
||||
`typeclasses.characters` module:
|
||||
|
||||
```python
|
||||
# Add this hook in any blank area within your Character class.
|
||||
def at_post_move(self, source_location):
|
||||
"""
|
||||
Default is to look around after a move
|
||||
Note: This has been moved to Room.at_object_receive
|
||||
"""
|
||||
# self.execute_cmd('look')
|
||||
```
|
||||
|
||||
Now let's create an NPC and make it aggressive. Type the following commands into your MUD client:
|
||||
```
|
||||
reload
|
||||
create/drop Orc:npcs.NPC
|
||||
```
|
||||
|
||||
> Note: You could also give the path as `typeclasses.npcs.NPC`, but Evennia will look into the
|
||||
`typeclasses` folder automatically, so this is a little shorter.
|
||||
|
||||
When you enter the aggressive NPC's location, it will default to using its peaceful action (say your
|
||||
name is Anna):
|
||||
|
||||
```
|
||||
Orc says, "Greetings, Anna!"
|
||||
```
|
||||
|
||||
Now we turn on the aggressive mode (we do it manually but it could also be triggered by some sort of
|
||||
AI code).
|
||||
|
||||
```
|
||||
set orc/is_aggressive = True
|
||||
```
|
||||
|
||||
Now it will perform its aggressive action whenever a character enters.
|
||||
|
||||
```
|
||||
Orc says, "Graaah, die, Anna!"
|
||||
```
|
||||
|
|
@ -1,19 +1,16 @@
|
|||
# Tutorial NPCs listening
|
||||
# NPCs that listen to what is said
|
||||
|
||||
> say hi
|
||||
You say, "hi"
|
||||
The troll under the bridge answers, "well, well. Hello."
|
||||
|
||||
This tutorial shows the implementation of an NPC object that responds to characters speaking in
|
||||
their location. In this example the NPC parrots what is said, but any actions could be triggered
|
||||
this way.
|
||||
|
||||
It is assumed that you already know how to create custom room and character typeclasses, please see
|
||||
the [Basic Game tutorial](./Tutorial-for-basic-MUSH-like-game.md) if you haven't already done this.
|
||||
|
||||
What we will need is simply a new NPC typeclass that can react when someone speaks.
|
||||
This howto explains how to make an NPC that reacts to characters speaking in their current location. The principle applies to other situations, such as enemies joining a fight or reacting to a character drawing a weapon.
|
||||
|
||||
```python
|
||||
# mygame/typeclasses/npc.py
|
||||
|
||||
from characters import Character
|
||||
|
||||
class Npc(Character):
|
||||
"""
|
||||
A NPC typeclass which extends the character class.
|
||||
|
|
@ -32,11 +29,18 @@ class Npc(Character):
|
|||
return f"{from_obj} said: '{message}'"
|
||||
```
|
||||
|
||||
We add a simple method `at_heard_say` that formats what it hears. We assume that the message that enters it is on the form `Someone says, "Hello"`, and we make sure to only get `Hello` in that example.
|
||||
|
||||
We are not actually calling `at_heard_say` yet. We'll handle that next.
|
||||
|
||||
When someone in the room speaks to this NPC, its `msg` method will be called. We will modify the
|
||||
NPCs `.msg` method to catch says so the NPC can respond.
|
||||
|
||||
|
||||
```python
|
||||
```{code-block} python
|
||||
:linenos:
|
||||
:emphasize-lines:
|
||||
|
||||
# mygame/typeclasses/npc.py
|
||||
|
||||
from characters import Character
|
||||
|
|
@ -70,26 +74,15 @@ class Npc(Character):
|
|||
So if the NPC gets a say and that say is not coming from the NPC itself, it will echo it using the
|
||||
`at_heard_say` hook. Some things of note in the above example:
|
||||
|
||||
- The `text` input can be on many different forms depending on where this `msg` is called from.
|
||||
Instead of trying to analyze `text` in detail with a range of `if` statements we just assume the
|
||||
form we want and catch the error if it does not match. This simplifies the code considerably. It's
|
||||
called 'leap before you look' and is a Python paradigm that may feel unfamiliar if you are used to
|
||||
other languages. Here we 'swallow' the error silently, which is fine when the code checked is
|
||||
simple. If not we may want to import `evennia.logger.log_trace` and add `log_trace()` in the
|
||||
`except` clause.
|
||||
- We use `execute_cmd` to fire the `say` command back. We could also have called
|
||||
`self.location.msg_contents` directly but using the Command makes sure all hooks are called (so
|
||||
those seeing the NPC's `say` can in turn react if they want).
|
||||
- Note the comments about `super` at the end. This will trigger the 'default' `msg` (in the parent
|
||||
class) as well. It's not really necessary as long as no one puppets the NPC (by `@ic <npcname>`) but
|
||||
it's wise to keep in there since the puppeting player will be totally blind if `msg()` is never
|
||||
returning anything to them!
|
||||
- **Line 15** The `text` input can be on many different forms depending on where this `msg` is called from. If you look at the [code of the 'say' command](evennia.commands.default.general.CmdSay) you'd find that it will call `.msg` with `("Hello", {"type": "say"})`. We use this knowledge to figure out if this comes from a `say` or not.
|
||||
- **Line 24**: We use `execute_cmd` to fire the NPCs own `say` command back. This works because the NPC is actually a child of `DefaultCharacter` - so it has the `CharacterCmdSet` on it! Normally you should use `execute_cmd` only sparingly; it's usually more efficient to call the actual code used by the Command directly. For this tutorial, invoking the command is shorter to write while making sure all hooks are called
|
||||
- **Line26**: Note the comments about `super` at the end. This will trigger the 'default' `msg` (in the parent class) as well. It's not really necessary as long as no one puppets the NPC (by `@ic <npcname>`) but it's wise to keep in there since the puppeting player will be totally blind if `msg()` is never returning anything to them!
|
||||
|
||||
Now that's done, let's create an NPC and see what it has to say for itself.
|
||||
|
||||
```
|
||||
@reload
|
||||
@create/drop Guild Master:npc.Npc
|
||||
reload
|
||||
create/drop Guild Master:npc.Npc
|
||||
```
|
||||
|
||||
(you could also give the path as `typeclasses.npc.Npc`, but Evennia will look into the `typeclasses`
|
||||
|
|
@ -106,5 +99,4 @@ There are many ways to implement this kind of functionality. An alternative exam
|
|||
sending to an NPC and call the `at_heard_say` hook directly.
|
||||
|
||||
While the tutorial solution has the advantage of being contained only within the NPC class,
|
||||
combining this with using the Character class gives more direct control over how the NPC will react.
|
||||
Which way to go depends on the design requirements of your particular game.
|
||||
combining this with using the Character class gives more direct control over how the NPC will react. Which way to go depends on the design requirements of your particular game.
|
||||
276
docs/1.0-dev/_sources/Howtos/Tutorial-NPC-Merchants.md.txt
Normal file
276
docs/1.0-dev/_sources/Howtos/Tutorial-NPC-Merchants.md.txt
Normal file
|
|
@ -0,0 +1,276 @@
|
|||
# NPC merchants
|
||||
|
||||
```
|
||||
*** Welcome to ye Old Sword shop! ***
|
||||
Things for sale (choose 1-3 to inspect, quit to exit):
|
||||
_________________________________________________________
|
||||
1. A rusty sword (5 gold)
|
||||
2. A sword with a leather handle (10 gold)
|
||||
3. Excalibur (100 gold)
|
||||
```
|
||||
|
||||
This will introduce an NPC able to sell things. In practice this means that when you interact with them you'll get shown a _menu_ of choices. Evennia provides the [EvMenu](../Components/EvMenu.md) utility to easily create in-game menus.
|
||||
|
||||
We will store all the merchant's wares in their inventory. This means that they may stand in an actual shop room, at a market or wander the road. We will also use 'gold' as an example currency.
|
||||
To enter the shop, you'll just need to stand in the same room and use the `buy/shop` command.
|
||||
|
||||
## Making the merchant class
|
||||
|
||||
The merchant will respond to you giving the `shop` or `buy` command in their presence.
|
||||
|
||||
```python
|
||||
# in for example mygame/typeclasses/merchants.py
|
||||
|
||||
from typeclasses.objects import Object
|
||||
from evennia import Command, CmdSet, EvMenu
|
||||
|
||||
class CmdOpenShop(Command):
|
||||
"""
|
||||
Open the shop!
|
||||
|
||||
Usage:
|
||||
shop/buy
|
||||
|
||||
"""
|
||||
key = "shop"
|
||||
aliases = ["buy"]
|
||||
|
||||
def func(self):
|
||||
# this will sit on the Merchant, which is self.obj.
|
||||
# the self.caller is the player wanting to buy stuff.
|
||||
self.obj.open_shop(self.caller)
|
||||
|
||||
|
||||
class MerchantCmdSet(CmdSet):
|
||||
def at_cmdset_creation(self):
|
||||
self.add(CmdOpenShop())
|
||||
|
||||
|
||||
class NPCMerchant(Object):
|
||||
|
||||
def at_object_creation(self):
|
||||
self.cmdset.add_default(MerchantCmdSet)
|
||||
|
||||
def open_shop(self, shopper):
|
||||
menunodes = {} # TODO!
|
||||
shopname = self.db.shopname or "The shop"
|
||||
EvMenu(shopper, menunodes, startnode="shop_start",
|
||||
shopname=shopname, shopkeeper=self, wares=self.contents)
|
||||
|
||||
```
|
||||
|
||||
We could also have put the commands in a separate module, but for compactness, we put it all with the merchant typeclass.
|
||||
|
||||
Note that we make the merchant an `Object`! Since we don't give them any other commands, it makes little sense to let them be a `Character`.
|
||||
|
||||
We make a very simple `shop`/`buy` Command and make sure to add it on the merchant in its own cmdset.
|
||||
|
||||
We initialize `EvMenu` on the `shopper` but we haven't created any `menunodes` yet, so this will not actually do much at this point. It's important that we we pass `shopname`, `shopkeeper` and `wares` into the menu, it means they will be made available as properties on the EvMenu instance - we will be able to access them from inside the menu.
|
||||
|
||||
## Coding the shopping menu
|
||||
|
||||
[EvMenu](../Components/EvMenu.md) splits the menu into _nodes_ represented by Python functions. Each node represents a stop in the menu where the user has to make a choice.
|
||||
|
||||
For simplicity, we'll code the shop interface above the `NPCMerchant` class in the same module.
|
||||
|
||||
The start node of the shop named "ye Old Sword shop!" will look like this if there are only 3 wares to sell:
|
||||
|
||||
```
|
||||
*** Welcome to ye Old Sword shop! ***
|
||||
Things for sale (choose 1-3 to inspect, quit to exit):
|
||||
_________________________________________________________
|
||||
1. A rusty sword (5 gold)
|
||||
2. A sword with a leather handle (10 gold)
|
||||
3. Excalibur (100 gold)
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
# in mygame/typeclasses/merchants.py
|
||||
|
||||
# top of module, above NPCMerchant class.
|
||||
|
||||
def node_shopfront(caller, raw_string, **kwargs):
|
||||
"This is the top-menu screen."
|
||||
|
||||
# made available since we passed them to EvMenu on start
|
||||
menu = caller.ndb._evmenu
|
||||
shopname = menu.shopname
|
||||
shopkeeper = menu.shopkeeper
|
||||
wares = menu.wares
|
||||
|
||||
text = f"*** Welcome to {shopname}! ***\n"
|
||||
if wares:
|
||||
text += f" Things for sale (choose 1-{len(wares)} to inspect); quit to exit:"
|
||||
else:
|
||||
text += " There is nothing for sale; quit to exit."
|
||||
|
||||
options = []
|
||||
for ware in wares:
|
||||
# add an option for every ware in store
|
||||
gold_val = ware.db.gold_value or 1
|
||||
options.append({"desc": f"{ware.key} ({gold_val} gold)",
|
||||
"goto": ("inspect_and_buy",
|
||||
{"selected_ware": ware})
|
||||
})
|
||||
|
||||
return text, options
|
||||
```
|
||||
|
||||
Inside the node we can access the menu on the caller as `caller.ndb._evmenu`. The extra keywords we passed into `EvMenu` are available on this menu instance. Armed with this we can easily present a shop interface. Each option will become a numbered choice on this screen.
|
||||
|
||||
Note how we pass the `ware` with each option and label it `selected_ware`. This will be accessible in the next node's `**kwargs` argument
|
||||
|
||||
If a player choose one of the wares, they should be able to inspect it. Here's how it should look if they selected `1` in ye Old Sword shop:
|
||||
|
||||
```
|
||||
You inspect A rusty sword:
|
||||
|
||||
This is an old weapon maybe once used by soldiers in some
|
||||
long forgotten army. It is rusty and in bad condition.
|
||||
__________________________________________________________
|
||||
1. Buy A rusty sword (5 gold)
|
||||
2. Look for something else.
|
||||
```
|
||||
|
||||
If you buy, you'll see
|
||||
|
||||
```
|
||||
You pay 5 gold and purchase A rusty sword!
|
||||
```
|
||||
or
|
||||
```
|
||||
You cannot afford 5 gold for A rusty sword!
|
||||
```
|
||||
|
||||
Either way you should end up back at the top level of the shopping menu again and can continue browsing or quit the menu with `quit`.
|
||||
|
||||
Here's how it looks in code:
|
||||
|
||||
```python
|
||||
# in mygame/typeclasses/merchants.py
|
||||
|
||||
# right after the other node
|
||||
|
||||
def _buy_item(caller, raw_string, **kwargs):
|
||||
"Called if buyer chooses to buy"
|
||||
selected_ware = kwargs["selected_ware"]
|
||||
value = selected_ware.db.gold_value or 1
|
||||
wealth = caller.db.gold or 0
|
||||
|
||||
if wealth >= value:
|
||||
rtext = f"You pay {value} gold and purchase {ware.key}!"
|
||||
caller.db.gold -= value
|
||||
move_to(caller, quiet=True, move_type="buy")
|
||||
else:
|
||||
rtext = f"You cannot afford {value} gold for {ware.key}!"
|
||||
caller.msg(rtext)
|
||||
# no matter what, we return to the top level of the shop
|
||||
return "shopfront"
|
||||
|
||||
def node_inspect_and_buy(caller, raw_string, **kwargs):
|
||||
"Sets up the buy menu screen."
|
||||
|
||||
# passed from the option we chose
|
||||
selected_ware = kwargs["selected_ware"]
|
||||
|
||||
value = selected_ware.db.gold_value or 1
|
||||
text = f"You inspect {ware.key}:\n\n{ware.db.desc}"
|
||||
gold_val = ware.db.gold_value or 1
|
||||
|
||||
options = ({
|
||||
"desc": f"Buy {ware.key} for {gold_val} gold",
|
||||
"goto": (_buy_item, kwargs)
|
||||
}, {
|
||||
"desc": "Look for something else",
|
||||
"goto": "shopfront",
|
||||
})
|
||||
return text, options
|
||||
```
|
||||
|
||||
In this node we grab the `selected_ware` from `kwargs` - this we pased along from the option on the previous node. We display its description and value. If the user buys, we reroute through the `_buy_item` helper function (this is not a node, it's just a callable that must return the name of the next node to go to.). In `_buy_item` we check if the buyer can affort the ware, and if it can we move it to their inventory. Either way, this method returns `shop_front` as the next node.
|
||||
|
||||
We have been referring to two nodes here: `"shopfront"` and `"inspect_and_buy"` , we should map them to the code in the menu. Scroll down to the `NPCMerchant` class in the same module and find that unfinished `open_shop` method again:
|
||||
|
||||
|
||||
```python
|
||||
# in /mygame/typeclasses/merchants.py
|
||||
|
||||
def node_shopfront(caller, raw_string, **kwargs):
|
||||
# ...
|
||||
|
||||
def _buy_item(caller, raw_string, **kwargs):
|
||||
# ...
|
||||
|
||||
def node_inspect_and_buy(caller, raw_string, **kwargs):
|
||||
# ...
|
||||
|
||||
class NPCMerchant(Object):
|
||||
|
||||
# ...
|
||||
|
||||
def open_shop(self, shopper):
|
||||
menunodes = {
|
||||
"shopfront": node_shopfront,
|
||||
"inspect_and_buy": node_inspect_and_buy
|
||||
}
|
||||
shopname = self.db.shopname or "The shop"
|
||||
EvMenu(shopper, menunodes, startnode="shop_start",
|
||||
shopname=shopname, shopkeeper=self, wares=self.contents)
|
||||
|
||||
```
|
||||
|
||||
|
||||
We now added the nodes to the Evmenu under their right labels. The merchant is now ready!
|
||||
|
||||
|
||||
## The shop is open for business!
|
||||
|
||||
Make sure to `reload`.
|
||||
|
||||
Let's try it out by creating the merchant and a few wares in-game. Remember that we also must create some gold get this economy going.
|
||||
|
||||
```
|
||||
> set self/gold = 8
|
||||
|
||||
> create/drop Stan S. Stanman;stan:typeclasses.merchants.NPCMerchant
|
||||
> set stan/shopname = Stan's previously owned vessles
|
||||
|
||||
> create/drop A proud vessel;ship
|
||||
> set ship/desc = The thing has holes in it.
|
||||
> set ship/gold_value = 5
|
||||
|
||||
> create/drop A classic speedster;rowboat
|
||||
> set rowboat/gold_value = 2
|
||||
> set rowboat/desc = It's not going anywhere fast.
|
||||
```
|
||||
|
||||
Note that a builder without any access to Python code can now set up a personalized merchant with just in-game commands. With the shop all set up, we just need to be in the same room to start consuming!
|
||||
|
||||
```
|
||||
> buy
|
||||
*** Welcome to Stan's previously owned vessels! ***
|
||||
Things for sale (choose 1-3 to inspect, quit to exit):
|
||||
_________________________________________________________
|
||||
1. A proud vessel (5 gold)
|
||||
2. A classic speedster (2 gold)
|
||||
|
||||
> 1
|
||||
|
||||
You inspect A proud vessel:
|
||||
|
||||
The thing has holes in it.
|
||||
__________________________________________________________
|
||||
1. Buy A proud vessel (5 gold)
|
||||
2. Look for something else.
|
||||
|
||||
> 1
|
||||
You pay 5 gold and purchase A proud vessel!
|
||||
|
||||
*** Welcome to Stan's previously owned vessels! ***
|
||||
Things for sale (choose 1-3 to inspect, quit to exit):
|
||||
_________________________________________________________
|
||||
1. A classic speedster (2 gold)
|
||||
|
||||
```
|
||||
|
||||
88
docs/1.0-dev/_sources/Howtos/Tutorial-NPC-Reacting.md.txt
Normal file
88
docs/1.0-dev/_sources/Howtos/Tutorial-NPC-Reacting.md.txt
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
# NPCs reacting to your presence
|
||||
|
||||
|
||||
> north
|
||||
------------------------------------
|
||||
Meadow
|
||||
You are standing in a green meadow.
|
||||
A bandit is here.
|
||||
------------------------------------
|
||||
Bandit gives you a menacing look!
|
||||
|
||||
This tutorial shows the implementation of an NPC object that responds to characters entering their
|
||||
location.
|
||||
|
||||
What we will need is the following:
|
||||
|
||||
- An NPC typeclass that can react when someone enters.
|
||||
- A custom [Room](../Components/Objects.md#rooms) typeclass that can tell the NPC that someone entered.
|
||||
- We will also tweak our default `Character` typeclass a little.
|
||||
|
||||
```python
|
||||
# in mygame/typeclasses/npcs.py (for example)
|
||||
|
||||
from typeclasses.characters import Character
|
||||
|
||||
class NPC(Character):
|
||||
"""
|
||||
A NPC typeclass which extends the character class.
|
||||
"""
|
||||
def at_char_entered(self, character):
|
||||
"""
|
||||
A simple is_aggressive check.
|
||||
Can be expanded upon later.
|
||||
"""
|
||||
if self.db.is_aggressive:
|
||||
self.execute_cmd(f"say Graaah! Die, {character}!")
|
||||
else:
|
||||
self.execute_cmd(f"say Greetings, {character}!")
|
||||
```
|
||||
|
||||
Here we make a simple method on the `NPC`˙. We expect it to be called when a (player-)character enters the room. We don't actually set the `is_aggressive` [Attribute](../Components/Attributes.md) beforehand; if it's not set, the NPC is simply non-hostile.
|
||||
|
||||
Whenever _something_ enters the `Room`, its [at_object_receive](DefaultObject.at_object_receive) hook will be called. So we should override it.
|
||||
|
||||
|
||||
```python
|
||||
# in mygame/typeclasses/rooms.py
|
||||
|
||||
from evennia import utils
|
||||
|
||||
# ...
|
||||
|
||||
class Room(ObjectParent, DefaultRoom):
|
||||
|
||||
# ...
|
||||
|
||||
def at_object_receive(self, arriving_obj, source_location):
|
||||
if arriving_obj.account:
|
||||
# this has an active acccount - a player character
|
||||
for item in self.contents:
|
||||
# get all npcs in the room and inform them
|
||||
if utils.inherits_from(item, "typeclasses.npcs.NPC"):
|
||||
self.at_char_entered(arriving_obj)
|
||||
|
||||
```
|
||||
|
||||
```{sidebar} Universal Object methods
|
||||
Remember that Rooms are `Objects`. So the same `at_object_receive` hook will fire for you when you pick something up (making you 'receive' it). Or for a box when putting something inside it.
|
||||
```
|
||||
A currently puppeted Character will have an `.account` attached to it. We use that to know that the thing arriving is a Character. We then use Evennia's [utils.inherits_from](evennia.utils.utils.inherits_from) helper utility to get every NPC in the room can each of their newly created `at_char_entered` method.
|
||||
|
||||
Make sure to `reload`.
|
||||
|
||||
Let's create an NPC and make it aggressive. For the sake of this example, let's assume your name is "Anna" and that there is a room to the north of your current location.
|
||||
|
||||
> create/drop Orc:typeclasses.npcs.NPC
|
||||
> north
|
||||
> south
|
||||
Orc says, Greetings, Anna!
|
||||
|
||||
Now let's turn the orc aggressive.
|
||||
|
||||
> set orc/is_aggressive = True
|
||||
> north
|
||||
> south
|
||||
Orc says, Graah! Die, Anna!
|
||||
|
||||
That's one easily aggravated Orc!
|
||||
|
|
@ -592,7 +592,7 @@ You can specify the /force switch to bypass this confirmation.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.building.CmdDestroy.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['@delete', '@del']</em><a class="headerlink" href="#evennia.commands.default.building.CmdDestroy.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['@del', '@delete']</em><a class="headerlink" href="#evennia.commands.default.building.CmdDestroy.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -633,7 +633,7 @@ You can specify the /force switch to bypass this confirmation.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.building.CmdDestroy.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': '@delete @del', 'category': 'building', 'key': '@destroy', 'no_prefix': 'destroy delete del', 'tags': '', 'text': '\n permanently delete objects\n\n Usage:\n destroy[/switches] [obj, obj2, obj3, [dbref-dbref], ...]\n\n Switches:\n override - The destroy command will usually avoid accidentally\n destroying account objects. This switch overrides this safety.\n force - destroy without confirmation.\n Examples:\n destroy house, roof, door, 44-78\n destroy 5-10, flower, 45\n destroy/force north\n\n Destroys one or many objects. If dbrefs are used, a range to delete can be\n given, e.g. 4-10. Also the end points will be deleted. This command\n displays a confirmation before destroying, to make sure of your choice.\n You can specify the /force switch to bypass this confirmation.\n '}</em><a class="headerlink" href="#evennia.commands.default.building.CmdDestroy.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': '@del @delete', 'category': 'building', 'key': '@destroy', 'no_prefix': 'destroy del delete', 'tags': '', 'text': '\n permanently delete objects\n\n Usage:\n destroy[/switches] [obj, obj2, obj3, [dbref-dbref], ...]\n\n Switches:\n override - The destroy command will usually avoid accidentally\n destroying account objects. This switch overrides this safety.\n force - destroy without confirmation.\n Examples:\n destroy house, roof, door, 44-78\n destroy 5-10, flower, 45\n destroy/force north\n\n Destroys one or many objects. If dbrefs are used, a range to delete can be\n given, e.g. 4-10. Also the end points will be deleted. This command\n displays a confirmation before destroying, to make sure of your choice.\n You can specify the /force switch to bypass this confirmation.\n '}</em><a class="headerlink" href="#evennia.commands.default.building.CmdDestroy.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -1345,7 +1345,7 @@ server settings.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.building.CmdTypeclass.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['@typeclasses', '@parent', '@type', '@swap', '@update']</em><a class="headerlink" href="#evennia.commands.default.building.CmdTypeclass.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['@swap', '@typeclasses', '@type', '@update', '@parent']</em><a class="headerlink" href="#evennia.commands.default.building.CmdTypeclass.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -1376,7 +1376,7 @@ server settings.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.building.CmdTypeclass.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': '@typeclasses @parent @type @swap @update', 'category': 'building', 'key': '@typeclass', 'no_prefix': 'typeclass typeclasses parent type swap update', 'tags': '', 'text': "\n set or change an object's typeclass\n\n Usage:\n typeclass[/switch] <object> [= typeclass.path]\n typeclass/prototype <object> = prototype_key\n\n typeclasses or typeclass/list/show [typeclass.path]\n swap - this is a shorthand for using /force/reset flags.\n update - this is a shorthand for using the /force/reload flag.\n\n Switch:\n show, examine - display the current typeclass of object (default) or, if\n given a typeclass path, show the docstring of that typeclass.\n update - *only* re-run at_object_creation on this object\n meaning locks or other properties set later may remain.\n reset - clean out *all* the attributes and properties on the\n object - basically making this a new clean object. This will also\n reset cmdsets!\n force - change to the typeclass also if the object\n already has a typeclass of the same name.\n list - show available typeclasses. Only typeclasses in modules actually\n imported or used from somewhere in the code will show up here\n (those typeclasses are still available if you know the path)\n prototype - clean and overwrite the object with the specified\n prototype key - effectively making a whole new object.\n\n Example:\n type button = examples.red_button.RedButton\n type/prototype button=a red button\n\n If the typeclass_path is not given, the current object's typeclass is\n assumed.\n\n View or set an object's typeclass. If setting, the creation hooks of the\n new typeclass will be run on the object. If you have clashing properties on\n the old class, use /reset. By default you are protected from changing to a\n typeclass of the same name as the one you already have - use /force to\n override this protection.\n\n The given typeclass must be identified by its location using python\n dot-notation pointing to the correct module and class. If no typeclass is\n given (or a wrong typeclass is given). Errors in the path or new typeclass\n will lead to the old typeclass being kept. The location of the typeclass\n module is searched from the default typeclass directory, as defined in the\n server settings.\n\n "}</em><a class="headerlink" href="#evennia.commands.default.building.CmdTypeclass.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': '@swap @typeclasses @type @update @parent', 'category': 'building', 'key': '@typeclass', 'no_prefix': 'typeclass swap typeclasses type update parent', 'tags': '', 'text': "\n set or change an object's typeclass\n\n Usage:\n typeclass[/switch] <object> [= typeclass.path]\n typeclass/prototype <object> = prototype_key\n\n typeclasses or typeclass/list/show [typeclass.path]\n swap - this is a shorthand for using /force/reset flags.\n update - this is a shorthand for using the /force/reload flag.\n\n Switch:\n show, examine - display the current typeclass of object (default) or, if\n given a typeclass path, show the docstring of that typeclass.\n update - *only* re-run at_object_creation on this object\n meaning locks or other properties set later may remain.\n reset - clean out *all* the attributes and properties on the\n object - basically making this a new clean object. This will also\n reset cmdsets!\n force - change to the typeclass also if the object\n already has a typeclass of the same name.\n list - show available typeclasses. Only typeclasses in modules actually\n imported or used from somewhere in the code will show up here\n (those typeclasses are still available if you know the path)\n prototype - clean and overwrite the object with the specified\n prototype key - effectively making a whole new object.\n\n Example:\n type button = examples.red_button.RedButton\n type/prototype button=a red button\n\n If the typeclass_path is not given, the current object's typeclass is\n assumed.\n\n View or set an object's typeclass. If setting, the creation hooks of the\n new typeclass will be run on the object. If you have clashing properties on\n the old class, use /reset. By default you are protected from changing to a\n typeclass of the same name as the one you already have - use /force to\n override this protection.\n\n The given typeclass must be identified by its location using python\n dot-notation pointing to the correct module and class. If no typeclass is\n given (or a wrong typeclass is given). Errors in the path or new typeclass\n will lead to the old typeclass being kept. The location of the typeclass\n module is searched from the default typeclass directory, as defined in the\n server settings.\n\n "}</em><a class="headerlink" href="#evennia.commands.default.building.CmdTypeclass.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -1531,7 +1531,7 @@ If object is not specified, the current location is examined.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.building.CmdExamine.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['@ex', '@exam']</em><a class="headerlink" href="#evennia.commands.default.building.CmdExamine.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['@exam', '@ex']</em><a class="headerlink" href="#evennia.commands.default.building.CmdExamine.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -1799,7 +1799,7 @@ the cases, see the module doc.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.building.CmdExamine.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': '@ex @exam', 'category': 'building', 'key': '@examine', 'no_prefix': 'examine ex exam', 'tags': '', 'text': '\n get detailed information about an object\n\n Usage:\n examine [<object>[/attrname]]\n examine [*<account>[/attrname]]\n\n Switch:\n account - examine an Account (same as adding *)\n object - examine an Object (useful when OOC)\n script - examine a Script\n channel - examine a Channel\n\n The examine command shows detailed game info about an\n object and optionally a specific attribute on it.\n If object is not specified, the current location is examined.\n\n Append a * before the search string to examine an account.\n\n '}</em><a class="headerlink" href="#evennia.commands.default.building.CmdExamine.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': '@exam @ex', 'category': 'building', 'key': '@examine', 'no_prefix': 'examine exam ex', 'tags': '', 'text': '\n get detailed information about an object\n\n Usage:\n examine [<object>[/attrname]]\n examine [*<account>[/attrname]]\n\n Switch:\n account - examine an Account (same as adding *)\n object - examine an Object (useful when OOC)\n script - examine a Script\n channel - examine a Channel\n\n The examine command shows detailed game info about an\n object and optionally a specific attribute on it.\n If object is not specified, the current location is examined.\n\n Append a * before the search string to examine an account.\n\n '}</em><a class="headerlink" href="#evennia.commands.default.building.CmdExamine.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -268,7 +268,7 @@ for everyone to use, you need build privileges and the alias command.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.general.CmdNick.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['nickname', 'nicks']</em><a class="headerlink" href="#evennia.commands.default.general.CmdNick.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['nicks', 'nickname']</em><a class="headerlink" href="#evennia.commands.default.general.CmdNick.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -300,7 +300,7 @@ for everyone to use, you need build privileges and the alias command.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.general.CmdNick.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'nickname nicks', 'category': 'general', 'key': 'nick', 'no_prefix': ' nickname nicks', 'tags': '', 'text': '\n define a personal alias/nick by defining a string to\n match and replace it with another on the fly\n\n Usage:\n nick[/switches] <string> [= [replacement_string]]\n nick[/switches] <template> = <replacement_template>\n nick/delete <string> or number\n nicks\n\n Switches:\n inputline - replace on the inputline (default)\n object - replace on object-lookup\n account - replace on account-lookup\n list - show all defined aliases (also "nicks" works)\n delete - remove nick by index in /list\n clearall - clear all nicks\n\n Examples:\n nick hi = say Hello, I\'m Sarah!\n nick/object tom = the tall man\n nick build $1 $2 = create/drop $1;$2\n nick tell $1 $2=page $1=$2\n nick tm?$1=page tallman=$1\n nick tm\\=$1=page tallman=$1\n\n A \'nick\' is a personal string replacement. Use $1, $2, ... to catch arguments.\n Put the last $-marker without an ending space to catch all remaining text. You\n can also use unix-glob matching for the left-hand side <string>:\n\n * - matches everything\n ? - matches 0 or 1 single characters\n [abcd] - matches these chars in any order\n [!abcd] - matches everything not among these chars\n \\= - escape literal \'=\' you want in your <string>\n\n Note that no objects are actually renamed or changed by this command - your nicks\n are only available to you. If you want to permanently add keywords to an object\n for everyone to use, you need build privileges and the alias command.\n\n '}</em><a class="headerlink" href="#evennia.commands.default.general.CmdNick.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'nicks nickname', 'category': 'general', 'key': 'nick', 'no_prefix': ' nicks nickname', 'tags': '', 'text': '\n define a personal alias/nick by defining a string to\n match and replace it with another on the fly\n\n Usage:\n nick[/switches] <string> [= [replacement_string]]\n nick[/switches] <template> = <replacement_template>\n nick/delete <string> or number\n nicks\n\n Switches:\n inputline - replace on the inputline (default)\n object - replace on object-lookup\n account - replace on account-lookup\n list - show all defined aliases (also "nicks" works)\n delete - remove nick by index in /list\n clearall - clear all nicks\n\n Examples:\n nick hi = say Hello, I\'m Sarah!\n nick/object tom = the tall man\n nick build $1 $2 = create/drop $1;$2\n nick tell $1 $2=page $1=$2\n nick tm?$1=page tallman=$1\n nick tm\\=$1=page tallman=$1\n\n A \'nick\' is a personal string replacement. Use $1, $2, ... to catch arguments.\n Put the last $-marker without an ending space to catch all remaining text. You\n can also use unix-glob matching for the left-hand side <string>:\n\n * - matches everything\n ? - matches 0 or 1 single characters\n [abcd] - matches these chars in any order\n [!abcd] - matches everything not among these chars\n \\= - escape literal \'=\' you want in your <string>\n\n Note that no objects are actually renamed or changed by this command - your nicks\n are only available to you. If you want to permanently add keywords to an object\n for everyone to use, you need build privileges and the alias command.\n\n '}</em><a class="headerlink" href="#evennia.commands.default.general.CmdNick.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -323,7 +323,7 @@ inv</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.general.CmdInventory.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['i', 'inv']</em><a class="headerlink" href="#evennia.commands.default.general.CmdInventory.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['inv', 'i']</em><a class="headerlink" href="#evennia.commands.default.general.CmdInventory.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -354,7 +354,7 @@ inv</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.general.CmdInventory.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'i inv', 'category': 'general', 'key': 'inventory', 'no_prefix': ' i inv', 'tags': '', 'text': '\n view inventory\n\n Usage:\n inventory\n inv\n\n Shows your inventory.\n '}</em><a class="headerlink" href="#evennia.commands.default.general.CmdInventory.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'inv i', 'category': 'general', 'key': 'inventory', 'no_prefix': ' inv i', 'tags': '', 'text': '\n view inventory\n\n Usage:\n inventory\n inv\n\n Shows your inventory.\n '}</em><a class="headerlink" href="#evennia.commands.default.general.CmdInventory.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -709,7 +709,7 @@ automatically begin with your name.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.general.CmdPose.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['emote', ':']</em><a class="headerlink" href="#evennia.commands.default.general.CmdPose.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = [':', 'emote']</em><a class="headerlink" href="#evennia.commands.default.general.CmdPose.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -750,7 +750,7 @@ space.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.general.CmdPose.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'emote :', 'category': 'general', 'key': 'pose', 'no_prefix': ' emote :', 'tags': '', 'text': "\n strike a pose\n\n Usage:\n pose <pose text>\n pose's <pose text>\n\n Example:\n pose is standing by the wall, smiling.\n -> others will see:\n Tom is standing by the wall, smiling.\n\n Describe an action being taken. The pose text will\n automatically begin with your name.\n "}</em><a class="headerlink" href="#evennia.commands.default.general.CmdPose.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': ': emote', 'category': 'general', 'key': 'pose', 'no_prefix': ' : emote', 'tags': '', 'text': "\n strike a pose\n\n Usage:\n pose <pose text>\n pose's <pose text>\n\n Example:\n pose is standing by the wall, smiling.\n -> others will see:\n Tom is standing by the wall, smiling.\n\n Describe an action being taken. The pose text will\n automatically begin with your name.\n "}</em><a class="headerlink" href="#evennia.commands.default.general.CmdPose.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -773,7 +773,7 @@ which permission groups you are a member of.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.general.CmdAccess.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['groups', 'hierarchy']</em><a class="headerlink" href="#evennia.commands.default.general.CmdAccess.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['hierarchy', 'groups']</em><a class="headerlink" href="#evennia.commands.default.general.CmdAccess.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -804,7 +804,7 @@ which permission groups you are a member of.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.general.CmdAccess.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'groups hierarchy', 'category': 'general', 'key': 'access', 'no_prefix': ' groups hierarchy', 'tags': '', 'text': '\n show your current game access\n\n Usage:\n access\n\n This command shows you the permission hierarchy and\n which permission groups you are a member of.\n '}</em><a class="headerlink" href="#evennia.commands.default.general.CmdAccess.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'hierarchy groups', 'category': 'general', 'key': 'access', 'no_prefix': ' hierarchy groups', 'tags': '', 'text': '\n show your current game access\n\n Usage:\n access\n\n This command shows you the permission hierarchy and\n which permission groups you are a member of.\n '}</em><a class="headerlink" href="#evennia.commands.default.general.CmdAccess.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
|
|
@ -683,7 +683,7 @@ See <a href="#id11"><span class="problematic" id="id12">|</span></a>luhttps://ww
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.system.CmdTasks.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['@delays', '@task']</em><a class="headerlink" href="#evennia.commands.default.system.CmdTasks.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['@task', '@delays']</em><a class="headerlink" href="#evennia.commands.default.system.CmdTasks.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -729,7 +729,7 @@ to all the variables defined therein.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.system.CmdTasks.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': '@delays @task', 'category': 'system', 'key': '@tasks', 'no_prefix': 'tasks delays task', 'tags': '', 'text': "\n Display or terminate active tasks (delays).\n\n Usage:\n tasks[/switch] [task_id or function_name]\n\n Switches:\n pause - Pause the callback of a task.\n unpause - Process all callbacks made since pause() was called.\n do_task - Execute the task (call its callback).\n call - Call the callback of this task.\n remove - Remove a task without executing it.\n cancel - Stop a task from automatically executing.\n\n Notes:\n A task is a single use method of delaying the call of a function. Calls are created\n in code, using `evennia.utils.delay`.\n See |luhttps://www.evennia.com/docs/latest/Command-Duration.html|ltthe docs|le for help.\n\n By default, tasks that are canceled and never called are cleaned up after one minute.\n\n Examples:\n - `tasks/cancel move_callback` - Cancels all movement delays from the slow_exit contrib.\n In this example slow exits creates it's tasks with\n `utils.delay(move_delay, move_callback)`\n - `tasks/cancel 2` - Cancel task id 2.\n\n "}</em><a class="headerlink" href="#evennia.commands.default.system.CmdTasks.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': '@task @delays', 'category': 'system', 'key': '@tasks', 'no_prefix': 'tasks task delays', 'tags': '', 'text': "\n Display or terminate active tasks (delays).\n\n Usage:\n tasks[/switch] [task_id or function_name]\n\n Switches:\n pause - Pause the callback of a task.\n unpause - Process all callbacks made since pause() was called.\n do_task - Execute the task (call its callback).\n call - Call the callback of this task.\n remove - Remove a task without executing it.\n cancel - Stop a task from automatically executing.\n\n Notes:\n A task is a single use method of delaying the call of a function. Calls are created\n in code, using `evennia.utils.delay`.\n See |luhttps://www.evennia.com/docs/latest/Command-Duration.html|ltthe docs|le for help.\n\n By default, tasks that are canceled and never called are cleaned up after one minute.\n\n Examples:\n - `tasks/cancel move_callback` - Cancels all movement delays from the slow_exit contrib.\n In this example slow exits creates it's tasks with\n `utils.delay(move_delay, move_callback)`\n - `tasks/cancel 2` - Cancel task id 2.\n\n "}</em><a class="headerlink" href="#evennia.commands.default.system.CmdTasks.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
|
|
@ -902,7 +902,7 @@ main test suite started with</p>
|
|||
<p>Test the batch processor.</p>
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.tests.TestBatchProcess.red_button">
|
||||
<code class="sig-name descname">red_button</code><em class="property"> = <module 'evennia.contrib.tutorials.red_button.red_button' from '/tmp/tmpetopgdxv/ba9ba34cd61c07c8a77381803c025c11cf345b21/evennia/contrib/tutorials/red_button/red_button.py'></em><a class="headerlink" href="#evennia.commands.default.tests.TestBatchProcess.red_button" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">red_button</code><em class="property"> = <module 'evennia.contrib.tutorials.red_button.red_button' from '/tmp/tmp5j5rru7h/a15a8ae42888846c44f33882b196663ac29d8cb3/evennia/contrib/tutorials/red_button/red_button.py'></em><a class="headerlink" href="#evennia.commands.default.tests.TestBatchProcess.red_button" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py method">
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ connect “account name” “pass word”</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.unloggedin.CmdUnconnectedConnect.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['conn', 'con', 'co']</em><a class="headerlink" href="#evennia.commands.default.unloggedin.CmdUnconnectedConnect.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['con', 'conn', 'co']</em><a class="headerlink" href="#evennia.commands.default.unloggedin.CmdUnconnectedConnect.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -157,7 +157,7 @@ there is no object yet before the account has logged in)</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.unloggedin.CmdUnconnectedConnect.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'conn con co', 'category': 'general', 'key': 'connect', 'no_prefix': ' conn con co', 'tags': '', 'text': '\n connect to the game\n\n Usage (at login screen):\n connect accountname password\n connect "account name" "pass word"\n\n Use the create command to first create an account before logging in.\n\n If you have spaces in your name, enclose it in double quotes.\n '}</em><a class="headerlink" href="#evennia.commands.default.unloggedin.CmdUnconnectedConnect.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'con conn co', 'category': 'general', 'key': 'connect', 'no_prefix': ' con conn co', 'tags': '', 'text': '\n connect to the game\n\n Usage (at login screen):\n connect accountname password\n connect "account name" "pass word"\n\n Use the create command to first create an account before logging in.\n\n If you have spaces in your name, enclose it in double quotes.\n '}</em><a class="headerlink" href="#evennia.commands.default.unloggedin.CmdUnconnectedConnect.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -181,7 +181,7 @@ create “account name” “pass word”</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.unloggedin.CmdUnconnectedCreate.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['cre', 'cr']</em><a class="headerlink" href="#evennia.commands.default.unloggedin.CmdUnconnectedCreate.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['cr', 'cre']</em><a class="headerlink" href="#evennia.commands.default.unloggedin.CmdUnconnectedCreate.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -212,7 +212,7 @@ create “account name” “pass word”</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.unloggedin.CmdUnconnectedCreate.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'cre cr', 'category': 'general', 'key': 'create', 'no_prefix': ' cre cr', 'tags': '', 'text': '\n create a new account account\n\n Usage (at login screen):\n create <accountname> <password>\n create "account name" "pass word"\n\n This creates a new account account.\n\n If you have spaces in your name, enclose it in double quotes.\n '}</em><a class="headerlink" href="#evennia.commands.default.unloggedin.CmdUnconnectedCreate.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'cr cre', 'category': 'general', 'key': 'create', 'no_prefix': ' cr cre', 'tags': '', 'text': '\n create a new account account\n\n Usage (at login screen):\n create <accountname> <password>\n create "account name" "pass word"\n\n This creates a new account account.\n\n If you have spaces in your name, enclose it in double quotes.\n '}</em><a class="headerlink" href="#evennia.commands.default.unloggedin.CmdUnconnectedCreate.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -286,7 +286,7 @@ All it does is display the connect screen.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.unloggedin.CmdUnconnectedLook.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['look', 'l']</em><a class="headerlink" href="#evennia.commands.default.unloggedin.CmdUnconnectedLook.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['l', 'look']</em><a class="headerlink" href="#evennia.commands.default.unloggedin.CmdUnconnectedLook.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -312,7 +312,7 @@ All it does is display the connect screen.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.commands.default.unloggedin.CmdUnconnectedLook.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'look l', 'category': 'general', 'key': '__unloggedin_look_command', 'no_prefix': ' look l', 'tags': '', 'text': '\n look when in unlogged-in state\n\n Usage:\n look\n\n This is an unconnected version of the look command for simplicity.\n\n This is called by the server and kicks everything in gear.\n All it does is display the connect screen.\n '}</em><a class="headerlink" href="#evennia.commands.default.unloggedin.CmdUnconnectedLook.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'l look', 'category': 'general', 'key': '__unloggedin_look_command', 'no_prefix': ' l look', 'tags': '', 'text': '\n look when in unlogged-in state\n\n Usage:\n look\n\n This is an unconnected version of the look command for simplicity.\n\n This is called by the server and kicks everything in gear.\n All it does is display the connect screen.\n '}</em><a class="headerlink" href="#evennia.commands.default.unloggedin.CmdUnconnectedLook.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ the module given by settings.CONNECTION_SCREEN_MODULE.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedConnect.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['conn', 'con', 'co']</em><a class="headerlink" href="#evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedConnect.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['con', 'conn', 'co']</em><a class="headerlink" href="#evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedConnect.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -169,7 +169,7 @@ there is no object yet before the account has logged in)</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedConnect.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'conn con co', 'category': 'general', 'key': 'connect', 'no_prefix': ' conn con co', 'tags': '', 'text': '\n Connect to the game.\n\n Usage (at login screen):\n connect <email> <password>\n\n Use the create command to first create an account before logging in.\n '}</em><a class="headerlink" href="#evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedConnect.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'con conn co', 'category': 'general', 'key': 'connect', 'no_prefix': ' con conn co', 'tags': '', 'text': '\n Connect to the game.\n\n Usage (at login screen):\n connect <email> <password>\n\n Use the create command to first create an account before logging in.\n '}</em><a class="headerlink" href="#evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedConnect.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -191,7 +191,7 @@ there is no object yet before the account has logged in)</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedCreate.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['cre', 'cr']</em><a class="headerlink" href="#evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedCreate.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['cr', 'cre']</em><a class="headerlink" href="#evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedCreate.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -227,7 +227,7 @@ name enclosed in quotes:</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedCreate.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'cre cr', 'category': 'general', 'key': 'create', 'no_prefix': ' cre cr', 'tags': '', 'text': '\n Create a new account.\n\n Usage (at login screen):\n create "accountname" <email> <password>\n\n This creates a new account account.\n\n '}</em><a class="headerlink" href="#evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedCreate.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'cr cre', 'category': 'general', 'key': 'create', 'no_prefix': ' cr cre', 'tags': '', 'text': '\n Create a new account.\n\n Usage (at login screen):\n create "accountname" <email> <password>\n\n This creates a new account account.\n\n '}</em><a class="headerlink" href="#evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedCreate.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -291,7 +291,7 @@ All it does is display the connect screen.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedLook.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['look', 'l']</em><a class="headerlink" href="#evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedLook.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['l', 'look']</em><a class="headerlink" href="#evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedLook.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -317,7 +317,7 @@ All it does is display the connect screen.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedLook.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'look l', 'category': 'general', 'key': '__unloggedin_look_command', 'no_prefix': ' look l', 'tags': '', 'text': '\n This is an unconnected version of the `look` command for simplicity.\n\n This is called by the server and kicks everything in gear.\n All it does is display the connect screen.\n '}</em><a class="headerlink" href="#evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedLook.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'l look', 'category': 'general', 'key': '__unloggedin_look_command', 'no_prefix': ' l look', 'tags': '', 'text': '\n This is an unconnected version of the `look` command for simplicity.\n\n This is called by the server and kicks everything in gear.\n All it does is display the connect screen.\n '}</em><a class="headerlink" href="#evennia.contrib.base_systems.email_login.email_login.CmdUnconnectedLook.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.base_systems.ingame_python.commands.CmdCallback.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['@callback', '@calls', '@callbacks']</em><a class="headerlink" href="#evennia.contrib.base_systems.ingame_python.commands.CmdCallback.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['@callback', '@callbacks', '@calls']</em><a class="headerlink" href="#evennia.contrib.base_systems.ingame_python.commands.CmdCallback.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -197,7 +197,7 @@ on user permission.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.base_systems.ingame_python.commands.CmdCallback.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': '@callback @calls @callbacks', 'category': 'building', 'key': '@call', 'no_prefix': 'call callback calls callbacks', 'tags': '', 'text': '\n Command to edit callbacks.\n '}</em><a class="headerlink" href="#evennia.contrib.base_systems.ingame_python.commands.CmdCallback.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': '@callback @callbacks @calls', 'category': 'building', 'key': '@call', 'no_prefix': 'call callback callbacks calls', 'tags': '', 'text': '\n Command to edit callbacks.\n '}</em><a class="headerlink" href="#evennia.contrib.base_systems.ingame_python.commands.CmdCallback.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ for that channel.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.base_systems.mux_comms_cmds.mux_comms_cmds.CmdDelCom.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['delchanalias', 'delaliaschan']</em><a class="headerlink" href="#evennia.contrib.base_systems.mux_comms_cmds.mux_comms_cmds.CmdDelCom.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['delaliaschan', 'delchanalias']</em><a class="headerlink" href="#evennia.contrib.base_systems.mux_comms_cmds.mux_comms_cmds.CmdDelCom.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -248,7 +248,7 @@ for that channel.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.base_systems.mux_comms_cmds.mux_comms_cmds.CmdDelCom.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'delchanalias delaliaschan', 'category': 'comms', 'key': 'delcom', 'no_prefix': ' delchanalias delaliaschan', 'tags': '', 'text': "\n remove a channel alias and/or unsubscribe from channel\n\n Usage:\n delcom <alias or channel>\n delcom/all <channel>\n\n If the full channel name is given, unsubscribe from the\n channel. If an alias is given, remove the alias but don't\n unsubscribe. If the 'all' switch is used, remove all aliases\n for that channel.\n "}</em><a class="headerlink" href="#evennia.contrib.base_systems.mux_comms_cmds.mux_comms_cmds.CmdDelCom.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'delaliaschan delchanalias', 'category': 'comms', 'key': 'delcom', 'no_prefix': ' delaliaschan delchanalias', 'tags': '', 'text': "\n remove a channel alias and/or unsubscribe from channel\n\n Usage:\n delcom <alias or channel>\n delcom/all <channel>\n\n If the full channel name is given, unsubscribe from the\n channel. If an alias is given, remove the alias but don't\n unsubscribe. If the 'all' switch is used, remove all aliases\n for that channel.\n "}</em><a class="headerlink" href="#evennia.contrib.base_systems.mux_comms_cmds.mux_comms_cmds.CmdDelCom.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ the operation will be general or on the room.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.full_systems.evscaperoom.commands.CmdGiveUp.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['quit', 'chicken out', 'q', 'abort']</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdGiveUp.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['abort', 'quit', 'chicken out', 'q']</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdGiveUp.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py method">
|
||||
|
|
@ -235,7 +235,7 @@ set in self.parse())</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.full_systems.evscaperoom.commands.CmdGiveUp.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'quit chicken out q abort', 'category': 'evscaperoom', 'key': 'give up', 'no_prefix': ' quit chicken out q abort', 'tags': '', 'text': '\n Give up\n\n Usage:\n give up\n\n Abandons your attempts at escaping and of ever winning the pie-eating contest.\n\n '}</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdGiveUp.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'abort quit chicken out q', 'category': 'evscaperoom', 'key': 'give up', 'no_prefix': ' abort quit chicken out q', 'tags': '', 'text': '\n Give up\n\n Usage:\n give up\n\n Abandons your attempts at escaping and of ever winning the pie-eating contest.\n\n '}</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdGiveUp.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -371,7 +371,7 @@ shout</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.full_systems.evscaperoom.commands.CmdSpeak.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['shout', 'whisper', ';']</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdSpeak.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['shout', ';', 'whisper']</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdSpeak.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -400,7 +400,7 @@ set in self.parse())</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.full_systems.evscaperoom.commands.CmdSpeak.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'shout whisper ;', 'category': 'general', 'key': 'say', 'no_prefix': ' shout whisper ;', 'tags': '', 'text': '\n Perform an communication action.\n\n Usage:\n say <text>\n whisper\n shout\n\n '}</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdSpeak.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'shout ; whisper', 'category': 'general', 'key': 'say', 'no_prefix': ' shout ; whisper', 'tags': '', 'text': '\n Perform an communication action.\n\n Usage:\n say <text>\n whisper\n shout\n\n '}</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdSpeak.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -428,7 +428,7 @@ emote /me points to /box and /lever.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.full_systems.evscaperoom.commands.CmdEmote.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['pose', ':']</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdEmote.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = [':', 'pose']</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdEmote.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -467,7 +467,7 @@ set in self.parse())</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.full_systems.evscaperoom.commands.CmdEmote.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'pose :', 'category': 'general', 'key': 'emote', 'no_prefix': ' pose :', 'tags': '', 'text': '\n Perform a free-form emote. Use /me to\n include yourself in the emote and /name\n to include other objects or characters.\n Use "..." to enact speech.\n\n Usage:\n emote <emote>\n :<emote\n\n Example:\n emote /me smiles at /peter\n emote /me points to /box and /lever.\n\n '}</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdEmote.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': ': pose', 'category': 'general', 'key': 'emote', 'no_prefix': ' : pose', 'tags': '', 'text': '\n Perform a free-form emote. Use /me to\n include yourself in the emote and /name\n to include other objects or characters.\n Use "..." to enact speech.\n\n Usage:\n emote <emote>\n :<emote\n\n Example:\n emote /me smiles at /peter\n emote /me points to /box and /lever.\n\n '}</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdEmote.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -490,7 +490,7 @@ looks and what actions is available.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.full_systems.evscaperoom.commands.CmdFocus.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['unfocus', 'examine', 'e', 'ex']</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdFocus.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['e', 'ex', 'unfocus', 'examine']</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdFocus.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -519,7 +519,7 @@ set in self.parse())</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.full_systems.evscaperoom.commands.CmdFocus.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'unfocus examine e ex', 'category': 'evscaperoom', 'key': 'focus', 'no_prefix': ' unfocus examine e ex', 'tags': '', 'text': '\n Focus your attention on a target.\n\n Usage:\n focus <obj>\n\n Once focusing on an object, use look to get more information about how it\n looks and what actions is available.\n\n '}</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdFocus.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'e ex unfocus examine', 'category': 'evscaperoom', 'key': 'focus', 'no_prefix': ' e ex unfocus examine', 'tags': '', 'text': '\n Focus your attention on a target.\n\n Usage:\n focus <obj>\n\n Once focusing on an object, use look to get more information about how it\n looks and what actions is available.\n\n '}</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdFocus.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -581,7 +581,7 @@ set in self.parse())</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.full_systems.evscaperoom.commands.CmdGet.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['inv', 'give', 'i', 'inventory']</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdGet.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['inv', 'inventory', 'i', 'give']</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdGet.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py method">
|
||||
|
|
@ -605,7 +605,7 @@ set in self.parse())</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.full_systems.evscaperoom.commands.CmdGet.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'inv give i inventory', 'category': 'evscaperoom', 'key': 'get', 'no_prefix': ' inv give i inventory', 'tags': '', 'text': '\n Use focus / examine instead.\n\n '}</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdGet.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'inv inventory i give', 'category': 'evscaperoom', 'key': 'get', 'no_prefix': ' inv inventory i give', 'tags': '', 'text': '\n Use focus / examine instead.\n\n '}</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdGet.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -626,7 +626,7 @@ set in self.parse())</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.full_systems.evscaperoom.commands.CmdRerouter.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['@dig', '@open']</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdRerouter.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['@open', '@dig']</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdRerouter.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py method">
|
||||
|
|
@ -649,7 +649,7 @@ to all the variables defined therein.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.full_systems.evscaperoom.commands.CmdRerouter.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': '@dig @open', 'category': 'general', 'key': 'open', 'no_prefix': ' dig open', 'tags': '', 'text': '\n Interact with an object in focus.\n\n Usage:\n <action> [arg]\n\n '}</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdRerouter.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': '@open @dig', 'category': 'general', 'key': 'open', 'no_prefix': ' open dig', 'tags': '', 'text': '\n Interact with an object in focus.\n\n Usage:\n <action> [arg]\n\n '}</em><a class="headerlink" href="#evennia.contrib.full_systems.evscaperoom.commands.CmdRerouter.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
|
|
@ -692,7 +692,7 @@ inv</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.game_systems.clothing.clothing.CmdInventory.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['i', 'inv']</em><a class="headerlink" href="#evennia.contrib.game_systems.clothing.clothing.CmdInventory.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['inv', 'i']</em><a class="headerlink" href="#evennia.contrib.game_systems.clothing.clothing.CmdInventory.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -723,7 +723,7 @@ inv</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.game_systems.clothing.clothing.CmdInventory.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'i inv', 'category': 'general', 'key': 'inventory', 'no_prefix': ' i inv', 'tags': '', 'text': '\n view inventory\n\n Usage:\n inventory\n inv\n\n Shows your inventory.\n '}</em><a class="headerlink" href="#evennia.contrib.game_systems.clothing.clothing.CmdInventory.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'inv i', 'category': 'general', 'key': 'inventory', 'no_prefix': ' inv i', 'tags': '', 'text': '\n view inventory\n\n Usage:\n inventory\n inv\n\n Shows your inventory.\n '}</em><a class="headerlink" href="#evennia.contrib.game_systems.clothing.clothing.CmdInventory.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ everyone but the person rolling.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.rpg.dice.dice.CmdDice.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['roll', '@dice']</em><a class="headerlink" href="#evennia.contrib.rpg.dice.dice.CmdDice.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['@dice', 'roll']</em><a class="headerlink" href="#evennia.contrib.rpg.dice.dice.CmdDice.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -331,7 +331,7 @@ everyone but the person rolling.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.rpg.dice.dice.CmdDice.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'roll @dice', 'category': 'general', 'key': 'dice', 'no_prefix': ' roll dice', 'tags': '', 'text': "\n roll dice\n\n Usage:\n dice[/switch] <nr>d<sides> [modifier] [success condition]\n\n Switch:\n hidden - tell the room the roll is being done, but don't show the result\n secret - don't inform the room about neither roll nor result\n\n Examples:\n dice 3d6 + 4\n dice 1d100 - 2 < 50\n\n This will roll the given number of dice with given sides and modifiers.\n So e.g. 2d6 + 3 means to 'roll a 6-sided die 2 times and add the result,\n then add 3 to the total'.\n Accepted modifiers are +, -, * and /.\n A success condition is given as normal Python conditionals\n (<,>,<=,>=,==,!=). So e.g. 2d6 + 3 > 10 means that the roll will succeed\n only if the final result is above 8. If a success condition is given, the\n outcome (pass/fail) will be echoed along with how much it succeeded/failed\n with. The hidden/secret switches will hide all or parts of the roll from\n everyone but the person rolling.\n "}</em><a class="headerlink" href="#evennia.contrib.rpg.dice.dice.CmdDice.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': '@dice roll', 'category': 'general', 'key': 'dice', 'no_prefix': ' dice roll', 'tags': '', 'text': "\n roll dice\n\n Usage:\n dice[/switch] <nr>d<sides> [modifier] [success condition]\n\n Switch:\n hidden - tell the room the roll is being done, but don't show the result\n secret - don't inform the room about neither roll nor result\n\n Examples:\n dice 3d6 + 4\n dice 1d100 - 2 < 50\n\n This will roll the given number of dice with given sides and modifiers.\n So e.g. 2d6 + 3 means to 'roll a 6-sided die 2 times and add the result,\n then add 3 to the total'.\n Accepted modifiers are +, -, * and /.\n A success condition is given as normal Python conditionals\n (<,>,<=,>=,==,!=). So e.g. 2d6 + 3 > 10 means that the roll will succeed\n only if the final result is above 8. If a success condition is given, the\n outcome (pass/fail) will be echoed along with how much it succeeded/failed\n with. The hidden/secret switches will hide all or parts of the roll from\n everyone but the person rolling.\n "}</em><a class="headerlink" href="#evennia.contrib.rpg.dice.dice.CmdDice.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
|
|
@ -865,7 +865,7 @@ Using the command without arguments will list all current recogs.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.rpg.rpsystem.rpsystem.CmdRecog.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['recognize', 'forget']</em><a class="headerlink" href="#evennia.contrib.rpg.rpsystem.rpsystem.CmdRecog.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['forget', 'recognize']</em><a class="headerlink" href="#evennia.contrib.rpg.rpsystem.rpsystem.CmdRecog.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py method">
|
||||
|
|
@ -892,7 +892,7 @@ Using the command without arguments will list all current recogs.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.rpg.rpsystem.rpsystem.CmdRecog.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'recognize forget', 'category': 'general', 'key': 'recog', 'no_prefix': ' recognize forget', 'tags': '', 'text': '\n Recognize another person in the same room.\n\n Usage:\n recog\n recog sdesc as alias\n forget alias\n\n Example:\n recog tall man as Griatch\n forget griatch\n\n This will assign a personal alias for a person, or forget said alias.\n Using the command without arguments will list all current recogs.\n\n '}</em><a class="headerlink" href="#evennia.contrib.rpg.rpsystem.rpsystem.CmdRecog.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'forget recognize', 'category': 'general', 'key': 'recog', 'no_prefix': ' forget recognize', 'tags': '', 'text': '\n Recognize another person in the same room.\n\n Usage:\n recog\n recog sdesc as alias\n forget alias\n\n Example:\n recog tall man as Griatch\n forget griatch\n\n This will assign a personal alias for a person, or forget said alias.\n Using the command without arguments will list all current recogs.\n\n '}</em><a class="headerlink" href="#evennia.contrib.rpg.rpsystem.rpsystem.CmdRecog.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ such as when closing the lid and un-blinding a character.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.red_button.red_button.CmdPushLidClosed.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['press button', 'push', 'press']</em><a class="headerlink" href="#evennia.contrib.tutorials.red_button.red_button.CmdPushLidClosed.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['push', 'press button', 'press']</em><a class="headerlink" href="#evennia.contrib.tutorials.red_button.red_button.CmdPushLidClosed.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -182,7 +182,7 @@ check if the lid is open or closed.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.red_button.red_button.CmdPushLidClosed.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'press button push press', 'category': 'general', 'key': 'push button', 'no_prefix': ' press button push press', 'tags': '', 'text': '\n Push the red button (lid closed)\n\n Usage:\n push button\n\n '}</em><a class="headerlink" href="#evennia.contrib.tutorials.red_button.red_button.CmdPushLidClosed.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'push press button press', 'category': 'general', 'key': 'push button', 'no_prefix': ' push press button press', 'tags': '', 'text': '\n Push the red button (lid closed)\n\n Usage:\n push button\n\n '}</em><a class="headerlink" href="#evennia.contrib.tutorials.red_button.red_button.CmdPushLidClosed.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -252,7 +252,7 @@ check if the lid is open or closed.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.red_button.red_button.CmdSmashGlass.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['break lid', 'smash', 'smash lid']</em><a class="headerlink" href="#evennia.contrib.tutorials.red_button.red_button.CmdSmashGlass.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['smash', 'smash lid', 'break lid']</em><a class="headerlink" href="#evennia.contrib.tutorials.red_button.red_button.CmdSmashGlass.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -279,7 +279,7 @@ break.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.red_button.red_button.CmdSmashGlass.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'break lid smash smash lid', 'category': 'general', 'key': 'smash glass', 'no_prefix': ' break lid smash smash lid', 'tags': '', 'text': '\n Smash the protective glass.\n\n Usage:\n smash glass\n\n Try to smash the glass of the button.\n\n '}</em><a class="headerlink" href="#evennia.contrib.tutorials.red_button.red_button.CmdSmashGlass.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'smash smash lid break lid', 'category': 'general', 'key': 'smash glass', 'no_prefix': ' smash smash lid break lid', 'tags': '', 'text': '\n Smash the protective glass.\n\n Usage:\n smash glass\n\n Try to smash the glass of the button.\n\n '}</em><a class="headerlink" href="#evennia.contrib.tutorials.red_button.red_button.CmdSmashGlass.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -379,7 +379,7 @@ be mutually exclusive.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.red_button.red_button.CmdPushLidOpen.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['press button', 'push', 'press']</em><a class="headerlink" href="#evennia.contrib.tutorials.red_button.red_button.CmdPushLidOpen.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['push', 'press button', 'press']</em><a class="headerlink" href="#evennia.contrib.tutorials.red_button.red_button.CmdPushLidOpen.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -408,7 +408,7 @@ set in self.parse())</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.red_button.red_button.CmdPushLidOpen.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'press button push press', 'category': 'general', 'key': 'push button', 'no_prefix': ' press button push press', 'tags': '', 'text': '\n Push the red button\n\n Usage:\n push button\n\n '}</em><a class="headerlink" href="#evennia.contrib.tutorials.red_button.red_button.CmdPushLidOpen.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'push press button press', 'category': 'general', 'key': 'push button', 'no_prefix': ' push press button press', 'tags': '', 'text': '\n Push the red button\n\n Usage:\n push button\n\n '}</em><a class="headerlink" href="#evennia.contrib.tutorials.red_button.red_button.CmdPushLidOpen.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -506,7 +506,7 @@ be mutually exclusive.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.red_button.red_button.CmdBlindLook.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['get', 'feel', 'listen', 'l', 'examine', 'ex']</em><a class="headerlink" href="#evennia.contrib.tutorials.red_button.red_button.CmdBlindLook.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['ex', 'get', 'listen', 'feel', 'l', 'examine']</em><a class="headerlink" href="#evennia.contrib.tutorials.red_button.red_button.CmdBlindLook.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -532,7 +532,7 @@ be mutually exclusive.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.red_button.red_button.CmdBlindLook.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'get feel listen l examine ex', 'category': 'general', 'key': 'look', 'no_prefix': ' get feel listen l examine ex', 'tags': '', 'text': "\n Looking around in darkness\n\n Usage:\n look <obj>\n\n ... not that there's much to see in the dark.\n\n "}</em><a class="headerlink" href="#evennia.contrib.tutorials.red_button.red_button.CmdBlindLook.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'ex get listen feel l examine', 'category': 'general', 'key': 'look', 'no_prefix': ' ex get listen feel l examine', 'tags': '', 'text': "\n Looking around in darkness\n\n Usage:\n look <obj>\n\n ... not that there's much to see in the dark.\n\n "}</em><a class="headerlink" href="#evennia.contrib.tutorials.red_button.red_button.CmdBlindLook.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
|
|
@ -425,7 +425,7 @@ of the object. We overload it with our own version.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.tutorial_world.objects.CmdLight.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['burn', 'light']</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.objects.CmdLight.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['light', 'burn']</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.objects.CmdLight.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -452,7 +452,7 @@ to sit on a “lightable” object, we operate only on self.obj.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.tutorial_world.objects.CmdLight.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'burn light', 'category': 'tutorialworld', 'key': 'on', 'no_prefix': ' burn light', 'tags': '', 'text': '\n Creates light where there was none. Something to burn.\n '}</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.objects.CmdLight.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'light burn', 'category': 'tutorialworld', 'key': 'on', 'no_prefix': ' light burn', 'tags': '', 'text': '\n Creates light where there was none. Something to burn.\n '}</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.objects.CmdLight.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -556,7 +556,7 @@ shift green root up/down</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.tutorial_world.objects.CmdShiftRoot.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['shiftroot', 'pull', 'push', 'move']</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.objects.CmdShiftRoot.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['push', 'move', 'shiftroot', 'pull']</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.objects.CmdShiftRoot.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -592,7 +592,7 @@ yellow/green - horizontal roots</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.tutorial_world.objects.CmdShiftRoot.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'shiftroot pull push move', 'category': 'tutorialworld', 'key': 'shift', 'no_prefix': ' shiftroot pull push move', 'tags': '', 'text': '\n Shifts roots around.\n\n Usage:\n shift blue root left/right\n shift red root left/right\n shift yellow root up/down\n shift green root up/down\n\n '}</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.objects.CmdShiftRoot.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'push move shiftroot pull', 'category': 'tutorialworld', 'key': 'shift', 'no_prefix': ' push move shiftroot pull', 'tags': '', 'text': '\n Shifts roots around.\n\n Usage:\n shift blue root left/right\n shift red root left/right\n shift yellow root up/down\n shift green root up/down\n\n '}</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.objects.CmdShiftRoot.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -609,7 +609,7 @@ yellow/green - horizontal roots</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.tutorial_world.objects.CmdPressButton.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['press button', 'button', 'push button']</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.objects.CmdPressButton.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['push button', 'press button', 'button']</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.objects.CmdPressButton.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -635,7 +635,7 @@ yellow/green - horizontal roots</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.tutorial_world.objects.CmdPressButton.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'press button button push button', 'category': 'tutorialworld', 'key': 'press', 'no_prefix': ' press button button push button', 'tags': '', 'text': '\n Presses a button.\n '}</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.objects.CmdPressButton.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'push button press button button', 'category': 'tutorialworld', 'key': 'press', 'no_prefix': ' push button press button button', 'tags': '', 'text': '\n Presses a button.\n '}</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.objects.CmdPressButton.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
@ -779,7 +779,7 @@ parry - forgoes your attack but will make you harder to hit on next</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.tutorial_world.objects.CmdAttack.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['bash', 'thrust', 'defend', 'chop', 'hit', 'kill', 'slash', 'stab', 'fight', 'pierce', 'parry']</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.objects.CmdAttack.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['defend', 'thrust', 'fight', 'hit', 'parry', 'stab', 'bash', 'chop', 'slash', 'pierce', 'kill']</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.objects.CmdAttack.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -805,7 +805,7 @@ parry - forgoes your attack but will make you harder to hit on next</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.tutorial_world.objects.CmdAttack.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'bash thrust defend chop hit kill slash stab fight pierce parry', 'category': 'tutorialworld', 'key': 'attack', 'no_prefix': ' bash thrust defend chop hit kill slash stab fight pierce parry', 'tags': '', 'text': '\n Attack the enemy. Commands:\n\n stab <enemy>\n slash <enemy>\n parry\n\n stab - (thrust) makes a lot of damage but is harder to hit with.\n slash - is easier to land, but does not make as much damage.\n parry - forgoes your attack but will make you harder to hit on next\n enemy attack.\n\n '}</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.objects.CmdAttack.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'defend thrust fight hit parry stab bash chop slash pierce kill', 'category': 'tutorialworld', 'key': 'attack', 'no_prefix': ' defend thrust fight hit parry stab bash chop slash pierce kill', 'tags': '', 'text': '\n Attack the enemy. Commands:\n\n stab <enemy>\n slash <enemy>\n parry\n\n stab - (thrust) makes a lot of damage but is harder to hit with.\n slash - is easier to land, but does not make as much damage.\n parry - forgoes your attack but will make you harder to hit on next\n enemy attack.\n\n '}</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.objects.CmdAttack.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
|
|
@ -968,7 +968,7 @@ to find something.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.tutorial_world.rooms.CmdLookDark.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['feel', 'fiddle', 'search', 'l', 'feel around']</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.rooms.CmdLookDark.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['search', 'feel', 'fiddle', 'l', 'feel around']</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.rooms.CmdLookDark.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -996,7 +996,7 @@ random chance of eventually finding a light source.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.tutorials.tutorial_world.rooms.CmdLookDark.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'feel fiddle search l feel around', 'category': 'tutorialworld', 'key': 'look', 'no_prefix': ' feel fiddle search l feel around', 'tags': '', 'text': '\n Look around in darkness\n\n Usage:\n look\n\n Look around in the darkness, trying\n to find something.\n '}</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.rooms.CmdLookDark.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'search feel fiddle l feel around', 'category': 'tutorialworld', 'key': 'look', 'no_prefix': ' search feel fiddle l feel around', 'tags': '', 'text': '\n Look around in darkness\n\n Usage:\n look\n\n Look around in the darkness, trying\n to find something.\n '}</em><a class="headerlink" href="#evennia.contrib.tutorials.tutorial_world.rooms.CmdLookDark.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ git evennia pull - Pull the latest evennia code.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.utils.git_integration.git_integration.CmdGitEvennia.directory">
|
||||
<code class="sig-name descname">directory</code><em class="property"> = '/tmp/tmpetopgdxv/ba9ba34cd61c07c8a77381803c025c11cf345b21/evennia'</em><a class="headerlink" href="#evennia.contrib.utils.git_integration.git_integration.CmdGitEvennia.directory" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">directory</code><em class="property"> = '/tmp/tmp5j5rru7h/a15a8ae42888846c44f33882b196663ac29d8cb3/evennia'</em><a class="headerlink" href="#evennia.contrib.utils.git_integration.git_integration.CmdGitEvennia.directory" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -269,7 +269,7 @@ git pull - Pull the latest code from your current branch.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.contrib.utils.git_integration.git_integration.CmdGit.directory">
|
||||
<code class="sig-name descname">directory</code><em class="property"> = '/tmp/tmpetopgdxv/ba9ba34cd61c07c8a77381803c025c11cf345b21/evennia/game_template'</em><a class="headerlink" href="#evennia.contrib.utils.git_integration.git_integration.CmdGit.directory" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">directory</code><em class="property"> = '/tmp/tmp5j5rru7h/a15a8ae42888846c44f33882b196663ac29d8cb3/evennia/game_template'</em><a class="headerlink" href="#evennia.contrib.utils.git_integration.git_integration.CmdGit.directory" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
|
|||
|
|
@ -336,7 +336,7 @@ indentation.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.utils.eveditor.CmdEditorGroup.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = [':uu', ':>', ':DD', ':S', ':UU', ':x', ':A', ':wq', ':q', ':w', ':I', ':', ':dd', ':fi', ':=', ':!', ':h', '::', ':p', ':r', ':u', ':echo', ':dw', ':::', ':i', ':y', ':f', ':fd', ':j', ':<', ':q!', ':s']</em><a class="headerlink" href="#evennia.utils.eveditor.CmdEditorGroup.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = [':y', ':s', ':!', ':echo', ':wq', ':uu', ':q!', ':h', ':I', ':fd', ':q', ':', ':w', ':DD', ':i', ':x', ':S', ':>', ':u', ':<', '::', ':r', ':dd', ':A', ':j', ':f', ':UU', ':fi', ':p', ':=', ':::', ':dw']</em><a class="headerlink" href="#evennia.utils.eveditor.CmdEditorGroup.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -364,7 +364,7 @@ efficient presentation.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.utils.eveditor.CmdEditorGroup.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': ':uu :> :DD :S :UU :x :A :wq :q :w :I : :dd :fi := :! :h :: :p :r :u :echo :dw ::: :i :y :f :fd :j :< :q! :s', 'category': 'general', 'key': ':editor_command_group', 'no_prefix': ' :uu :> :DD :S :UU :x :A :wq :q :w :I : :dd :fi := :! :h :: :p :r :u :echo :dw ::: :i :y :f :fd :j :< :q! :s', 'tags': '', 'text': '\n Commands for the editor\n '}</em><a class="headerlink" href="#evennia.utils.eveditor.CmdEditorGroup.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': ':y :s :! :echo :wq :uu :q! :h :I :fd :q : :w :DD :i :x :S :> :u :< :: :r :dd :A :j :f :UU :fi :p := ::: :dw', 'category': 'general', 'key': ':editor_command_group', 'no_prefix': ' :y :s :! :echo :wq :uu :q! :h :I :fd :q : :w :DD :i :x :S :> :u :< :: :r :dd :A :j :f :UU :fi :p := ::: :dw', 'tags': '', 'text': '\n Commands for the editor\n '}</em><a class="headerlink" href="#evennia.utils.eveditor.CmdEditorGroup.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
|
|
@ -931,7 +931,7 @@ single question.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.utils.evmenu.CmdYesNoQuestion.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['a', 'n', '__nomatch_command', 'abort', 'yes', 'y', 'no']</em><a class="headerlink" href="#evennia.utils.evmenu.CmdYesNoQuestion.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['yes', 'abort', 'a', 'y', '__nomatch_command', 'no', 'n']</em><a class="headerlink" href="#evennia.utils.evmenu.CmdYesNoQuestion.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -957,7 +957,7 @@ single question.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.utils.evmenu.CmdYesNoQuestion.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'a n __nomatch_command abort yes y no', 'category': 'general', 'key': '__noinput_command', 'no_prefix': ' a n __nomatch_command abort yes y no', 'tags': '', 'text': '\n Handle a prompt for yes or no. Press [return] for the default choice.\n\n '}</em><a class="headerlink" href="#evennia.utils.evmenu.CmdYesNoQuestion.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'yes abort a y __nomatch_command no n', 'category': 'general', 'key': '__noinput_command', 'no_prefix': ' yes abort a y __nomatch_command no n', 'tags': '', 'text': '\n Handle a prompt for yes or no. Press [return] for the default choice.\n\n '}</em><a class="headerlink" href="#evennia.utils.evmenu.CmdYesNoQuestion.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ the <strong>caller.msg()</strong> construct every time the page is updated.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.utils.evmore.CmdMore.aliases">
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['a', 'end', 'quit', 'n', 'e', 'q', 'abort', 't', 'p', 'previous', 'next', 'top']</em><a class="headerlink" href="#evennia.utils.evmore.CmdMore.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">aliases</code><em class="property"> = ['e', 'quit', 'p', 't', 'abort', 'a', 'previous', 'end', 'next', 'q', 'top', 'n']</em><a class="headerlink" href="#evennia.utils.evmore.CmdMore.aliases" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py attribute">
|
||||
|
|
@ -163,7 +163,7 @@ the <strong>caller.msg()</strong> construct every time the page is updated.</p>
|
|||
|
||||
<dl class="py attribute">
|
||||
<dt id="evennia.utils.evmore.CmdMore.search_index_entry">
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'a end quit n e q abort t p previous next top', 'category': 'general', 'key': '__noinput_command', 'no_prefix': ' a end quit n e q abort t p previous next top', 'tags': '', 'text': '\n Manipulate the text paging. Catch no-input with aliases.\n '}</em><a class="headerlink" href="#evennia.utils.evmore.CmdMore.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<code class="sig-name descname">search_index_entry</code><em class="property"> = {'aliases': 'e quit p t abort a previous end next q top n', 'category': 'general', 'key': '__noinput_command', 'no_prefix': ' e quit p t abort a previous end next q top n', 'tags': '', 'text': '\n Manipulate the text paging. Catch no-input with aliases.\n '}</em><a class="headerlink" href="#evennia.utils.evmore.CmdMore.search_index_entry" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
|
|
|||
|
|
@ -215,16 +215,17 @@ or the original github wiki. You have been warned.</p>
|
|||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Howtos/Howtos-Overview.html#howtos">Howto’s</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Howto-Command-Prompt.html">Command Prompt</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Howto-Command-Cooldown.html">Command Cooldown</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Howto-Command-Duration.html">Command Duration</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Howto-Default-Exit-Errors.html">Default Exit Errors</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Howto-Command-Prompt.html">Adding a Command Prompt</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Howto-Command-Cooldown.html">Adding Command Cooldowns</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Howto-Command-Duration.html">Commands that take time to finish</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Howto-Default-Exit-Errors.html">Return custom errors on missing Exits</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Howto-Add-Object-Weight.html">Give objects weight</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Howtos/Howtos-Overview.html#mobs-and-npcs">Mobs and NPCs</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Tutorial-NPCs-listening.html">Tutorial NPCs listening</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Tutorial-Aggressive-NPCs.html">Tutorial Aggressive NPCs</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/NPC-shop-Tutorial.html">NPC shop Tutorial</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Tutorial-NPC-Listening.html">NPCs that listen to what is said</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Tutorial-NPC-Reacting.html">NPCs reacting to your presence</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Tutorial-NPC-Merchants.html">NPC merchants</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Howtos/Howtos-Overview.html#vehicles">Vehicles</a><ul>
|
||||
|
|
@ -235,13 +236,11 @@ or the original github wiki. You have been warned.</p>
|
|||
<li class="toctree-l2"><a class="reference internal" href="Howtos/Howtos-Overview.html#systems">Systems</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Tutorial-Persistent-Handler.html">Making a Persistent object Handler</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Gametime-Tutorial.html">Gametime Tutorial</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Mass-and-weight-for-objects.html">Mass and weight for objects</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Weather-Tutorial.html">Weather Tutorial</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Tutorial-Coordinates.html">Coordinates</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Tutorial-Coordinates.html#adding-room-coordinates-in-your-game">Adding room coordinates in your game</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Dynamic-In-Game-Map.html">Dynamic In Game Map</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Static-In-Game-Map.html">Static In Game Map</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Arxcode-Installation.html">Arxcode installing help</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Tutorial-Tweeting-Game-Stats.html">Tutorial Tweeting Game Stats</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
@ -258,6 +257,7 @@ or the original github wiki. You have been warned.</p>
|
|||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Evennia-for-roleplaying-sessions.html">Evennia for roleplaying sessions</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Evennia-for-Diku-Users.html">Evennia for Diku Users</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Evennia-for-MUSH-Users.html">Evennia for MUSH Users</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="Howtos/Arxcode-Installation.html">Arxcode installing help</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Howtos/Howtos-Overview.html#old-tutorials">Old tutorials</a><ul>
|
||||
|
|
|
|||
Binary file not shown.
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue