traverses through this exit. Events are described on a <aclass="reference internal"href="../Components/Typeclasses.html"><spanclass="std std-doc">typeclass</span></a>
(<aclass="reference internal"href="../Components/Exits.html"><spanclass="std std-doc">exits</span></a> in our example). All objects inheriting from this
<li><p>The event “get” is set on objects (on the <codeclass="docutils literal notranslate"><spanclass="pre">Object</span></code> typeclass).</p></li>
<li><p>When using the “get” command to pick up an object, this object’s <codeclass="docutils literal notranslate"><spanclass="pre">at_get</span></code>
hook is called.</p></li>
<li><p>A modified hook of DefaultObject is set by the event system. This hook will
execute (or call) the “get” event on this object.</p></li>
<li><p>All callbacks tied to this object’s “get” event will be executed in order.
These callbacks act as functions containing Python code that you can write
in-game, using specific variables that will be listed when you edit the callback
itself.</p></li>
<li><p>In individual callbacks, you can add multiple lines of Python code that will
be fired at this point. In this example, the <codeclass="docutils literal notranslate"><spanclass="pre">character</span></code> variable will
contain the character who has picked up the object, while <codeclass="docutils literal notranslate"><spanclass="pre">obj</span></code> will contain the
object that was picked up.</p></li>
</ol>
<p>Following this example, if you create a callback “get” on the object “a sword”,
and put in it:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="n">character</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You have picked up </span><spanclass="si">{}</span><spanclass="s2"> and have completed this quest!"</span><spanclass="o">.</span><spanclass="n">format</span><spanclass="p">(</span><spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">get_display_name</span><spanclass="p">(</span><spanclass="n">character</span><spanclass="p">)))</span>
</pre></div>
</div>
<p>When you pick up this object you should see something like:</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>You pick up a sword.
You have picked up a sword and have completed this quest!
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">EVENTS_WITH_VALIDATION</span></code>: a group that can edit callbacks, but will need approval (default to
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">EVENTS_WITHOUT_VALIDATION</span></code>: a group with permission to edit callbacks without need of
validation (default to <codeclass="docutils literal notranslate"><spanclass="pre">"immortals"</span></code>).</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">EVENTS_VALIDATING</span></code>: a group that can validate callbacks (default to <codeclass="docutils literal notranslate"><spanclass="pre">"immortals"</span></code>).</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">EVENTS_CALENDAR</span></code>: type of the calendar to be used (either <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">"standard"</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">"custom"</span></code>,
default to <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>).</p></li>
</ul>
</li>
<li><p>Add the <codeclass="docutils literal notranslate"><spanclass="pre">call</span></code> command.</p></li>
<li><p>Inherit from the custom typeclasses of the in-game Python system.</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">evennia.contrib.base_systems.ingame_python.typeclasses.EventCharacter</span></code>: to replace <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">evennia.contrib.base_systems.ingame_python.typeclasses.EventExit</span></code>: to replace <codeclass="docutils literal notranslate"><spanclass="pre">DefaultExit</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">evennia.contrib.base_systems.ingame_python.typeclasses.EventObject</span></code>: to replace <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">evennia.contrib.base_systems.ingame_python.typeclasses.EventRoom</span></code>: to replace <codeclass="docutils literal notranslate"><spanclass="pre">DefaultRoom</span></code>.</p></li>
</ul>
</li>
</ol>
<p>The following sections describe in details each step of the installation.</p>
<blockquote>
<div><p>Note: If you were to start the game without having started the main script (such as when
resetting your database) you will most likely face a traceback when logging in, telling you
that a ‘callback’ property is not defined. After performing step <codeclass="docutils literal notranslate"><spanclass="pre">1</span></code> the error will go away.</p>
<p>To start the event script, you only need a single command, using <codeclass="docutils literal notranslate"><spanclass="pre">@py</span></code>.</p>
<p>This command will create a global script (that is, a script independent from any object). This
script will hold basic configuration, individual callbacks and so on. You may access it directly,
but you will probably use the callback handler. Creating this script will also create a <codeclass="docutils literal notranslate"><spanclass="pre">callback</span></code>
handler on all objects (see below for details).</p>
<p>The ingame-python contrib adds three <aclass="reference internal"href="../Components/Permissions.html"><spanclass="std std-doc">permissions</span></a>) in the settings. You can
override them by changing the settings into your <codeclass="docutils literal notranslate"><spanclass="pre">server/conf/settings.py</span></code> file (see below for an
example). The settings defined in the events contrib are:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">EVENTS_WITH_VALIDATION</span></code>: this defines a permission that can edit callbacks, but will need
approval. If you set this to <codeclass="docutils literal notranslate"><spanclass="pre">"wizards"</span></code>, for instance, users with the permission <codeclass="docutils literal notranslate"><spanclass="pre">"wizards"</span></code>
will be able to edit callbacks. These callbacks will not be connected, though, and will need to be
checked and approved by an administrator. This setting can contain <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>, meaning that no user is
allowed to edit callbacks with validation.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">EVENTS_WITHOUT_VALIDATION</span></code>: this setting defines a permission allowing editing of callbacks
without needing validation. By default, this setting is set to <codeclass="docutils literal notranslate"><spanclass="pre">"immortals"</span></code>. It means that
immortals can edit callbacks, and they will be connected when they leave the editor, without needing
approval.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">EVENTS_VALIDATING</span></code>: this last setting defines who can validate callbacks. By default, this is
set to <codeclass="docutils literal notranslate"><spanclass="pre">"immortals"</span></code>, meaning only immortals can see callbacks needing validation, accept or
reject them.</p></li>
</ul>
<p>You can override all these settings in your <codeclass="docutils literal notranslate"><spanclass="pre">server/conf/settings.py</span></code> file. For instance:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># ... other settings ...</span>
<p>In addition, there is another setting that must be set if you plan on using the time-related events
(events that are scheduled at specific, in-game times). You would need to specify the type of
calendar you are using. By default, time-related events are disabled. You can change the
<codeclass="docutils literal notranslate"><spanclass="pre">EVENTS_CALENDAR</span></code> to set it to:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">"standard"</span></code>: the standard calendar, with standard days, months, years and so on.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">"custom"</span></code>: a custom calendar that will use the <codeclass="docutils literal notranslate"><spanclass="pre">custom_gametime</span></code> contrib to schedule events.</p></li>
</ul>
<p>This contrib defines two additional permissions that can be set on individual users:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">events_without_validation</span></code>: this would give this user the rights to edit callbacks but not
require validation before they are connected.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">events_validating</span></code>: this permission allows this user to run validation checks on callbacks
needing to be validated.</p></li>
</ul>
<p>For instance, to give the right to edit callbacks without needing approval to the player ‘kaldara’,
<p>The rights to use the <codeclass="docutils literal notranslate"><spanclass="pre">call</span></code> command are directly related to these permissions: by default, only
users who have the <codeclass="docutils literal notranslate"><spanclass="pre">events_without_validation</span></code> permission or are in (or above) the group defined in
the <codeclass="docutils literal notranslate"><spanclass="pre">EVENTS_WITH_VALIDATION</span></code> setting will be able to call the command (with different switches).</p>
<h3>Adding the <codeclass="docutils literal notranslate"><spanclass="pre">call</span></code> command<aclass="headerlink"href="#adding-the-call-command"title="Link to this heading">¶</a></h3>
<p>You also have to add the <codeclass="docutils literal notranslate"><spanclass="pre">@call</span></code> command to your Character CmdSet. This command allows your users
to add, edit and delete callbacks in-game. In your <codeclass="docutils literal notranslate"><spanclass="pre">commands/default_cmdsets</span></code>, it might look like
<p>Finally, to use the in-game Python system, you need to have your typeclasses inherit from the modified event
classes. For instance, in your <codeclass="docutils literal notranslate"><spanclass="pre">typeclasses/characters.py</span></code> module, you should change inheritance
<h2>Using the <codeclass="docutils literal notranslate"><spanclass="pre">call</span></code> command<aclass="headerlink"href="#using-the-call-command"title="Link to this heading">¶</a></h2>
<p>The in-game Python system relies, to a great extent, on its <codeclass="docutils literal notranslate"><spanclass="pre">call</span></code> command.
Who can execute this command, and who can do what with it, will depend on your
set of permissions.</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">call</span></code> command allows to add, edit and delete callbacks on specific objects’ events. The event
system can be used on most Evennia objects, mostly typeclassed objects (excluding players). The
first argument of the <codeclass="docutils literal notranslate"><spanclass="pre">call</span></code> command is the name of the object you want to edit. It can also be
used to know what events are available for this specific object.</p>
<p>To see the events connected to an object, use the <codeclass="docutils literal notranslate"><spanclass="pre">call</span></code> command and give the name or ID of the
object to examine. For instance, <codeclass="docutils literal notranslate"><spanclass="pre">call</span><spanclass="pre">here</span></code> to examine the events on your current location. Or
<codeclass="docutils literal notranslate"><spanclass="pre">call</span><spanclass="pre">self</span></code> to see the events on yourself.</p>
<p>This command will display a table, containing:</p>
<ulclass="simple">
<li><p>The name of each event in the first column.</p></li>
<li><p>The number of callbacks of this name, and the number of total lines of these callbacks in the
second column.</p></li>
<li><p>A short help to tell you when the event is triggered in the third column.</p></li>
</ul>
<p>If you execute <codeclass="docutils literal notranslate"><spanclass="pre">call</span><spanclass="pre">#1</span></code> for instance, you might see a table like this:</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">/add</span></code> switch should be used to add a callback. It takes two arguments beyond the object’s
<p>The section dedicated to <aclass="reference internal"href="#the-eventfuncs">eventfuncs</a> will elaborate on the <codeclass="docutils literal notranslate"><spanclass="pre">deny()</span></code> function and
<spanclass="n">character</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You're the superuser, 'course I'll let you pass."</span><spanclass="p">)</span>
<spanclass="k">else</span><spanclass="p">:</span>
<spanclass="n">character</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"Hold on, what do you think you're doing?"</span><spanclass="p">)</span>
<p>You can now enter <codeclass="docutils literal notranslate"><spanclass="pre">:wq</span></code> to leave the editor by saving the callback.</p>
<p>If you enter <codeclass="docutils literal notranslate"><spanclass="pre">call</span><spanclass="pre">north</span></code>, you should see that “can_traverse” now has an active callback. You can
use <codeclass="docutils literal notranslate"><spanclass="pre">call</span><spanclass="pre">north</span><spanclass="pre">=</span><spanclass="pre">can_traverse</span></code> to see more details on the connected callbacks:</p>
<spanclass="n">character</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You're the superuser, 'course I'll let you pass."</span><spanclass="p">)</span>
<spanclass="k">else</span><spanclass="p">:</span>
<spanclass="n">character</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"Hold on, what do you think you're doing?"</span><spanclass="p">)</span>
<p>You can use the <codeclass="docutils literal notranslate"><spanclass="pre">/edit</span></code> switch to the <codeclass="docutils literal notranslate"><spanclass="pre">@call</span></code> command to edit a callback. You should provide, after
the name of the object to edit and the equal sign:</p>
<li><p>The name of the event (as seen above).</p></li>
<li><p>A number, if several callbacks are connected at this location.</p></li>
</ol>
<p>You can type <codeclass="docutils literal notranslate"><spanclass="pre">call/edit</span><spanclass="pre"><object></span><spanclass="pre">=</span><spanclass="pre"><event</span><spanclass="pre">name></span></code> to see the callbacks that are linked at this
location. If there is only one callback, it will be opened in the editor; if more are defined, you
will be asked for a number to provide (for instance, <codeclass="docutils literal notranslate"><spanclass="pre">call/edit</span><spanclass="pre">north</span><spanclass="pre">=</span><spanclass="pre">can_traverse</span><spanclass="pre">2</span></code>).</p>
<p>The command <codeclass="docutils literal notranslate"><spanclass="pre">call</span></code> also provides a <codeclass="docutils literal notranslate"><spanclass="pre">/del</span></code> switch to remove a callback. It takes the same arguments
as the <codeclass="docutils literal notranslate"><spanclass="pre">/edit</span></code> switch.</p>
<p>When removed, callbacks are logged, so an administrator can retrieve its content, assuming the
<codeclass="docutils literal notranslate"><spanclass="pre">/del</span></code> was an error.</p>
<p>When adding or editing a callback, the event editor should open in code mode. The additional
options supported by the editor in this mode are describe in <aclass="reference external"href="https://github.com/evennia/evennia/wiki/EvEditor#the-eveditor-to-edit-code">a dedicated section of the EvEditor’s
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">deny()</span></code> function allows to interrupt the callback and the action that called it. In the
<codeclass="docutils literal notranslate"><spanclass="pre">can_*</span></code> events, it can be used to prevent the action from happening. For instance, in <codeclass="docutils literal notranslate"><spanclass="pre">can_say</span></code> on
rooms, it can prevent the character from saying something in the room. One could have a <codeclass="docutils literal notranslate"><spanclass="pre">can_eat</span></code>
event set on food that would prevent this character from eating this food.</p>
<p>Behind the scenes, the <codeclass="docutils literal notranslate"><spanclass="pre">deny()</span></code> function raises an exception that is being intercepted by the
handler of events. The handler will then report that the action was cancelled.</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">get</span></code> eventfunc is a shortcut to get a single object with a specific identity. It’s often used
<p>In the Python code you will enter in individual callbacks, you will have access to variables in your
locals. These variables will depend on the event, and will be clearly listed when you add or edit a
callback. As you’ve seen in the previous example, when we manipulate characters or character
actions, we often have a <codeclass="docutils literal notranslate"><spanclass="pre">character</span></code> variable that holds the character doing the action.</p>
<p>In most cases, when an event is fired, all callbacks from this event are called. Variables are
created for each event. Sometimes, however, the callback will execute and then ask for a variable
in your locals: in other words, some callbacks can alter the actions being performed by changing
values of variables. This is always clearly specified in the help of the event.</p>
<p>One example that will illustrate this system is the “msg_leave” event that can be set on exits.
This event can alter the message that will be sent to other characters when someone leaves through
this exit.</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>call/add down = msg_leave
<spanclass="n">message</span><spanclass="o">=</span><spanclass="s2">"</span><spanclass="si">{character}</span><spanclass="s2"> falls into a hole!"</span>
<p>If you write something like this in your event:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="n">message</span><spanclass="o">=</span><spanclass="s2">"</span><spanclass="si">{character}</span><spanclass="s2"> falls into a hole in the ground!"</span>
</pre></div>
</div>
<p>And if the character Wilfred takes this exit, others in the room will see:</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>Wildred falls into a hole in the ground!
</pre></div>
</div>
<p>In this case, the in-game Python system placed the variable “message” in the callback locals, but will read
<p>Events are usually linked to commands, as we saw before. However, this is not always the case.
Events can be triggered by other actions and, as we’ll see later, could even be called from inside
other events!</p>
<p>There is a specific event, on all objects, that can trigger at a specific time. It’s an event with
a mandatory parameter, which is the time you expect this event to fire.</p>
<p>For instance, let’s add an event on this room that should trigger every day, at precisely 12:00 PM
(the time is given as game time, not real time):</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>call here = time 12:00
</pre></div>
</div>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># This will be called every MUD day at 12:00 PM</span>
<spanclass="n">room</span><spanclass="o">.</span><spanclass="n">msg_contents</span><spanclass="p">(</span><spanclass="s2">"It's noon, time to have lunch!"</span><spanclass="p">)</span>
</pre></div>
</div>
<p>Now, at noon every MUD day, this event will fire and this callback will be executed. You can use
this event on every kind of typeclassed object, to have a specific action done every MUD day at the
same time.</p>
<p>Time-related events can be much more complex than this. They can trigger every in-game hour or more
often (it might not be a good idea to have events trigger that often on a lot of objects). You can
have events that run every in-game week or month or year. It will greatly vary depending on the
type of calendar used in your game. The number of time units is described in the game
configuration.</p>
<p>With a standard calendar, for instance, you have the following units: minutes, hours, days, months
and years. You will specify them as numbers separated by either a colon (:), a space ( ), or a dash
(-). Pick whatever feels more appropriate (usually, we separate hours and minutes with a colon, the
other units with a dash).</p>
<p>Some examples of syntax:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">18:30</span></code>: every day at 6:30 PM.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">01</span><spanclass="pre">12:00</span></code>: every month, the first day, at 12 PM.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">06-15</span><spanclass="pre">09:58</span></code>: every year, on the 15th of June (month comes before day), at 9:58 AM.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">2025-01-01</span><spanclass="pre">00:00</span></code>: January 1st, 2025 at midnight (obviously, this will trigger only once).</p></li>
</ul>
<p>Notice that we specify units in the reverse order (year, month, day, hour and minute) and separate
them with logical separators. The smallest unit that is not defined is going to set how often the
event should fire. That’s why, if you use <codeclass="docutils literal notranslate"><spanclass="pre">12:00</span></code>, the smallest unit that is not defined is “day”:
the event will fire every day at the specified time.</p>
<blockquote>
<div><p>You can use chained events (see below) in conjunction with time-related events to create more
<p>Callbacks can call other events, either now or a bit later. It is potentially very powerful.</p>
<p>To use chained events, just use the <codeclass="docutils literal notranslate"><spanclass="pre">call_event</span></code> eventfunc. It takes 2-3 arguments:</p>
<ulclass="simple">
<li><p>The object containing the event.</p></li>
<li><p>The name of the event to call.</p></li>
<li><p>Optionally, the number of seconds to wait before calling this event.</p></li>
</ul>
<p>All objects have events that are not triggered by commands or game-related operations. They are
called “chain_X”, like “chain_1”, “chain_2”, “chain_3” and so on. You can give them more specific
names, as long as it begins by “chain_”, like “chain_flood_room”.</p>
<p>Rather than a long explanation, let’s look at an example: a subway that will go from one place to
the next at regular times. Connecting exits (opening its doors), waiting a bit, closing them,
rolling around and stopping at a different station. That’s quite a complex set of callbacks, as it
is, but let’s only look at the part that opens and closes the doors:</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>call/add here = time 10:00
</pre></div>
</div>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># At 10:00 AM, the subway arrives in the room of ID 22.</span>
<spanclass="c1"># Notice that exit #23 and #24 are respectively the exit leading</span>
<spanclass="c1"># on the platform and back in the subway.</span>
<spanclass="n">room</span><spanclass="o">.</span><spanclass="n">msg_contents</span><spanclass="p">(</span><spanclass="s2">"The doors open and wind gushes in the subway"</span><spanclass="p">)</span>
<spanclass="n">station</span><spanclass="o">.</span><spanclass="n">msg_contents</span><spanclass="p">(</span><spanclass="s2">"The doors of the subway open with a dull clank."</span><spanclass="p">)</span>
<spanclass="c1"># Set the doors to close in 20 seconds</span>
<spanclass="n">room</span><spanclass="o">.</span><spanclass="n">msg_content</span><spanclass="p">(</span><spanclass="s2">"After a short warning signal, the doors close and the subway begins moving."</span><spanclass="p">)</span>
<spanclass="n">station</span><spanclass="o">.</span><spanclass="n">msg_content</span><spanclass="p">(</span><spanclass="s2">"After a short warning signal, the doors close and the subway begins moving."</span><spanclass="p">)</span>
</pre></div>
</div>
<p>Behind the scenes, the <codeclass="docutils literal notranslate"><spanclass="pre">call_event</span></code> function freezes all variables (“room”, “station”, “to_exit”,
“back_exit” in our example), so you don’t need to define them again.</p>
<p>A word of caution on callbacks that call chained events: it isn’t impossible for a callback to call
itself at some recursion level. If <codeclass="docutils literal notranslate"><spanclass="pre">chain_1</span></code> calls <codeclass="docutils literal notranslate"><spanclass="pre">chain_2</span></code> that calls <codeclass="docutils literal notranslate"><spanclass="pre">chain_3</span></code> that calls
<codeclass="docutils literal notranslate"><spanclass="pre">chain_</span></code>, particularly if there’s no pause between them, you might run into an infinite loop.</p>
<p>Be also careful when it comes to handling characters or objects that may very well move during your
pause between event calls. When you use <codeclass="docutils literal notranslate"><spanclass="pre">call_event()</span></code>, the MUD doesn’t pause and commands can be
entered by players, fortunately. It also means that, a character could start an event that pauses
for awhile, but be gone when the chained event is called. You need to check that, even lock the
character into place while you are pausing (some actions should require locking) or at least,
checking that the character is still in the room, for it might create illogical situations if you
don’t.</p>
<blockquote>
<div><p>Chained events are a special case: contrary to standard events, they are created in-game, not
through code. They usually contain only one callback, although nothing prevents you from creating
<p>Adding new events should be done in your typeclasses. Events are contained in the <codeclass="docutils literal notranslate"><spanclass="pre">_events</span></code> class
variable, a dictionary of event names as keys, and tuples to describe these events as values. You
also need to register this class, to tell the in-game Python system that it contains events to be added to
this typeclass.</p>
<p>Here, we want to add a “push” event on objects. In your <codeclass="docutils literal notranslate"><spanclass="pre">typeclasses/objects.py</span></code> file, you should
<li><p>Line 1-2: we import several things we will need from the in-game Python system. Note that we use
<codeclass="docutils literal notranslate"><spanclass="pre">EventObject</span></code> as a parent instead of <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code>, as explained in the installation.</p></li>
<li><p>Line 4-12: we usually define the help of the event in a separate variable, this is more readable,
though there’s no rule against doing it another way. Usually, the help should contain a short
explanation on a single line, a longer explanation on several lines, and then the list of variables
with explanations.</p></li>
<li><p>Line 14: we call a decorator on the class to indicate it contains events. If you’re not familiar
with decorators, you don’t really have to worry about it, just remember to put this line just
above the class definition if your class contains events.</p></li>
<li><p>Line 15: we create the class inheriting from <codeclass="docutils literal notranslate"><spanclass="pre">EventObject</span></code>.</p></li>
<li><p>Line 20-22: we define the events of our objects in an <codeclass="docutils literal notranslate"><spanclass="pre">_events</span></code> class variable. It is a
dictionary. Keys are event names. Values are a tuple containing:</p>
<ul>
<li><p>The list of variable names (list of str). This will determine what variables are needed when
the event triggers. These variables will be used in callbacks (as we’ll see below).</p></li>
<li><p>The event help (a str, the one we have defined above).</p></li>
</ul>
</li>
</ul>
<p>If you add this code and reload your game, create an object and examine its events with <codeclass="docutils literal notranslate"><spanclass="pre">@call</span></code>, you
should see the “push” event with its help. Of course, right now, the event exists, but it’s not
<p>The in-game Python system is accessible through a handler on all objects. This handler is named <codeclass="docutils literal notranslate"><spanclass="pre">callbacks</span></code>
and can be accessed from any typeclassed object (your character, a room, an exit…). This handler
offers several methods to examine and call an event or callback on this object.</p>
<p>To call an event, use the <codeclass="docutils literal notranslate"><spanclass="pre">callbacks.call</span></code> method in an object. It takes as argument:</p>
<ulclass="simple">
<li><p>The name of the event to call.</p></li>
<li><p>All variables that will be accessible in the event as positional arguments. They should be
<p>Here we use <codeclass="docutils literal notranslate"><spanclass="pre">callbacks.call</span></code> with the following arguments:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">"push"</span></code>: the name of the event to be called.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">self.caller</span></code>: the one who pushed the button (this is our first variable, <codeclass="docutils literal notranslate"><spanclass="pre">character</span></code>).</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">obj</span></code>: the object being pushed (our second variable, <codeclass="docutils literal notranslate"><spanclass="pre">obj</span></code>).</p></li>
</ul>
<p>In the “push” callbacks of our objects, we then can use the “character” variable (containing the one
who pushed the object), and the “obj” variable (containing the object that was pushed).</p>
<spanclass="n">character</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"The rock topples over to reveal a beautiful ant-hill!"</span><spanclass="p">)</span>
</pre></div>
</div>
<p>You can now try to “push rock”. You’ll try to push the rock, and once out of six times, you will
<p>Eventfuncs, like <codeclass="docutils literal notranslate"><spanclass="pre">deny()</span></code>, are defined in
<codeclass="docutils literal notranslate"><spanclass="pre">contrib/base_systesm/ingame_python/eventfuncs.py</span></code>. You can add your own
eventfuncs by creating a file named <codeclass="docutils literal notranslate"><spanclass="pre">eventfuncs.py</span></code> in your <codeclass="docutils literal notranslate"><spanclass="pre">world</span></code> directory.
The functions defined in this file will be added as helpers.</p>
<p>You can also decide to create your eventfuncs in another location, or even in
several locations. To do so, edit the <codeclass="docutils literal notranslate"><spanclass="pre">EVENTFUNCS_LOCATION</span></code> setting in your
<codeclass="docutils literal notranslate"><spanclass="pre">server/conf/settings.py</span></code> file, specifying either a python path or a list of
Python paths in which your helper functions are defined. For instance:</p>
<p>If you want to create events with parameters (if you create a “whisper” or “ask” command, for
instance, and need to have some characters automatically react to words), you can set an additional
argument in the tuple of events in your typeclass’<codeclass="docutils literal notranslate"><spanclass="pre">_events</span></code> class variable. This third argument
must contain a callback that will be called to filter through the list of callbacks when the event
fires. Two types of parameters are commonly used (but you can define more parameter types, although
this is out of the scope of this documentation).</p>
<ulclass="simple">
<li><p>Keyword parameters: callbacks of this event will be filtered based on specific keywords. This is
useful if you want the user to specify a word and compare this word to a list.</p></li>
<li><p>Phrase parameters: callbacks will be filtered using an entire phrase and checking all its words.
The “say” command uses phrase parameters (you can set a “say” callback to fires if a phrase
contains one specific word).</p></li>
</ul>
<p>In both cases, you need to import a function from
<codeclass="docutils literal notranslate"><spanclass="pre">evennia.contrib.base_systems.ingame_python.utils</span></code> and use it as third parameter in your
event definition.</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">keyword_event</span></code> should be used for keyword parameters.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">phrase_event</span></code> should be used for phrase parameters.</p></li>
</ul>
<p>For example, here is the definition of the “say” event:</p>
<p>When you call an event using the <codeclass="docutils literal notranslate"><spanclass="pre">obj.callbacks.call</span></code> method, you should also provide the parameter,
using the <codeclass="docutils literal notranslate"><spanclass="pre">parameters</span></code> keyword:</p>
<p>The in-game Python system will still be accessible (you will have access to the <codeclass="docutils literal notranslate"><spanclass="pre">call</span></code> command, to debug),
but no event will be called automatically.</p>
<divclass="toctree-wrapper compound">
</div>
<hrclass="docutils"/>
<p><small>This document page is generated from <codeclass="docutils literal notranslate"><spanclass="pre">evennia/contrib/base_systems/ingame_python/README.md</span></code>. Changes to this
file will be overwritten, so edit that file rather than this one.</small></p>