evennia/docs/2.x/Howtos/Tutorial-Building-a-Mech.html

323 lines
24 KiB
HTML
Raw Normal View History

<!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/" />
2023-10-19 20:22:27 +00:00
<title>Building a giant mech &#8212; Evennia 2.x 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" />
2022-11-23 20:20:36 +00:00
<link rel="next" title="Building a train that moves" href="Tutorial-Building-a-Train.html" />
2022-11-21 23:18:31 +00:00
<link rel="prev" title="NPC merchants" href="Tutorial-NPC-Merchants.html" />
</head><body>
2023-10-19 20:22:27 +00:00
<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" >
2022-11-23 20:20:36 +00:00
<a href="Tutorial-Building-a-Train.html" title="Building a train that moves"
accesskey="N">next</a> |</li>
<li class="right" >
2022-11-21 23:18:31 +00:00
<a href="Tutorial-NPC-Merchants.html" title="NPC merchants"
accesskey="P">previous</a> |</li>
2023-10-19 20:22:27 +00:00
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 2.x</a> &#187;</li>
2023-12-20 18:20:52 +01:00
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" accesskey="U">Tutorials and Howtos</a> &#187;</li>
2022-11-23 20:20:36 +00:00
<li class="nav-item nav-item-this"><a href="">Building a giant mech</a></li>
</ul>
2023-12-20 18:20:52 +01:00
</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>
2022-11-23 20:20:36 +00:00
<li><a class="reference internal" href="#">Building a giant mech</a><ul>
<li><a class="reference internal" href="#make-a-mech-that-can-shoot">Make a Mech that can shoot</a></li>
<li><a class="reference internal" href="#making-an-army-of-mechs">Making an army of Mechs</a><ul>
<li><a class="reference internal" href="#future-mechs">Future Mechs</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
2022-11-21 23:18:31 +00:00
<p class="topless"><a href="Tutorial-NPC-Merchants.html"
title="previous chapter">NPC merchants</a></p>
<h4>Next topic</h4>
2022-11-23 20:20:36 +00:00
<p class="topless"><a href="Tutorial-Building-a-Train.html"
title="next chapter">Building a train that moves</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
2022-11-23 20:20:36 +00:00
<li><a href="../_sources/Howtos/Tutorial-Building-a-Mech.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
2023-10-19 20:22:27 +00:00
<li><a href="https://www.evennia.com/docs/latest/index.html">Documentation Top</a> </li>
<li><a href="https://www.evennia.com">Evennia Home</a> </li>
<li><a href="https://github.com/evennia/evennia">Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
2022-11-23 20:20:36 +00:00
<section class="tex2jax_ignore mathjax_ignore" id="building-a-giant-mech">
<h1>Building a giant mech<a class="headerlink" href="#building-a-giant-mech" title="Permalink to this headline"></a></h1>
<p>Let us create a functioning giant mech in Evennia. Everyone likes a giant mech, right? Start in-game as a character with build privileges (or the superuser).</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>create/drop Giant Mech ; mech
</pre></div>
</div>
<p>Boom. We created a Giant Mech Object and dropped it in the room. We also gave it an alias <em>mech</em>.
Lets describe it.</p>
2022-11-23 20:20:36 +00:00
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>desc mech = This is a huge mech. It has missiles and stuff.
</pre></div>
</div>
<p>Next we define who can “puppet” the mech object.</p>
2022-11-23 20:20:36 +00:00
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>lock mech = puppet:all()
</pre></div>
</div>
2022-11-23 20:20:36 +00:00
<p>This makes it so that everyone can control the mech. More mechs to the people! (Note that whereas Evennias default commands may look vaguely MUX-like, you can change the syntax to look like whatever interface style you prefer.)</p>
<p>Before we continue, lets make a brief detour. Evennia is very flexible about its objects and even more flexible about using and adding commands to those objects. Here are some ground rules well worth remembering for the remainder of this article:</p>
<ul class="simple">
<li><p>The <a class="reference internal" href="../Components/Accounts.html"><span class="doc std std-doc">Account</span></a> represents the real person logging in and has no game-world existence.</p></li>
<li><p>Any <a class="reference internal" href="../Components/Objects.html"><span class="doc std std-doc">Object</span></a> can be puppeted by an Account (with proper permissions).</p></li>
2023-10-19 20:22:27 +00:00
<li><p><span class="xref myst">Characters</span>, <span class="xref myst">Rooms</span>, and <span class="xref myst">Exits</span> are just children of normal Objects.</p></li>
<li><p>Any Object can be inside another (except if it creates a loop).</p></li>
<li><p>Any Object can store custom sets of commands on it. Those commands can:</p>
<ul>
<li><p>be made available to the puppeteer (Account),</p></li>
<li><p>be made available to anyone in the same location as the Object, and</p></li>
<li><p>be made available to anyone “inside” the Object</p></li>
2022-11-23 20:20:36 +00:00
<li><p>Also Accounts can store commands on themselves. Account commands are always available unless commands on a puppeted Object explicitly override them.</p></li>
</ul>
</li>
</ul>
2022-11-23 20:20:36 +00:00
<p>In Evennia, using the <code class="docutils literal notranslate"><span class="pre">ic</span></code> command will allow you to puppet a given Object (assuming you have puppet-access to do so). As mentioned above, the bog-standard Character class is in fact like any Object: it is auto-puppeted when logging in and just has a command set on it containing the normal in-game commands, like look, inventory, get and so on.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>ic mech
</pre></div>
</div>
<p>You just jumped out of your Character and <em>are</em> now the mech! If people look at you in-game, they
will look at a mech. The problem at this point is that the mech Object has no commands of its own.
The usual things like look, inventory and get sat on the Character object, remember? So at the
moment the mech is not quite as cool as it could be.</p>
2022-11-23 20:20:36 +00:00
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>ic &lt;Your old Character&gt;
</pre></div>
</div>
<p>You just jumped back to puppeting your normal, mundane Character again. All is well.</p>
<blockquote>
2022-11-23 20:20:36 +00:00
<div><p>Where did that <code class="docutils literal notranslate"><span class="pre">ic</span></code> command come from, if the mech had no commands on it? The
answer is that it came from the <code class="docutils literal notranslate"><span class="pre">Account</span></code>s command set. This is important. Without the Account being the one with the <code class="docutils literal notranslate"><span class="pre">ic</span></code> command, we would not have been able to get back out of our mech again.</p>
</div></blockquote>
2022-11-23 20:20:36 +00:00
<section id="make-a-mech-that-can-shoot">
<h2>Make a Mech that can shoot<a class="headerlink" href="#make-a-mech-that-can-shoot" title="Permalink to this headline"></a></h2>
<p>Let us make the mech a little more interesting. In our favorite text editor, we will create some new
mech-suitable commands. In Evennia, commands are defined as Python classes.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in a new file mygame/commands/mechcommands.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">CmdShoot</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
2023-01-06 17:19:13 +00:00
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Firing the mechs gun</span>
<span class="sd"> Usage:</span>
<span class="sd"> shoot [target]</span>
<span class="sd"> This will fire your mechs main gun. If no</span>
<span class="sd"> target is given, you will shoot in the air.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;shoot&quot;</span>
<span class="n">aliases</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;fire&quot;</span><span class="p">,</span> <span class="s2">&quot;fire!&quot;</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">&quot;This actually does the shooting&quot;</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="n">location</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">location</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="c1"># no argument given to command - shoot in the air</span>
<span class="n">message</span> <span class="o">=</span> <span class="s2">&quot;BOOM! The mech fires its gun in the air!&quot;</span>
<span class="n">location</span><span class="o">.</span><span class="n">msg_contents</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
<span class="k">return</span>
<span class="c1"># we have an argument, search for target</span>
<span class="n">target</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="o">.</span><span class="n">strip</span><span class="p">())</span>
<span class="k">if</span> <span class="n">target</span><span class="p">:</span>
<span class="n">location</span><span class="o">.</span><span class="n">msg_contents</span><span class="p">(</span>
<span class="sa">f</span><span class="s2">&quot;BOOM! The mech fires its gun at </span><span class="si">{</span><span class="n">target</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2">&quot;</span>
<span class="p">)</span>
<span class="k">class</span> <span class="nc">CmdLaunch</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="c1"># make your own &#39;launch&#39;-command here as an exercise!</span>
<span class="c1"># (it&#39;s very similar to the &#39;shoot&#39; command above).</span>
</pre></div>
</div>
2022-11-23 20:20:36 +00:00
<p>This is saved as a normal Python module (lets call it <code class="docutils literal notranslate"><span class="pre">mechcommands.py</span></code>), in a place Evennia looks for such modules (<code class="docutils literal notranslate"><span class="pre">mygame/commands/</span></code>). This command will trigger when the player gives the command “shoot”, “fire,” or even “fire!” with an exclamation mark. The mech can shoot in the air or at a target if you give one. In a real game the gun would probably be given a chance to hit and give
damage to the target, but this is enough for now.</p>
2022-11-23 20:20:36 +00:00
<p>We also make a second command for launching missiles (<code class="docutils literal notranslate"><span class="pre">CmdLaunch</span></code>). To save space we wont describe it here; it looks the same except it returns a text about the missiles being fired and has different <code class="docutils literal notranslate"><span class="pre">key</span></code> and <code class="docutils literal notranslate"><span class="pre">aliases</span></code>. We leave that up to you to create as an exercise. You could have it print <code class="docutils literal notranslate"><span class="pre">&quot;WOOSH!</span> <span class="pre">The</span> <span class="pre">mech</span> <span class="pre">launches</span> <span class="pre">missiles</span> <span class="pre">against</span> <span class="pre">&lt;target&gt;!</span></code>, for example.</p>
<p>Now we shove our commands into a command set. A <a class="reference internal" href="../Components/Command-Sets.html"><span class="doc std std-doc">Command Set</span></a> (CmdSet) is a container holding any number of commands. The command set is what we will store on the mech.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in the same file mygame/commands/mechcommands.py</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">CmdSet</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">MechCmdSet</span><span class="p">(</span><span class="n">CmdSet</span><span class="p">):</span>
2023-01-06 17:19:13 +00:00
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> This allows mechs to do do mech stuff.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;mechcmdset&quot;</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="s2">&quot;Called once, when cmdset is first created&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">CmdShoot</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">CmdLaunch</span><span class="p">())</span>
</pre></div>
</div>
2022-11-23 20:20:36 +00:00
<p>This simply groups all the commands we want. We add our new shoot/launch commands. Lets head back into the game. For testing we will manually attach our new CmdSet to the mech.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>py self.search(&quot;mech&quot;).cmdset.add(&quot;commands.mechcommands.MechCmdSet&quot;)
</pre></div>
</div>
2022-11-23 20:20:36 +00:00
<p>This is a little Python snippet that searches for the mech in our current location and attaches our new MechCmdSet to it. What we add is actually the Python path to our cmdset class. Evennia will import and initialize it behind the scenes.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>ic mech
</pre></div>
</div>
<p>We are back as the mech! Lets do some shooting!</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>fire!
BOOM! The mech fires its gun in the air!
</pre></div>
</div>
2022-11-23 20:20:36 +00:00
<p>There we go, one functioning mech. Try your own <code class="docutils literal notranslate"><span class="pre">launch</span></code> command and see that it works too. We can not only walk around as the mech — since the CharacterCmdSet is included in our MechCmdSet, the mech can also do everything a Character could do, like look around, pick up stuff, and have an inventory. We could now shoot the gun at a target or try the missile launch command. Once you have your own mech, what else do you need?</p>
<blockquote>
2022-11-23 20:20:36 +00:00
<div><p>Youll find that the mechs commands are available to you by just standing in the same
location (not just by puppeting it). Well solve this with a <em>lock</em> in the next section.</p>
</div></blockquote>
</section>
2022-11-23 20:20:36 +00:00
<section id="making-an-army-of-mechs">
<h2>Making an army of Mechs<a class="headerlink" href="#making-an-army-of-mechs" title="Permalink to this headline"></a></h2>
<p>What weve done so far is just to make a normal Object, describe it and put some commands on it.
This is great for testing. The way we added it, the MechCmdSet will even go away if we reload the
2022-11-23 20:20:36 +00:00
server. Now we want to make the mech an actual object “type” so we can create mechs without those extra steps. For this we need to create a new Typeclass.</p>
<p>A <a class="reference internal" href="../Components/Typeclasses.html"><span class="doc std std-doc">Typeclass</span></a> is a near-normal Python class that stores its existence to the database
behind the scenes. A Typeclass is created in a normal Python source file:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in the new file mygame/typeclasses/mech.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">commands.mechcommands</span> <span class="kn">import</span> <span class="n">MechCmdSet</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">Mech</span><span class="p">(</span><span class="n">Object</span><span class="p">):</span>
2023-01-06 17:19:13 +00:00
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> This typeclass describes an armed Mech.</span>
<span class="sd"> &quot;&quot;&quot;</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="s2">&quot;This is called only when object is first created&quot;</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">default_cmds</span><span class="o">.</span><span class="n">CharacterCmdSet</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</span><span class="p">(</span><span class="n">MechCmdSet</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="bp">self</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="s2">&quot;puppet:all();call:false()&quot;</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">desc</span> <span class="o">=</span> <span class="s2">&quot;This is a huge mech. It has missiles and stuff.&quot;</span>
</pre></div>
</div>
2022-11-23 20:20:36 +00:00
<p>For convenience we include the full contents of the default <code class="docutils literal notranslate"><span class="pre">CharacterCmdSet</span></code> in there. This will make a Characters normal commands available to the mech. We also add the mech-commands from before, making sure they are stored persistently in the database. The locks specify that anyone can puppet the meck and no-one can “call” the mechs Commands from outside it - you have to puppet it to be able to shoot.</p>
<p>Thats it. When Objects of this type are created, they will always start out with the mechs command set and the correct lock. We set a default description, but you would probably change this with <code class="docutils literal notranslate"><span class="pre">desc</span></code> to individualize your mechs as you build them.</p>
<p>Back in the game, just exit the old mech (<code class="docutils literal notranslate"><span class="pre">&#64;ic</span></code> back to your old character) then do</p>
2022-11-23 20:20:36 +00:00
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>create/drop The Bigger Mech ; bigmech : mech.Mech
</pre></div>
</div>
<p>We create a new, bigger mech with an alias bigmech. Note how we give the python-path to our
Typeclass at the end — this tells Evennia to create the new object based on that class (we dont
2022-11-23 20:20:36 +00:00
have to give the full path in our game dir <code class="docutils literal notranslate"><span class="pre">typeclasses.mech.Mech</span></code> because Evennia knows to look in the <code class="docutils literal notranslate"><span class="pre">typeclasses</span></code> folder already). A shining new mech will appear in the room! Just use</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>ic bigmech
</pre></div>
</div>
<p>to take it on a test drive.</p>
<section id="future-mechs">
2022-11-23 20:20:36 +00:00
<h3>Future Mechs<a class="headerlink" href="#future-mechs" title="Permalink to this headline"></a></h3>
<p>Having you puppet the mech-object directly is just one way to implement a giant mech in Evennia.</p>
<p>For example, you could instead picture a mech as a “vehicle” that you “enter” as your normal
2022-11-23 20:20:36 +00:00
Character (since any Object can move inside another). In that case the “insides” of the mech Object could be the “cockpit”. The cockpit would have the <code class="docutils literal notranslate"><span class="pre">MechCommandSet</span></code> stored on itself and all the shooting goodness would be made available to you only when you enter it.</p>
<p>To expand on this you could add more commands to the mech and remove others. Maybe the mech shouldnt work just like a Character after all.</p>
<p>Maybe it makes loud noises every time it passes from room to room. Maybe it cannot pick up things without crushing them. Maybe it needs fuel, ammo and repairs. Maybe youll lock it down so it can only be puppeted by emo teenagers.</p>
<p>And of course you could put more guns on it. And make it fly.</p>
</section>
2022-11-23 20:20:36 +00:00
</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" >
2022-11-23 20:20:36 +00:00
<a href="Tutorial-Building-a-Train.html" title="Building a train that moves"
>next</a> |</li>
<li class="right" >
2022-11-21 23:18:31 +00:00
<a href="Tutorial-NPC-Merchants.html" title="NPC merchants"
>previous</a> |</li>
2023-10-19 20:22:27 +00:00
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 2.x</a> &#187;</li>
2023-12-20 18:20:52 +01:00
<li class="nav-item nav-item-1"><a href="Howtos-Overview.html" >Tutorials and Howtos</a> &#187;</li>
2022-11-23 20:20:36 +00:00
<li class="nav-item nav-item-this"><a href="">Building a giant mech</a></li>
</ul>
</div>
<div class="footer" role="contentinfo">
2023-10-19 20:22:27 +00:00
&#169; Copyright 2023, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
</div>
</body>
</html>