mirror of
https://github.com/evennia/evennia.git
synced 2026-03-18 22:06:30 +01:00
591 lines
No EOL
42 KiB
HTML
591 lines
No EOL
42 KiB
HTML
|
||
|
||
<!DOCTYPE html>
|
||
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
||
<head>
|
||
<meta charset="utf-8">
|
||
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
||
<title>Scripts — Evennia 1.0-dev documentation</title>
|
||
|
||
|
||
|
||
|
||
<link rel="shortcut icon" href="_static/favicon.ico"/>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
|
||
|
||
|
||
|
||
|
||
|
||
<link rel="index" title="Index"
|
||
href="genindex.html"/>
|
||
<link rel="search" title="Search" href="search.html"/>
|
||
<link rel="top" title="Evennia 1.0-dev documentation" href="index.html"/>
|
||
|
||
|
||
<script src="_static/js/modernizr.min.js"></script>
|
||
|
||
</head>
|
||
|
||
<body class="wy-body-for-nav" role="document">
|
||
|
||
|
||
<div class="wy-grid-for-nav">
|
||
|
||
|
||
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
|
||
<div class="wy-side-scroll">
|
||
<div class="wy-side-nav-search">
|
||
|
||
|
||
|
||
<a href="index.html" class="icon icon-home"> Evennia
|
||
|
||
|
||
|
||
</a>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<div role="search">
|
||
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
|
||
<input type="text" name="q" placeholder="Search docs" />
|
||
<input type="hidden" name="check_keywords" value="yes" />
|
||
<input type="hidden" name="area" value="default" />
|
||
</form>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
|
||
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
|
||
|
||
|
||
|
||
<!-- Local TOC -->
|
||
<div class="local-toc"><ul>
|
||
<li><a class="reference internal" href="#">Scripts</a><ul>
|
||
<li><a class="reference internal" href="#defining-new-scripts">Defining new Scripts</a></li>
|
||
<li><a class="reference internal" href="#properties-and-functions-defined-on-scripts">Properties and functions defined on Scripts</a></li>
|
||
<li><a class="reference internal" href="#global-scripts">Global Scripts</a></li>
|
||
<li><a class="reference internal" href="#dealing-with-errors">Dealing with Errors</a></li>
|
||
<li><a class="reference internal" href="#example-of-a-timed-script">Example of a timed script</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
|
||
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
|
||
|
||
|
||
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
|
||
|
||
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
|
||
<a href="index.html">Evennia</a>
|
||
|
||
</nav>
|
||
|
||
|
||
|
||
<div class="wy-nav-content">
|
||
<div class="rst-content">
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<div role="navigation" aria-label="breadcrumbs navigation">
|
||
|
||
<ul class="wy-breadcrumbs">
|
||
|
||
<li><a href="index.html">Docs</a> »</li>
|
||
|
||
<li>Scripts</li>
|
||
|
||
|
||
<li class="wy-breadcrumbs-aside">
|
||
|
||
|
||
<a href="_sources/Scripts.md.txt" rel="nofollow"> View page source</a>
|
||
|
||
|
||
</li>
|
||
|
||
</ul>
|
||
|
||
|
||
<hr/>
|
||
</div>
|
||
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
|
||
<div itemprop="articleBody">
|
||
|
||
<div class="section" id="scripts">
|
||
<h1>Scripts<a class="headerlink" href="#scripts" title="Permalink to this headline">¶</a></h1>
|
||
<p><em>Scripts</em> are the out-of-character siblings to the in-character
|
||
<a class="reference internal" href="Objects.html"><span class="doc">Objects</span></a>. Scripts are so flexible that the “Script” is a bit limiting</p>
|
||
<ul class="simple">
|
||
<li><p>we had to pick something to name them after all. Other possible names
|
||
(depending on what you’d use them for) would be <code class="docutils literal notranslate"><span class="pre">OOBObjects</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">StorageContainers</span></code> or <code class="docutils literal notranslate"><span class="pre">TimerObjects</span></code>.</p></li>
|
||
</ul>
|
||
<p>Scripts can be used for many different things in Evennia:</p>
|
||
<ul class="simple">
|
||
<li><p>They can attach to Objects to influence them in various ways - or exist
|
||
independently of any one in-game entity (so-called <em>Global Scripts</em>).</p></li>
|
||
<li><p>They can work as timers and tickers - anything that may change with Time. But
|
||
they can also have no time dependence at all. Note though that if all you want
|
||
is just to have an object method called repeatedly, you should consider using
|
||
the <a class="reference internal" href="TickerHandler.html"><span class="doc">TickerHandler</span></a> which is more limited but is specialized on
|
||
just this task.</p></li>
|
||
<li><p>They can describe State changes. A Script is an excellent platform for
|
||
hosting a persistent, but unique system handler. For example, a Script could be
|
||
used as the base to track the state of a turn-based combat system. Since
|
||
Scripts can also operate on a timer they can also update themselves regularly
|
||
to perform various actions.</p></li>
|
||
<li><p>They can act as data stores for storing game data persistently in the database
|
||
(thanks to its ability to have <a class="reference internal" href="Attributes.html"><span class="doc">Attributes</span></a>).</p></li>
|
||
<li><p>They can be used as OOC stores for sharing data between groups of objects, for
|
||
example for tracking the turns in a turn-based combat system or barter exchange.</p></li>
|
||
</ul>
|
||
<p>Scripts are <a class="reference internal" href="Typeclasses.html"><span class="doc">Typeclassed</span></a> entities and are manipulated in a similar
|
||
way to how it works for other such Evennia entities:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4
|
||
5</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># create a new script </span>
|
||
<span class="n">new_script</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">create_script</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="s2">"myscript"</span><span class="p">,</span> <span class="n">typeclass</span><span class="o">=...</span><span class="p">)</span>
|
||
|
||
<span class="c1"># search (this is always a list, also if there is only one match)</span>
|
||
<span class="n">list_of_myscript</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_script</span><span class="p">(</span><span class="s2">"myscript"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<div class="section" id="defining-new-scripts">
|
||
<h2>Defining new Scripts<a class="headerlink" href="#defining-new-scripts" title="Permalink to this headline">¶</a></h2>
|
||
<p>A Script is defined as a class and is created in the same way as other
|
||
<a class="reference internal" href="Typeclasses.html"><span class="doc">typeclassed</span></a> entities. The class has several properties
|
||
to control the timer-component of the scripts. These are all <em>optional</em> -
|
||
leaving them out will just create a Script with no timer components (useful to act as
|
||
a database store or to hold a persistent game system, for example).</p>
|
||
<p>This you can do for example in the module
|
||
<code class="docutils literal notranslate"><span class="pre">evennia/typeclasses/scripts.py</span></code>. Below is an example Script
|
||
Typeclass.</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">DefaultScript</span>
|
||
|
||
<span class="k">class</span> <span class="nc">MyScript</span><span class="p">(</span><span class="n">DefaultScript</span><span class="p">):</span>
|
||
|
||
<span class="k">def</span> <span class="nf">at_script_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">key</span> <span class="o">=</span> <span class="s2">"myscript"</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">interval</span> <span class="o">=</span> <span class="mi">60</span> <span class="c1"># 1 min repeat</span>
|
||
|
||
<span class="k">def</span> <span class="nf">at_repeat</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="c1"># do stuff every minute </span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/scripts.py</span></code> is the <code class="docutils literal notranslate"><span class="pre">Script</span></code> class which inherits from <code class="docutils literal notranslate"><span class="pre">DefaultScript</span></code> already. This is provided as your own base class to do with what you like: You can tweak <code class="docutils literal notranslate"><span class="pre">Script</span></code> if you want to change the default behavior and it is usually convenient to inherit from this instead. Here’s an example:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22
|
||
23
|
||
24
|
||
25
|
||
26
|
||
27
|
||
28
|
||
29</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># for example in mygame/typeclasses/scripts.py </span>
|
||
<span class="c1"># Script class is defined at the top of this module</span>
|
||
|
||
<span class="kn">import</span> <span class="nn">random</span>
|
||
|
||
<span class="k">class</span> <span class="nc">Weather</span><span class="p">(</span><span class="n">Script</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> A timer script that displays weather info. Meant to </span>
|
||
<span class="sd"> be attached to a room. </span>
|
||
<span class="sd"> </span>
|
||
<span class="sd"> """</span>
|
||
<span class="k">def</span> <span class="nf">at_script_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">key</span> <span class="o">=</span> <span class="s2">"weather_script"</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">desc</span> <span class="o">=</span> <span class="s2">"Gives random weather messages."</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">interval</span> <span class="o">=</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">5</span> <span class="c1"># every 5 minutes</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">persistent</span> <span class="o">=</span> <span class="bp">True</span> <span class="c1"># will survive reload</span>
|
||
|
||
<span class="k">def</span> <span class="nf">at_repeat</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="s2">"called every self.interval seconds."</span>
|
||
<span class="n">rand</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span>
|
||
<span class="k">if</span> <span class="n">rand</span> <span class="o"><</span> <span class="mf">0.5</span><span class="p">:</span>
|
||
<span class="n">weather</span> <span class="o">=</span> <span class="s2">"A faint breeze is felt."</span>
|
||
<span class="k">elif</span> <span class="n">rand</span> <span class="o"><</span> <span class="mf">0.7</span><span class="p">:</span>
|
||
<span class="n">weather</span> <span class="o">=</span> <span class="s2">"Clouds sweep across the sky."</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">weather</span> <span class="o">=</span> <span class="s2">"There is a light drizzle of rain."</span>
|
||
<span class="c1"># send this message to everyone inside the object this</span>
|
||
<span class="c1"># script is attached to (likely a room)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="o">.</span><span class="n">msg_contents</span><span class="p">(</span><span class="n">weather</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>If we put this script on a room, it will randomly report some weather
|
||
to everyone in the room every 5 minutes.</p>
|
||
<p>To activate it, just add it to the script handler (<code class="docutils literal notranslate"><span class="pre">scripts</span></code>) on an
|
||
<a class="reference internal" href="Objects.html"><span class="doc">Room</span></a>. That object becomes <code class="docutils literal notranslate"><span class="pre">self.obj</span></code> in the example above. Here we
|
||
put it on a room called <code class="docutils literal notranslate"><span class="pre">myroom</span></code>:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">myroom</span><span class="o">.</span><span class="n">scripts</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">scripts</span><span class="o">.</span><span class="n">Weather</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<blockquote>
|
||
<div><p>Note that <code class="docutils literal notranslate"><span class="pre">typeclasses</span></code> in your game dir is added to the setting <code class="docutils literal notranslate"><span class="pre">TYPECLASS_PATHS</span></code>.
|
||
Therefore we don’t need to give the full path (<code class="docutils literal notranslate"><span class="pre">typeclasses.scripts.Weather</span></code>
|
||
but only <code class="docutils literal notranslate"><span class="pre">scripts.Weather</span></code> above.</p>
|
||
</div></blockquote>
|
||
<p>You can also create scripts using the <code class="docutils literal notranslate"><span class="pre">evennia.create_script</span></code> function:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">create_script</span>
|
||
<span class="n">create_script</span><span class="p">(</span><span class="s1">'typeclasses.weather.Weather'</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="n">myroom</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>Note that if you were to give a keyword argument to <code class="docutils literal notranslate"><span class="pre">create_script</span></code>, that would
|
||
override the default value in your Typeclass. So for example, here is an instance
|
||
of the weather script that runs every 10 minutes instead (and also not survive
|
||
a server reload):</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">create_script</span><span class="p">(</span><span class="s1">'typeclasses.weather.Weather'</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="n">myroom</span><span class="p">,</span>
|
||
<span class="n">persistent</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">10</span><span class="o">*</span><span class="mi">60</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>From in-game you can use the <code class="docutils literal notranslate"><span class="pre">@script</span></code> command to launch the Script on things:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="nd">@script</span> <span class="n">here</span> <span class="o">=</span> <span class="n">typeclasses</span><span class="o">.</span><span class="n">scripts</span><span class="o">.</span><span class="n">Weather</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>You can conveniently view and kill running Scripts by using the <code class="docutils literal notranslate"><span class="pre">@scripts</span></code>
|
||
command in-game.</p>
|
||
</div>
|
||
<div class="section" id="properties-and-functions-defined-on-scripts">
|
||
<h2>Properties and functions defined on Scripts<a class="headerlink" href="#properties-and-functions-defined-on-scripts" title="Permalink to this headline">¶</a></h2>
|
||
<p>A Script has all the properties of a typeclassed object, such as <code class="docutils literal notranslate"><span class="pre">db</span></code> and <code class="docutils literal notranslate"><span class="pre">ndb</span></code>(see <a class="reference internal" href="Typeclasses.html"><span class="doc">Typeclasses</span></a>). Setting <code class="docutils literal notranslate"><span class="pre">key</span></code> is useful in order to manage scripts (delete them by name etc). These are usually set up in the Script’s typeclass, but can also be assigned on the fly as keyword arguments to <code class="docutils literal notranslate"><span class="pre">evennia.create_script</span></code>.</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">desc</span></code> - an optional description of the script’s function. Seen in script listings.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">interval</span></code> - how often the script should run. If <code class="docutils literal notranslate"><span class="pre">interval</span> <span class="pre">==</span> <span class="pre">0</span></code> (default), this script has no timing component, will not repeat and will exist forever. This is useful for Scripts used for storage or acting as bases for various non-time dependent game systems.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">start_delay</span></code> - (bool), if we should wait <code class="docutils literal notranslate"><span class="pre">interval</span></code> seconds before firing for the first time or not.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">repeats</span></code> - How many times we should repeat, assuming <code class="docutils literal notranslate"><span class="pre">interval</span> <span class="pre">></span> <span class="pre">0</span></code>. If repeats is set to <code class="docutils literal notranslate"><span class="pre"><=</span> <span class="pre">0</span></code>, the script will repeat indefinitely. Note that <em>each</em> firing of the script (including the first one) counts towards this value. So a <code class="docutils literal notranslate"><span class="pre">Script</span></code> with <code class="docutils literal notranslate"><span class="pre">start_delay=False</span></code> and <code class="docutils literal notranslate"><span class="pre">repeats=1</span></code> will start, immediately fire and shut down right away.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">persistent</span></code>- if this script should survive a server <em>reset</em> or server <em>shutdown</em>. (You don’t need to set this for it to survive a normal reload - the script will be paused and seamlessly restart after the reload is complete).</p></li>
|
||
</ul>
|
||
<p>There is one special property:</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">obj</span></code> - the <a class="reference internal" href="Objects.html"><span class="doc">Object</span></a> this script is attached to (if any). You should not need to set this manually. If you add the script to the Object with <code class="docutils literal notranslate"><span class="pre">myobj.scripts.add(myscriptpath)</span></code> or give <code class="docutils literal notranslate"><span class="pre">myobj</span></code> as an argument to the <code class="docutils literal notranslate"><span class="pre">utils.create.create_script</span></code> function, the <code class="docutils literal notranslate"><span class="pre">obj</span></code> property will be set to <code class="docutils literal notranslate"><span class="pre">myobj</span></code> for you.</p></li>
|
||
</ul>
|
||
<p>It’s also imperative to know the hook functions. Normally, overriding
|
||
these are all the customization you’ll need to do in Scripts. You can
|
||
find longer descriptions of these in <code class="docutils literal notranslate"><span class="pre">src/scripts/scripts.py</span></code>.</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">at_script_creation()</span></code> - this is usually where the script class sets things like <code class="docutils literal notranslate"><span class="pre">interval</span></code> and <code class="docutils literal notranslate"><span class="pre">repeats</span></code>; things that control how the script runs. It is only called once - when the script is first created.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">is_valid()</span></code> - determines if the script should still be running or not. This is called when running <code class="docutils literal notranslate"><span class="pre">obj.scripts.validate()</span></code>, which you can run manually, but which is also called by Evennia during certain situations such as reloads. This is also useful for using scripts as state managers. If the method returns <code class="docutils literal notranslate"><span class="pre">False</span></code>, the script is stopped and cleanly removed.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">at_start()</span></code> - this is called when the script starts or is unpaused. For persistent scripts this is at least once ever server startup. Note that this will <em>always</em> be called right away, also if <code class="docutils literal notranslate"><span class="pre">start_delay</span></code> is <code class="docutils literal notranslate"><span class="pre">True</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">at_repeat()</span></code> - this is called every <code class="docutils literal notranslate"><span class="pre">interval</span></code> seconds, or not at all. It is called right away at startup, unless <code class="docutils literal notranslate"><span class="pre">start_delay</span></code> is <code class="docutils literal notranslate"><span class="pre">True</span></code>, in which case the system will wait <code class="docutils literal notranslate"><span class="pre">interval</span></code> seconds before calling.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">at_stop()</span></code> - this is called when the script stops for whatever reason. It’s a good place to do custom cleanup.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">at_server_reload()</span></code> - this is called whenever the server is warm-rebooted (e.g. with the <code class="docutils literal notranslate"><span class="pre">@reload</span></code> command). It’s a good place to save non-persistent data you might want to survive a reload.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">at_server_shutdown()</span></code> - this is called when a system reset or systems shutdown is invoked.</p></li>
|
||
</ul>
|
||
<p>Running methods (usually called automatically by the engine, but possible to also invoke manually)</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">start()</span></code> - this will start the script. This is called automatically whenever you add a new script to a handler. <code class="docutils literal notranslate"><span class="pre">at_start()</span></code> will be called.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">stop()</span></code> - this will stop the script and delete it. Removing a script from a handler will stop it automatically. <code class="docutils literal notranslate"><span class="pre">at_stop()</span></code> will be called.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">pause()</span></code> - this pauses a running script, rendering it inactive, but not deleting it. All properties are saved and timers can be resumed. This is called automatically when the server reloads and will <em>not</em> lead to the <em>at_stop()</em> hook being called. This is a suspension of the script, not a change of state.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">unpause()</span></code> - resumes a previously paused script. The <code class="docutils literal notranslate"><span class="pre">at_start()</span></code> hook <em>will</em> be called to allow it to reclaim its internal state. Timers etc are restored to what they were before pause. The server automatically unpauses all paused scripts after a server reload.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">force_repeat()</span></code> - this will forcibly step the script, regardless of when it would otherwise have fired. The timer will reset and the <code class="docutils literal notranslate"><span class="pre">at_repeat()</span></code> hook is called as normal. This also counts towards the total number of repeats, if limited.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">time_until_next_repeat()</span></code> - for timed scripts, this returns the time in seconds until it next fires. Returns <code class="docutils literal notranslate"><span class="pre">None</span></code> if <code class="docutils literal notranslate"><span class="pre">interval==0</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">remaining_repeats()</span></code> - if the Script should run a limited amount of times, this tells us how many are currently left.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">reset_callcount(value=0)</span></code> - this allows you to reset the number of times the Script has fired. It only makes sense if <code class="docutils literal notranslate"><span class="pre">repeats</span> <span class="pre">></span> <span class="pre">0</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">restart(interval=None,</span> <span class="pre">repeats=None,</span> <span class="pre">start_delay=None)</span></code> - this method allows you to restart the Script in-place with different run settings. If you do, the <code class="docutils literal notranslate"><span class="pre">at_stop</span></code> hook will be called and the Script brought to a halt, then the <code class="docutils literal notranslate"><span class="pre">at_start</span></code> hook will be called as the Script starts up with your (possibly changed) settings. Any keyword left at <code class="docutils literal notranslate"><span class="pre">None</span></code> means to not change the original setting.</p></li>
|
||
</ul>
|
||
</div>
|
||
<div class="section" id="global-scripts">
|
||
<h2>Global Scripts<a class="headerlink" href="#global-scripts" title="Permalink to this headline">¶</a></h2>
|
||
<p>A script does not have to be connected to an in-game object. If not it is
|
||
called a <em>Global script</em>. You can create global scripts by simply not supplying an object to store it on:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># adding a global script</span>
|
||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">create_script</span>
|
||
<span class="n">create_script</span><span class="p">(</span><span class="s2">"typeclasses.globals.MyGlobalEconomy"</span><span class="p">,</span>
|
||
<span class="n">key</span><span class="o">=</span><span class="s2">"economy"</span><span class="p">,</span> <span class="n">persistent</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="bp">None</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>Henceforth you can then get it back by searching for its key or other identifier with
|
||
<code class="docutils literal notranslate"><span class="pre">evennia.search_script</span></code>. In-game, the <code class="docutils literal notranslate"><span class="pre">scripts</span></code> command will show all scripts.</p>
|
||
<p>Evennia supplies a convenient “container” called <code class="docutils literal notranslate"><span class="pre">GLOBAL_SCRIPTS</span></code> that can offer an easy
|
||
way to access global scripts. If you know the name (key) of the script you can get it like so:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">GLOBAL_SCRIPTS</span>
|
||
|
||
<span class="n">my_script</span> <span class="o">=</span> <span class="n">GLOBAL_SCRIPTS</span><span class="o">.</span><span class="n">my_script</span>
|
||
<span class="c1"># needed if there are spaces in name or name determined on the fly</span>
|
||
<span class="n">another_script</span> <span class="o">=</span> <span class="n">GLOBAL_SCRIPTS</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"another script"</span><span class="p">)</span>
|
||
<span class="c1"># get all global scripts (this returns a Queryset)</span>
|
||
<span class="n">all_scripts</span> <span class="o">=</span> <span class="n">GLOBAL_SCRIPTS</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
|
||
<span class="c1"># you can operate directly on the script</span>
|
||
<span class="n">GLOBAL_SCRIPTS</span><span class="o">.</span><span class="n">weather</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">current_weather</span> <span class="o">=</span> <span class="s2">"Cloudy"</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<blockquote>
|
||
<div><p>Note that global scripts appear as properties on <code class="docutils literal notranslate"><span class="pre">GLOBAL_SCRIPTS</span></code> based on their <code class="docutils literal notranslate"><span class="pre">key</span></code>.
|
||
If you were to create two global scripts with the same <code class="docutils literal notranslate"><span class="pre">key</span></code> (even with different typeclasses),
|
||
the <code class="docutils literal notranslate"><span class="pre">GLOBAL_SCRIPTS</span></code> container will only return one of them (which one depends on order in
|
||
the database). Best is to organize your scripts so that this does not happen. Otherwise, use <code class="docutils literal notranslate"><span class="pre">evennia.search_script</span></code> to get exactly the script you want.</p>
|
||
</div></blockquote>
|
||
<p>There are two ways to make a script appear as a property on <code class="docutils literal notranslate"><span class="pre">GLOBAL_SCRIPTS</span></code>. The first is
|
||
to manually create a new global script with <code class="docutils literal notranslate"><span class="pre">create_script</span></code> as mentioned above. Often you want this to happen automatically when the server starts though. For this you can use the setting <code class="docutils literal notranslate"><span class="pre">GLOBAL_SCRIPTS</span></code>:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">GLOBAL_SCRIPTS</span> <span class="o">=</span> <span class="p">{</span>
|
||
<span class="s2">"my_script"</span><span class="p">:</span> <span class="p">{</span>
|
||
<span class="s2">"typeclass"</span><span class="p">:</span> <span class="s2">"scripts.Weather"</span><span class="p">,</span>
|
||
<span class="s2">"repeats"</span><span class="p">:</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span>
|
||
<span class="s2">"interval"</span><span class="p">:</span> <span class="mi">50</span><span class="p">,</span>
|
||
<span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"Weather script"</span>
|
||
<span class="s2">"persistent"</span><span class="p">:</span> <span class="bp">True</span>
|
||
<span class="p">},</span>
|
||
<span class="s2">"storagescript"</span><span class="p">:</span> <span class="p">{</span>
|
||
<span class="s2">"typeclass"</span><span class="p">:</span> <span class="s2">"scripts.Storage"</span><span class="p">,</span>
|
||
<span class="s2">"persistent"</span><span class="p">:</span> <span class="bp">True</span>
|
||
<span class="p">}</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>Here the key (<code class="docutils literal notranslate"><span class="pre">myscript</span></code> and <code class="docutils literal notranslate"><span class="pre">storagescript</span></code> above) is required, all other fields are optional. If <code class="docutils literal notranslate"><span class="pre">typeclass</span></code> is not given, a script of type <code class="docutils literal notranslate"><span class="pre">settings.BASE_SCRIPT_TYPECLASS</span></code> is assumed. The keys related to timing and intervals are only needed if the script is timed.</p>
|
||
<p>Evennia will use the information in <code class="docutils literal notranslate"><span class="pre">settings.GLOBAL_SCRIPTS</span></code> to automatically create and start these
|
||
scripts when the server starts (unless they already exist, based on their <code class="docutils literal notranslate"><span class="pre">key</span></code>). You need to reload the server before the setting is read and new scripts become available. You can then find the <code class="docutils literal notranslate"><span class="pre">key</span></code> you gave as properties on <code class="docutils literal notranslate"><span class="pre">evennia.GLOBAL_SCRIPTS</span></code>
|
||
(such as <code class="docutils literal notranslate"><span class="pre">evennia.GLOBAL_SCRIPTS.storagescript</span></code>).</p>
|
||
<blockquote>
|
||
<div><p>Note: Make sure that your Script typeclass does not have any critical errors. If so, you’ll see errors in your log and your Script will temporarily fall back to being a <code class="docutils literal notranslate"><span class="pre">DefaultScript</span></code> type.</p>
|
||
</div></blockquote>
|
||
<p>Moreover, a script defined this way is <em>guaranteed</em> to exist when you try to access it:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">GLOBAL_SCRIPTS</span>
|
||
<span class="c1"># first stop the script </span>
|
||
<span class="n">GLOBAL_SCRIPTS</span><span class="o">.</span><span class="n">storagescript</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
|
||
<span class="c1"># running the `scripts` command now will show no storagescript</span>
|
||
<span class="c1"># but below now it's recreated again! </span>
|
||
<span class="n">storage</span> <span class="o">=</span> <span class="n">GLOBAL_SCRIPTS</span><span class="o">.</span><span class="n">storagescript</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>That is, if the script is deleted, next time you get it from <code class="docutils literal notranslate"><span class="pre">GLOBAL_SCRIPTS</span></code>, it will use the information
|
||
in settings to recreate it for you.</p>
|
||
<blockquote>
|
||
<div><p>Note that if your goal with the Script is to store persistent data, you should set it as <code class="docutils literal notranslate"><span class="pre">persistent=True</span></code>, either in <code class="docutils literal notranslate"><span class="pre">settings.GLOBAL_SCRIPTS</span></code> or in the Scripts typeclass. Otherwise any data you wanted to store on it will be gone (since a new script of the same name is restarted instead).</p>
|
||
</div></blockquote>
|
||
</div>
|
||
<div class="section" id="dealing-with-errors">
|
||
<h2>Dealing with Errors<a class="headerlink" href="#dealing-with-errors" title="Permalink to this headline">¶</a></h2>
|
||
<p>Errors inside an timed, executing script can sometimes be rather terse or point to
|
||
parts of the execution mechanism that is hard to interpret. One way to make it
|
||
easier to debug scripts is to import Evennia’s native logger and wrap your
|
||
functions in a try/catch block. Evennia’s logger can show you where the
|
||
traceback occurred in your script.</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15</pre></div></td><td class="code"><div class="highlight"><pre><span></span>
|
||
<span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">logger</span>
|
||
|
||
<span class="k">class</span> <span class="nc">Weather</span><span class="p">(</span><span class="n">DefaultScript</span><span class="p">):</span>
|
||
|
||
<span class="c1"># [...]</span>
|
||
|
||
<span class="k">def</span> <span class="nf">at_repeat</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="c1"># [...] code as above</span>
|
||
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
|
||
<span class="c1"># logs the error </span>
|
||
<span class="n">logger</span><span class="o">.</span><span class="n">log_trace</span><span class="p">()</span>
|
||
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
</div>
|
||
<div class="section" id="example-of-a-timed-script">
|
||
<h2>Example of a timed script<a class="headerlink" href="#example-of-a-timed-script" title="Permalink to this headline">¶</a></h2>
|
||
<p>In-game you can try out scripts using the <code class="docutils literal notranslate"><span class="pre">@script</span></code> command. In the
|
||
<code class="docutils literal notranslate"><span class="pre">evennia/contrib/tutorial_examples/bodyfunctions.py</span></code> is a little example script
|
||
that makes you do little ‘sounds’ at random intervals. Try the following to apply an
|
||
example time-based script to your character.</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">></span> <span class="nd">@script</span> <span class="bp">self</span> <span class="o">=</span> <span class="n">bodyfunctions</span><span class="o">.</span><span class="n">BodyFunctions</span>
|
||
</pre></div>
|
||
</div>
|
||
<blockquote>
|
||
<div><p>Note: Since <code class="docutils literal notranslate"><span class="pre">evennia/contrib/tutorial_examples</span></code> is in the default setting
|
||
<code class="docutils literal notranslate"><span class="pre">TYPECLASS_PATHS</span></code>, we only need to specify the final part of the path,
|
||
that is, <code class="docutils literal notranslate"><span class="pre">bodyfunctions.BodyFunctions</span></code>.</p>
|
||
</div></blockquote>
|
||
<p>If you want to inflict your flatulence script on another person, place or
|
||
thing, try something like the following:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">></span> <span class="nd">@py</span> <span class="bp">self</span><span class="o">.</span><span class="n">location</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">'matt'</span><span class="p">)</span><span class="o">.</span><span class="n">scripts</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s1">'bodyfunctions.BodyFunctions'</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Here’s how you stop it on yourself.</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">></span> <span class="nd">@script</span><span class="o">/</span><span class="n">stop</span> <span class="bp">self</span> <span class="o">=</span> <span class="n">bodyfunctions</span><span class="o">.</span><span class="n">BodyFunctions</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This will kill the script again. You can use the <code class="docutils literal notranslate"><span class="pre">@scripts</span></code> command to list all
|
||
active scripts in the game, if any (there are none by default).</p>
|
||
<p>For another example of a Script in use, check out the <a class="reference external" href="https://github.com/evennia/evennia/wiki/Turn%20based%20Combat%20System">Turn Based Combat System
|
||
tutorial</a>.</p>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
<footer>
|
||
|
||
|
||
<hr/>
|
||
|
||
<div role="contentinfo">
|
||
<p>
|
||
© Copyright 2020, The Evennia developer community.
|
||
|
||
</p>
|
||
</div>
|
||
Built with <a href="http://sphinx-doc.org/">Sphinx</a> and ❤️ using a custom <a href="https://github.com/LinxiFan/Sphinx-theme">theme</a> based on <a href="https://readthedocs.org">Read the Docs</a>.
|
||
|
||
</footer>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</section>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
|
||
|
||
<script type="text/javascript">
|
||
var DOCUMENTATION_OPTIONS = {
|
||
URL_ROOT:'./',
|
||
VERSION:'1.0-dev',
|
||
COLLAPSE_INDEX:false,
|
||
FILE_SUFFIX:'.html',
|
||
HAS_SOURCE: true,
|
||
SOURCELINK_SUFFIX: '.txt'
|
||
};
|
||
</script>
|
||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||
<script type="text/javascript" src="_static/underscore.js"></script>
|
||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||
<script type="text/javascript" src="_static/language_data.js"></script>
|
||
|
||
|
||
|
||
|
||
|
||
<script type="text/javascript" src="_static/js/theme.js"></script>
|
||
|
||
|
||
|
||
|
||
<script type="text/javascript">
|
||
jQuery(function () {
|
||
SphinxRtdTheme.StickyNav.enable();
|
||
});
|
||
</script>
|
||
|
||
|
||
</body>
|
||
</html> |