mirror of
https://github.com/evennia/evennia.git
synced 2026-03-28 02:36:32 +01:00
Updated HTML docs
This commit is contained in:
parent
95b1772cdb
commit
9e40124c44
86 changed files with 2873 additions and 3808 deletions
|
|
@ -39,55 +39,66 @@
|
|||
|
||||
<div class="section" id="scripts">
|
||||
<h1>Scripts<a class="headerlink" href="#scripts" title="Permalink to this headline">¶</a></h1>
|
||||
<p><a class="reference external" href="../api/evennia.scripts.scripts.html">Script API reference</a></p>
|
||||
<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>
|
||||
<a class="reference internal" href="Objects.html"><span class="doc">Objects</span></a>. Scripts are so flexible that the name “Script” is a bit limiting
|
||||
in itself - but we had to pick <em>something</em> to name them. 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>
|
||||
<p>If you ever consider creating an <a class="reference internal" href="Objects.html"><span class="doc">Object</span></a> with a <code class="docutils literal notranslate"><span class="pre">None</span></code>-location just to store some game data,
|
||||
you should really be using a Script instead.</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>
|
||||
<li><p>Scripts are full <a class="reference internal" href="Typeclasses.html"><span class="doc">Typeclassed</span></a> entities - they have <a class="reference internal" href="Attributes.html"><span class="doc">Attributes</span></a> and
|
||||
can be modified in the same way. But they have <em>no in-game existence</em>, so no
|
||||
location or command-execution like <a class="reference internal" href="Objects.html"><span class="doc">Objects</span></a> and no connection to a particular
|
||||
player/session like <a class="reference internal" href="Accounts.html"><span class="doc">Accounts</span></a>. This means they are perfectly suitable for acting
|
||||
as database-storage backends for game <em>systems</em>: Storing the current state of the economy,
|
||||
who is involved in the current fight, tracking an ongoing barter and so on. They are great as
|
||||
persistent system handlers.</p></li>
|
||||
<li><p>Scripts have an optional <em>timer component</em>. This means that you can set up the script
|
||||
to tick the <code class="docutils literal notranslate"><span class="pre">at_repeat</span></code> hook on the Script at a certain interval. The timer can be controlled
|
||||
independently of the rest of the script as needed. This component is optional
|
||||
and complementary to other timing functions in Evennia, like
|
||||
<a class="reference external" href="../api/evennia.utils.utils.html#evennia.utils.utils.delay">evennia.utils.delay</a> and
|
||||
<a class="reference external" href="../api/evennia.utils.utils.html#evennia.utils.utils.repeat">evennia.utils.repeat</a>.</p></li>
|
||||
<li><p>Scripts can <em>attach</em> to Objects and Accounts via e.g. <code class="docutils literal notranslate"><span class="pre">obj.scripts.add/remove</span></code>. In the
|
||||
script you can then access the object/account as <code class="docutils literal notranslate"><span class="pre">self.obj</span></code> or <code class="docutils literal notranslate"><span class="pre">self.account</span></code>. This can be used to
|
||||
dynamically extend other typeclasses but also to use the timer component to affect the parent object
|
||||
in various ways. For historical reasons, a Script <em>not</em> attached to an object is referred to as a
|
||||
<em>Global</em> Script.</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>
|
||||
<div class="versionchanged">
|
||||
<p><span class="versionmodified changed">Changed in version 1.0: </span>In previus Evennia versions, stopping the Script’s timer also meant deleting the Script object.
|
||||
Starting with this version, the timer can be start/stopped separately and <cite>.delete()</cite> must be called
|
||||
on the Script explicitly to delete it.</p>
|
||||
</div>
|
||||
<div class="section" id="in-game-command-examples">
|
||||
<h2>In-game command examples<a class="headerlink" href="#in-game-command-examples" title="Permalink to this headline">¶</a></h2>
|
||||
<p>There are two main commands controlling scripts in the default cmdset:</p>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">addscript</span></code> command is used for attaching scripts to existing objects:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">></span> <span class="n">addscript</span> <span class="n">obj</span> <span class="o">=</span> <span class="n">bodyfunctions</span><span class="o">.</span><span class="n">BodyFunctions</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">scripts</span></code> command is used to view all scripts and perform operations on them:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">></span> <span class="n">scripts</span>
|
||||
<span class="o">></span> <span class="n">scripts</span><span class="o">/</span><span class="n">stop</span> <span class="n">bodyfunctions</span><span class="o">.</span><span class="n">BodyFunctions</span>
|
||||
<span class="o">></span> <span class="n">scripts</span><span class="o">/</span><span class="n">start</span> <span class="c1">#244</span>
|
||||
<span class="o">></span> <span class="n">scripts</span><span class="o">/</span><span class="n">pause</span> <span class="c1">#11</span>
|
||||
<span class="o">></span> <span class="n">scripts</span><span class="o">/</span><span class="n">delete</span> <span class="c1">#566</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="versionchanged">
|
||||
<p><span class="versionmodified changed">Changed in version 1.0: </span>The <cite>addscript</cite> command used to be only <cite>script</cite> which was easy to confuse with <cite>scripts</cite>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="code-examples">
|
||||
<h2>Code examples<a class="headerlink" href="#code-examples" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Here are some examples of working with Scripts in-code (more details to follow in later
|
||||
sections).</p>
|
||||
<p>Create a new script:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">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>
|
||||
</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>
|
||||
<p>Create script with timer component:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||||
2
|
||||
3
|
||||
|
|
@ -97,22 +108,210 @@ Typeclass.</p>
|
|||
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>
|
||||
10
|
||||
11</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># (note that this will call `timed_script.at_repeat` which is empty by default)</span>
|
||||
<span class="n">timed_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">"Timed script"</span><span class="p">,</span>
|
||||
<span class="n">interval</span><span class="o">=</span><span class="mi">34</span><span class="p">,</span> <span class="c1"># seconds <=0 means off</span>
|
||||
<span class="n">start_delay</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="c1"># wait interval before first call</span>
|
||||
<span class="n">autostart</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="c1"># start timer (else needing .start() )</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="c1"># manipulate the script's timer</span>
|
||||
<span class="n">timed_script</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
|
||||
<span class="n">timed_script</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||||
<span class="n">timed_script</span><span class="o">.</span><span class="n">pause</span><span class="p">()</span>
|
||||
<span class="n">timed_script</span><span class="o">.</span><span class="n">unpause</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>Attach script to another object:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2
|
||||
3</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">myobj</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">new_script</span><span class="p">)</span>
|
||||
<span class="n">myobj</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">evennia</span><span class="o">.</span><span class="n">DefaultScript</span><span class="p">)</span>
|
||||
<span class="n">all_scripts_on_obj</span> <span class="o">=</span> <span class="n">myobj</span><span class="o">.</span><span class="n">scripts</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>Search/find scripts in various ways:</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="c1"># regular search (this is always a list, also if there is only one match)</span>
|
||||
<span class="n">list_of_myscripts</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>
|
||||
|
||||
<span class="c1"># search through Evennia's GLOBAL_SCRIPTS container (based on </span>
|
||||
<span class="c1"># script's key only)</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">myscript</span> <span class="o">=</span> <span class="n">GLOBAL_SCRIPTS</span><span class="o">.</span><span class="n">myscript</span>
|
||||
<span class="n">GLOBAL_SCRIPTS</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"Timed script"</span><span class="p">)</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">foo</span> <span class="o">=</span> <span class="s2">"bar"</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>Delete the Script (this will also stop its timer):</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">new_script</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
|
||||
<span class="n">timed_script</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
</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 parent class is <code class="docutils literal notranslate"><span class="pre">evennia.DefaultScript</span></code>.</p>
|
||||
<div class="section" id="simple-storage-script">
|
||||
<h3>Simple storage script<a class="headerlink" href="#simple-storage-script" title="Permalink to this headline">¶</a></h3>
|
||||
<p>In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/scripts.py</span></code> is an empty <code class="docutils literal notranslate"><span class="pre">Script</span></code> class already set up. You
|
||||
can use this as a base for your own scripts.</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</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/typeclasses/scripts.py</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">Script</span><span class="p">(</span><span class="n">DefaultScript</span><span class="p">):</span>
|
||||
<span class="c1"># stuff common for all your scripts goes here</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">MyScript</span><span class="p">(</span><span class="n">Script</span><span class="p">):</span>
|
||||
<span class="k">def</span> <span class="nf">at_script_creation</span><span class="p">(</span><span class="n">selfself</span><span class="p">):</span>
|
||||
<span class="sd">"""Called once, when script is first created"""</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">db</span><span class="o">.</span><span class="n">foo</span> <span class="o">=</span> <span class="s2">"bar"</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>Once created, this simple Script could act as a global storage:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">evennia</span><span class="o">.</span><span class="n">create_script</span><span class="p">(</span><span class="s1">'typeclasses.scripts.MyScript'</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># from somewhere else </span>
|
||||
|
||||
<span class="n">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>
|
||||
<span class="n">bar</span> <span class="o">=</span> <span class="n">myscript</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">foo</span>
|
||||
<span class="n">myscript</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">something_else</span> <span class="o">=</span> <span class="mi">1000</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>Note that if you give keyword arguments to <code class="docutils literal notranslate"><span class="pre">create_script</span></code> you can override the values
|
||||
you set in your <code class="docutils literal notranslate"><span class="pre">at_script_creation</span></code>:</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="n">evennia</span><span class="o">.</span><span class="n">create_script</span><span class="p">(</span><span class="s1">'typeclasses.scripts.MyScript'</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">"another name"</span><span class="p">,</span>
|
||||
<span class="n">attributes</span><span class="o">=</span><span class="p">[(</span><span class="s2">"foo"</span><span class="p">,</span> <span class="s2">"bar-alternative"</span><span class="p">)])</span>
|
||||
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>See the <a class="reference external" href="../api/evennia.utils.create.html#evennia.utils.create.create_script">create_script</a> and
|
||||
<a class="reference external" href="../api/evennia.utils.search.html#evennia.utils.search.search_script">search_script</a> API documentation for more options
|
||||
on creating and finding Scripts.</p>
|
||||
</div>
|
||||
<div class="section" id="timed-scripts">
|
||||
<h3>Timed Scripts<a class="headerlink" href="#timed-scripts" title="Permalink to this headline">¶</a></h3>
|
||||
<p>There are several properties one can set on the Script to control its timer component.</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/typeclasses/scripts.py</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">TimerScript</span><span class="p">(</span><span class="n">Script</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">desc</span> <span class="o">=</span> <span class="s2">"An example script"</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>
|
||||
<p>This example will call <code class="docutils literal notranslate"><span class="pre">at_repeat</span></code> every minute. The <code class="docutils literal notranslate"><span class="pre">create_script</span></code> function has an <code class="docutils literal notranslate"><span class="pre">autostart=True</span></code> keyword
|
||||
set by default - this means the script’s timer component will be started automatically. Otherwise
|
||||
<code class="docutils literal notranslate"><span class="pre">.start()</span></code> must be called separately.</p>
|
||||
<p>Supported properties are:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">key</span></code> (str): The name of the script. This makes it easier to search for it later. If it’s a script
|
||||
attached to another object one can also get all scripts off that object and get the script that way.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">desc</span></code> (str): Note - not <code class="docutils literal notranslate"><span class="pre">.db.desc</span></code>! This is a database field on the Script shown in script listings
|
||||
to help identifying what does what.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">interval</span></code> (int): The amount of time (in seconds) between every ‘tick’ of the timer. Note that
|
||||
it’s generally bad practice to use sub-second timers for anything in a text-game - the player will
|
||||
not be able to appreciate the precision (and if you print it, it will just spam the screen). For
|
||||
calculations you can pretty much always do them on-demand, or at a much slower interval without the
|
||||
player being the wiser.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">start_delay</span></code> (bool): If timer should start right away or wait <code class="docutils literal notranslate"><span class="pre">interval</span></code> seconds first.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">repeats</span></code> (int): If >0, the timer will only run this many times before stopping. Otherwise the
|
||||
number of repeats are infinite. If set to 1, the Script mimics a <code class="docutils literal notranslate"><span class="pre">delay</span></code> action.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">persistent</span></code> (bool): This defaults to <code class="docutils literal notranslate"><span class="pre">True</span></code> and means the timer will survive a server reload/reboot.
|
||||
If not, a reload will have the timer come back in a stopped state. Setting this to <code class="docutils literal notranslate"><span class="pre">False</span></code> will <em>not</em>
|
||||
delete the Script object itself (use <code class="docutils literal notranslate"><span class="pre">.delete()</span></code> for this).</p></li>
|
||||
</ul>
|
||||
<p>The timer component is controlled with methods on the Script class:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.at_repeat()</span></code> - this method is called every <code class="docutils literal notranslate"><span class="pre">interval</span></code> seconds while the timer is
|
||||
active.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.is_valid()</span></code> - this method is called by the timer just before <code class="docutils literal notranslate"><span class="pre">at_repeat()</span></code>. If it returns <code class="docutils literal notranslate"><span class="pre">False</span></code>
|
||||
the timer is immediately stopped.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.start()</span></code> - start/update the timer. If keyword arguments are given, they can be used to
|
||||
change <code class="docutils literal notranslate"><span class="pre">interval</span></code>, <code class="docutils literal notranslate"><span class="pre">start_delay</span></code> etc on the fly. This calls the <code class="docutils literal notranslate"><span class="pre">.at_start()</span></code> hook.
|
||||
This is also called after a server reload assuming the timer was not previously stopped.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.update()</span></code> - legacy alias for <code class="docutils literal notranslate"><span class="pre">.start</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.stop()</span></code> - stops and resets the timer. This calls the <code class="docutils literal notranslate"><span class="pre">.at_stop()</span></code> hook.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.pause()</span></code> - pauses the timer where it is, storing its current position. This calls
|
||||
the <code class="docutils literal notranslate"><span class="pre">.at_pause(manual_pause=True)</span></code> hook. This is also called on a server reload/reboot,
|
||||
at which time the <code class="docutils literal notranslate"><span class="pre">manual_pause</span></code> will be <code class="docutils literal notranslate"><span class="pre">False</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.unpause()</span></code> - unpause a previously paused script. This will call the <code class="docutils literal notranslate"><span class="pre">at_start</span></code> hook.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.time_until_next_repeat()</span></code> - get the time until next time the timer fires.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.remaining_repeats()</span></code> - get the number of repeats remaining, or <code class="docutils literal notranslate"><span class="pre">None</span></code> if repeats are infinite.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.reset_callcount()</span></code> - this resets the repeat counter to start over from 0. Only useful if <code class="docutils literal notranslate"><span class="pre">repeats>0</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.force_repeat()</span></code> - this prematurely forces <code class="docutils literal notranslate"><span class="pre">at_repeat</span></code> to be called right away. Doing so will reset the
|
||||
countdown so that next call will again happen after <code class="docutils literal notranslate"><span class="pre">interval</span></code> seconds.</p></li>
|
||||
</ul>
|
||||
<div class="section" id="script-timers-vs-delay-repeat">
|
||||
<h4>Script timers vs delay/repeat<a class="headerlink" href="#script-timers-vs-delay-repeat" title="Permalink to this headline">¶</a></h4>
|
||||
<p>If the <em>only</em> goal is to get a repeat/delay effect, the
|
||||
<a class="reference external" href="../api/evennia.utils.utils.html#evennia.utils.utils.delay">evennia.utils.delay</a> and
|
||||
<a class="reference external" href="../api/evennia.utils.utils.html#evennia.utils.utils.repeat">evennia.utils.repeat</a> functions
|
||||
should generally be considered first. A Script is a lot ‘heavier’ to create/delete on the fly.
|
||||
In fact, for making a single delayed call (<code class="docutils literal notranslate"><span class="pre">script.repeats==1</span></code>), the <code class="docutils literal notranslate"><span class="pre">utils.delay</span></code> call is
|
||||
probably always the better choice.</p>
|
||||
<p>For repeating tasks, the <code class="docutils literal notranslate"><span class="pre">utils.repeat</span></code> is optimized for quick repeating of a large number of objects. It
|
||||
uses the TickerHandler under the hood. Its subscription-based model makes it very efficient to
|
||||
start/stop the repeating action for an object. The side effect is however that all objects set to tick
|
||||
at a given interval will <em>all do so at the same time</em>. This may or may not look strange in-game depending
|
||||
on the situation. By contrast the Script uses its own ticker that will operate independently from the
|
||||
tickers of all other Scripts.</p>
|
||||
<p>It’s also worth noting that once the script object has <em>already been created</em>,
|
||||
starting/stopping/pausing/unpausing the timer has very little overhead. The pause/unpause and update
|
||||
methods of the script also offers a bit more fine-control than using <code class="docutils literal notranslate"><span class="pre">utils.delays/repeat</span></code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="script-attached-to-another-object">
|
||||
<h3>Script attached to another object<a class="headerlink" href="#script-attached-to-another-object" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Scripts can be attached to an <a class="reference internal" href="Accounts.html"><span class="doc">Account</span></a> or (more commonly) an <a class="reference internal" href="Objects.html"><span class="doc">Object</span></a>.
|
||||
If so, the ‘parent object’ will be available to the script as either <code class="docutils literal notranslate"><span class="pre">.obj</span></code> or <code class="docutils literal notranslate"><span class="pre">.account</span></code>.</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||||
2
|
||||
3
|
||||
|
|
@ -140,8 +339,7 @@ Here’s an example:</p>
|
|||
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>
|
||||
28</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># 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>
|
||||
|
|
@ -156,7 +354,6 @@ Here’s an example:</p>
|
|||
<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>
|
||||
|
|
@ -172,169 +369,91 @@ Here’s an example:</p>
|
|||
<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
|
||||
<p>If attached to a room, this Script 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>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">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>
|
||||
</td></tr></table></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>
|
||||
<p>You can also attach the script as part of creating it:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">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="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>
|
||||
</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>
|
||||
<div class="section" id="other-script-methods">
|
||||
<h2>Other Script methods<a class="headerlink" href="#other-script-methods" 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_script_creation()</span></code> - this is only called once - when the script is first created.</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
|
||||
<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>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_server_start()</span></code> - this is called when the server comes back (from reload/shutdown/reboot). It
|
||||
can be usuful for initializations and caching of non-persistent data when starting up a script’s
|
||||
functionality.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_repeat()</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_start()</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_pause()</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_stop()</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">delete()</span></code> - same as for other typeclassed entities, this will delete the Script. Of note is that
|
||||
it will also stop the timer (if it runs), leading to the <code class="docutils literal notranslate"><span class="pre">at_stop</span></code> hook being called.</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>
|
||||
<p>In addition, Scripts support <a class="reference internal" href="Attributes.html"><span class="doc">Attributes</span></a>, <a class="reference internal" href="Tags.html"><span class="doc">Tags</span></a> and <a class="reference internal" href="Locks.html"><span class="doc">Locks</span></a> etc like other
|
||||
Typeclassed entities.</p>
|
||||
<p>See also the methods involved in controlling a <a class="reference external" href="#Timed_Scripts">Timed Script</a> above.</p>
|
||||
</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="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>
|
||||
</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>
|
||||
<div class="section" id="the-global-scripts-container">
|
||||
<h2>The GLOBAL_SCRIPTS container<a class="headerlink" href="#the-global-scripts-container" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A Script not attached to another entity is commonly referred to as a <em>Global</em> script since it’t available
|
||||
to access from anywhere. This means they need to be searched for in order to be used.</p>
|
||||
<p>Evennia supplies a convenient “container” <code class="docutils literal notranslate"><span class="pre">evennia.GLOBAL_SCRIPTS</span></code> to help organize your global
|
||||
scripts. All you need is the Script’s <code class="docutils literal notranslate"><span class="pre">key</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</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"># access as a property on the container, named the same as the key</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="c1"># get all global scripts (this returns a Django 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
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<p>Note that global scripts appear as properties on <cite>GLOBAL_SCRIPTS</cite> based on their <cite>key</cite>.
|
||||
If you were to create two global scripts with the same <cite>key</cite> (even with different typeclasses),
|
||||
the <cite>GLOBAL_SCRIPTS</cite> 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>
|
||||
<cite>evennia.search_scripts</cite> to get exactly the script you want.</p>
|
||||
</div>
|
||||
<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>:</p>
|
||||
<ol class="simple">
|
||||
<li><p>Manually create a new global script with a <code class="docutils literal notranslate"><span class="pre">key</span></code> using <code class="docutils literal notranslate"><span class="pre">create_script</span></code>.</p></li>
|
||||
<li><p>Define the script’s properties in the <code class="docutils literal notranslate"><span class="pre">GLOBAL_SCRIPTS</span></code> settings variable. This tells Evennia
|
||||
that it should check if a script with that <code class="docutils literal notranslate"><span class="pre">key</span></code> exists and if not, create it for you.
|
||||
This is very useful for scripts that must always exist and/or should be auto-created with your server.</p></li>
|
||||
</ol>
|
||||
<p>Here’s how to tell Evennia to manage the script in settings:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||||
2
|
||||
3
|
||||
|
|
@ -345,36 +464,30 @@ to happen automatically when the server starts though. For this you can use the
|
|||
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>
|
||||
11</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/server/conf/settings.py</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="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">"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="s2">"storagescript"</span><span class="p">:</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>Above we add two scripts with keys <code class="docutils literal notranslate"><span class="pre">myscript</span></code> and <code class="docutils literal notranslate"><span class="pre">storagescript</span></code>respectively. The following dict
|
||||
can be empty - the <code class="docutils literal notranslate"><span class="pre">settings.BASE_SCRIPT_TYPECLASS</span></code> will then be used. Under the hood, the provided
|
||||
dict (along with the <code class="docutils literal notranslate"><span class="pre">key</span></code>) will be passed into <code class="docutils literal notranslate"><span class="pre">create_script</span></code> automatically, so
|
||||
all the <a class="reference external" href="../api/evennia.utils.create.create_script.html">same keyword arguments as for create_script</a> are
|
||||
supported here.</p>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<p>Before setting up Evennia to manage your script like this, make sure that your Script typeclass
|
||||
does not have any critical errors (test it separately). If there are, you’ll see errors in your log
|
||||
and your Script will temporarily fall back to being a <cite>DefaultScript</cite> type.</p>
|
||||
</div>
|
||||
<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
|
||||
|
|
@ -382,26 +495,19 @@ errors in your log and your Script will temporarily fall back to being a <code c
|
|||
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"># Delete 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">delete</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="c1"># but below it's automatically 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>
|
||||
<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>, Evennia will use the
|
||||
information in settings to recreate it for you on the fly.</p>
|
||||
</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
|
||||
<div class="section" id="hints-dealing-with-script-errors">
|
||||
<h2>Hints: Dealing with Script Errors<a class="headerlink" href="#hints-dealing-with-script-errors" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Errors inside a 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
|
||||
|
|
@ -418,54 +524,22 @@ traceback occurred in your script.</p>
|
|||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15</pre></div></td><td class="code"><div class="highlight"><pre><span></span>
|
||||
13</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="k">class</span> <span class="nc">Weather</span><span class="p">(</span><span class="n">Script</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="c1"># [...]</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>
|
||||
|
||||
|
||||
|
|
@ -491,11 +565,20 @@ tutorial</a>.</p>
|
|||
<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>
|
||||
<li><a class="reference internal" href="#in-game-command-examples">In-game command examples</a></li>
|
||||
<li><a class="reference internal" href="#code-examples">Code examples</a></li>
|
||||
<li><a class="reference internal" href="#defining-new-scripts">Defining new Scripts</a><ul>
|
||||
<li><a class="reference internal" href="#simple-storage-script">Simple storage script</a></li>
|
||||
<li><a class="reference internal" href="#timed-scripts">Timed Scripts</a><ul>
|
||||
<li><a class="reference internal" href="#script-timers-vs-delay-repeat">Script timers vs delay/repeat</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#script-attached-to-another-object">Script attached to another object</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#other-script-methods">Other Script methods</a></li>
|
||||
<li><a class="reference internal" href="#the-global-scripts-container">The GLOBAL_SCRIPTS container</a></li>
|
||||
<li><a class="reference internal" href="#hints-dealing-with-script-errors">Hints: Dealing with Script Errors</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue