<p>This is a small tutorial for customizing your character objects, using the example of letting users
turn on and off ANSI color parsing as an example. <codeclass="docutils literal notranslate"><spanclass="pre">@options</span><spanclass="pre">NOCOLOR=True</span></code> will now do what this
tutorial shows, but the tutorial subject can be applied to other toggles you may want, as well.</p>
<p>In the Building guide’s <aclass="reference external"href="TextTags.html#coloured-text">Colors</a> page you can learn how to add color to your
game by using special markup. Colors enhance the gaming experience, but not all users want color.
Examples would be users working from clients that don’t support color, or people with various seeing
disabilities that rely on screen readers to play your game. Also, whereas Evennia normally
automatically detects if a client supports color, it may get it wrong. Being able to turn it on
manually if you know it <strong>should</strong> work could be a nice feature.</p>
<p>So here’s how to allow those users to remove color. It basically means you implementing a simple
configuration system for your characters. This is the basic sequence:</p>
<li><p>Define your own default character typeclass, inheriting from Evennia’s default.</p></li>
<li><p>Set an attribute on the character to control markup on/off.</p></li>
<li><p>Set your custom character class to be the default for new accounts.</p></li>
<li><p>Overload the <codeclass="docutils literal notranslate"><spanclass="pre">msg()</span></code> method on the typeclass and change how it uses markup.</p></li>
<li><p>Create a custom command to allow users to change their setting.</p></li>
<p>Create a new module in <codeclass="docutils literal notranslate"><spanclass="pre">mygame/typeclasses</span></code> named, for example, <codeclass="docutils literal notranslate"><spanclass="pre">mycharacter.py</span></code>. Alternatively you
can simply add a new class to ‘mygamegame/typeclasses/characters.py’.</p>
<p>In your new module(or characters.py), create a new <aclass="reference internal"href="Typeclasses.html"><spanclass="doc">Typeclass</span></a> inheriting from
<codeclass="docutils literal notranslate"><spanclass="pre">evennia.DefaultCharacter</span></code>. We will also import <codeclass="docutils literal notranslate"><spanclass="pre">evennia.utils.ansi</span></code>, which we will use later.</p>
<p>Let’s make sure that new characters are created of this type. Edit your
<codeclass="docutils literal notranslate"><spanclass="pre">mygame/server/conf/settings.py</span></code> file and add/change <codeclass="docutils literal notranslate"><spanclass="pre">BASE_CHARACTER_TYPECLASS</span></code> to point to your new
character class. Observe that this will only affect <em>new</em> characters, not those already created. You
have to convert already created characters to the new typeclass by using the <codeclass="docutils literal notranslate"><spanclass="pre">@typeclass</span></code> command
(try on a secondary character first though, to test that everything works - you don’t want to render
<p><codeclass="docutils literal notranslate"><spanclass="pre">@typeclass</span></code> changes Bob’s typeclass and runs all its creation hooks all over again. The <codeclass="docutils literal notranslate"><spanclass="pre">/reset</span></code>
switch clears all attributes and properties back to the default for the new typeclass - this is
useful in this case to avoid ending up with an object having a “mixture” of properties from the old
typeclass and the new one. <codeclass="docutils literal notranslate"><spanclass="pre">/force</span></code> might be needed if you edit the typeclass and want to update the
object despite the actual typeclass name not having changed.</p>
<h2>Overload the <codeclass="docutils literal notranslate"><spanclass="pre">msg()</span></code> method<aclass="headerlink"href="#overload-the-msg-method"title="Permalink to this headline">¶</a></h2>
<p>Next we need to overload the <codeclass="docutils literal notranslate"><spanclass="pre">msg()</span></code> method. What we want is to check the configuration value before
calling the main function. The original <codeclass="docutils literal notranslate"><spanclass="pre">msg</span></code> method call is seen in <codeclass="docutils literal notranslate"><spanclass="pre">evennia/objects/objects.py</span></code>
<spanclass="k">if</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">config_color</span><spanclass="ow">is</span><spanclass="ow">not</span><spanclass="bp">None</span><spanclass="p">:</span><spanclass="c1"># this would mean it was not set</span>
<p>Above we create a custom version of the <codeclass="docutils literal notranslate"><spanclass="pre">msg()</span></code> method. If the configuration Attribute is set, it
strips the ANSI from the text it is about to send, and then calls the parent <codeclass="docutils literal notranslate"><spanclass="pre">msg()</span></code> as usual. You
need to <codeclass="docutils literal notranslate"><spanclass="pre">@reload</span></code> before your changes become visible.</p>
<p>There we go! Just flip the attribute <codeclass="docutils literal notranslate"><spanclass="pre">config_color</span></code> to False and your users will not see any color.
As superuser (assuming you use the Typeclass <codeclass="docutils literal notranslate"><spanclass="pre">ColorableCharacter</span></code>) you can test this with the <codeclass="docutils literal notranslate"><spanclass="pre">@py</span></code>
<p>For completeness, let’s add a custom command so users can turn off their color display themselves if
they want.</p>
<p>In <codeclass="docutils literal notranslate"><spanclass="pre">mygame/commands</span></code>, create a new file, call it for example <codeclass="docutils literal notranslate"><spanclass="pre">configcmds.py</span></code> (it’s likely that
you’ll want to add other commands for configuration down the line). You can also copy/rename the
<spanclass="c1"># send a message with a tiny bit of formatting, just for fun</span>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"Color was turned |won|W."</span><spanclass="p">)</span>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"Color was turned off."</span><spanclass="p">)</span>
<p>Lastly, we make this command available to the user by adding it to the default <codeclass="docutils literal notranslate"><spanclass="pre">CharacterCmdSet</span></code> in
<codeclass="docutils literal notranslate"><spanclass="pre">mygame/commands/default_cmdsets.py</span></code> and reloading the server. Make sure you also import the
<p>Apart from ANSI colors, Evennia also supports <strong>Xterm256</strong> colors (See [Colors](./TextTags#colored-
text)). The <codeclass="docutils literal notranslate"><spanclass="pre">msg()</span></code> method supports the <codeclass="docutils literal notranslate"><spanclass="pre">xterm256</span></code> keyword for manually activating/deactiving
xterm256. It should be easy to expand the above example to allow players to customize xterm256
regardless of if Evennia thinks their client supports it or not.</p>
<p>To get a better understanding of how <codeclass="docutils literal notranslate"><spanclass="pre">msg()</span></code> works with keywords, you can try this as superuser:</p>
<divclass="highlight-default notranslate"><divclass="highlight"><pre><span></span><spanclass="nd">@py</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"|123Dark blue with xterm256, bright blue with ANSI"</span><spanclass="p">,</span><spanclass="n">xterm256</span><spanclass="o">=</span><spanclass="kc">True</span><spanclass="p">)</span>
<spanclass="nd">@py</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"|gThis should be uncolored"</span><spanclass="p">,</span><spanclass="n">nomarkup</span><spanclass="o">=</span><spanclass="kc">True</span><spanclass="p">)</span>