mirror of
https://github.com/evennia/evennia.git
synced 2026-03-18 13:56:30 +01:00
486 lines
42 KiB
HTML
486 lines
42 KiB
HTML
|
|
|
|||
|
|
<!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>Scripts — Evennia 0.9.5 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>
|
|||
|
|
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
|||
|
|
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
|
|||
|
|
<link rel="shortcut icon" href="_static/favicon.ico"/>
|
|||
|
|
<link rel="index" title="Index" href="genindex.html" />
|
|||
|
|
<link rel="search" title="Search" href="search.html" />
|
|||
|
|
</head><body>
|
|||
|
|
<div class="related" role="navigation" aria-label="related navigation">
|
|||
|
|
<h3>Navigation</h3>
|
|||
|
|
<ul>
|
|||
|
|
<li class="right" style="margin-right: 10px">
|
|||
|
|
<a href="genindex.html" title="General Index"
|
|||
|
|
accesskey="I">index</a></li>
|
|||
|
|
<li class="right" >
|
|||
|
|
<a href="py-modindex.html" title="Python Module Index"
|
|||
|
|
>modules</a> |</li>
|
|||
|
|
<li class="nav-item nav-item-0"><a href="index.html">Evennia 0.9.5</a> »</li>
|
|||
|
|
<li class="nav-item nav-item-this"><a href="">Scripts</a></li>
|
|||
|
|
</ul>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="document">
|
|||
|
|
<div class="documentwrapper">
|
|||
|
|
<div class="bodywrapper">
|
|||
|
|
<div class="body" role="main">
|
|||
|
|
|
|||
|
|
<section class="tex2jax_ignore mathjax_ignore" id="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 std std-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 std std-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 std std-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 std std-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"><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>
|
|||
|
|
</div>
|
|||
|
|
<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 std std-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"><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>
|
|||
|
|
</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"><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="kc">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>
|
|||
|
|
</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 std std-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>If you wanted to stop and delete that script on the <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Room</span></a>. You could do that
|
|||
|
|
with the script handler by passing the <code class="docutils literal notranslate"><span class="pre">delete</span></code> method with the script key (<code class="docutils literal notranslate"><span class="pre">self.key</span></code>) as:</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">delete</span><span class="p">(</span><span class="s1">'weather_script'</span><span class="p">)</span>
|
|||
|
|
</pre></div>
|
|||
|
|
</div>
|
|||
|
|
<blockquote>
|
|||
|
|
<div><p>Note that If no key is given, this will delete <em>all</em> scripts on the object!</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"><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>
|
|||
|
|
</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"><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="kc">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>
|
|||
|
|
</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>
|
|||
|
|
</section>
|
|||
|
|
<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 std std-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 std std-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>
|
|||
|
|
</section>
|
|||
|
|
<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"><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="kc">True</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
|||
|
|
</pre></div>
|
|||
|
|
</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"><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>
|
|||
|
|
</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 add a python global dictionary
|
|||
|
|
named <code class="docutils literal notranslate"><span class="pre">GLOBAL_SCRIPTS</span></code> to your <code class="docutils literal notranslate"><span class="pre">settings.py</span></code> file. The <code class="docutils literal notranslate"><span class="pre">settings.py</span></code> fie is located in
|
|||
|
|
<code class="docutils literal notranslate"><span class="pre">mygame/conf/settings.py</span></code>:</p>
|
|||
|
|
<div class="highlight-python notranslate"><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">"typeclasses.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="p">,</span>
|
|||
|
|
<span class="s2">"persistent"</span><span class="p">:</span> <span class="kc">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">"typeclasses.scripts.Storage"</span><span class="p">,</span>
|
|||
|
|
<span class="s2">"persistent"</span><span class="p">:</span> <span class="kc">True</span>
|
|||
|
|
<span class="p">},</span>
|
|||
|
|
<span class="p">{</span>
|
|||
|
|
<span class="s2">"another_script"</span><span class="p">:</span> <span class="p">{</span>
|
|||
|
|
<span class="s2">"typeclass"</span><span class="p">:</span> <span class="s2">"typeclasses.another_script.AnotherScript"</span>
|
|||
|
|
<span class="p">}</span>
|
|||
|
|
<span class="p">}</span>
|
|||
|
|
</pre></div>
|
|||
|
|
</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>
|
|||
|
|
<blockquote>
|
|||
|
|
<div><p>Note: Provide the full path to the scripts module in GLOBAL_SCRIPTS. In the example with
|
|||
|
|
<code class="docutils literal notranslate"><span class="pre">another_script</span></code>, you can also create separate script modules that exist beyond <a class="reference external" href="http://scrypt.py">scrypt.py</a> for
|
|||
|
|
further organizational requirements if needed.</p>
|
|||
|
|
</div></blockquote>
|
|||
|
|
<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"><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>
|
|||
|
|
</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>
|
|||
|
|
</section>
|
|||
|
|
<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"><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>
|
|||
|
|
</div>
|
|||
|
|
</section>
|
|||
|
|
<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-none notranslate"><div class="highlight"><pre><span></span>> @script self = bodyfunctions.BodyFunctions
|
|||
|
|
</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-none notranslate"><div class="highlight"><pre><span></span>> @py self.location.search('matt').scripts.add('bodyfunctions.BodyFunctions')
|
|||
|
|
</pre></div>
|
|||
|
|
</div>
|
|||
|
|
<p>Here’s how you stop it on yourself.</p>
|
|||
|
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> @script/stop self = bodyfunctions.BodyFunctions
|
|||
|
|
</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>
|
|||
|
|
</section>
|
|||
|
|
</section>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<div class="clearer"></div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
|||
|
|
<div class="sphinxsidebarwrapper">
|
|||
|
|
<p class="logo"><a href="index.html">
|
|||
|
|
<img class="logo" src="_static/evennia_logo.png" alt="Logo"/>
|
|||
|
|
</a></p>
|
|||
|
|
<div id="searchbox" style="display: none" role="search">
|
|||
|
|
<h3 id="searchlabel">Quick search</h3>
|
|||
|
|
<div class="searchformwrapper">
|
|||
|
|
<form class="search" action="search.html" method="get">
|
|||
|
|
<input type="text" name="q" aria-labelledby="searchlabel" />
|
|||
|
|
<input type="submit" value="Go" />
|
|||
|
|
</form>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<script>$('#searchbox').show(0);</script>
|
|||
|
|
<p><h3><a href="index.html">Table of Contents</a></h3>
|
|||
|
|
<ul>
|
|||
|
|
<li><a class="reference internal" href="#">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 role="note" aria-label="source link">
|
|||
|
|
<!--h3>This Page</h3-->
|
|||
|
|
<ul class="this-page-menu">
|
|||
|
|
<li><a href="_sources/Scripts.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="http://webchat.freenode.net/?channels=evennia&uio=MT1mYWxzZSY5PXRydWUmMTE9MTk1JjEyPXRydWUbb">IRC</a> -
|
|||
|
|
<a href="https://discord.gg/NecFePw">Discord</a> -
|
|||
|
|
<a href="https://groups.google.com/forum/#%21forum/evennia">Forums</a>
|
|||
|
|
</li>
|
|||
|
|
<li><a href="http://evennia.blogspot.com/">Evennia Dev blog</a> </li>
|
|||
|
|
</ul>
|
|||
|
|
<h3>Versions</h3>
|
|||
|
|
<ul>
|
|||
|
|
<li><a href="../1.0-dev/index.html">1.0-dev (develop branch)</a></li>
|
|||
|
|
<li><a href="Scripts.html">0.9.5 (v0.9.5 branch)</a></li>
|
|||
|
|
</ul>
|
|||
|
|
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="clearer"></div>
|
|||
|
|
</div>
|
|||
|
|
<div class="related" role="navigation" aria-label="related navigation">
|
|||
|
|
<h3>Navigation</h3>
|
|||
|
|
<ul>
|
|||
|
|
<li class="right" style="margin-right: 10px">
|
|||
|
|
<a href="genindex.html" title="General Index"
|
|||
|
|
>index</a></li>
|
|||
|
|
<li class="right" >
|
|||
|
|
<a href="py-modindex.html" title="Python Module Index"
|
|||
|
|
>modules</a> |</li>
|
|||
|
|
<li class="nav-item nav-item-0"><a href="index.html">Evennia 0.9.5</a> »</li>
|
|||
|
|
<li class="nav-item nav-item-this"><a href="">Scripts</a></li>
|
|||
|
|
</ul>
|
|||
|
|
</div>
|
|||
|
|
<div class="footer" role="contentinfo">
|
|||
|
|
© Copyright 2020, The Evennia developer community.
|
|||
|
|
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
|||
|
|
</div>
|
|||
|
|
</body>
|
|||
|
|
</html>
|