Auto-convert contrib readmes to doc pages

This commit is contained in:
Griatch 2022-01-08 00:58:56 +01:00
parent bc5ba46851
commit b922cf9b3c
254 changed files with 7117 additions and 1060 deletions

View file

@ -9,7 +9,7 @@ import re
from collections import defaultdict
from sphinx.errors import DocumentError
from pathlib import Path
from os.path import abspath, dirname, join as pathjoin, sep, relpath
from os.path import abspath, dirname, join as pathjoin, relpath
_IGNORE_FILES = []
_SOURCEDIR_NAME = "source"
@ -267,6 +267,7 @@ def auto_link_remapper(no_autodoc=False):
# we add a self-reference so the toc itself is also a part of a toctree
fil.write("\n```\n\n```{toctree}\n :hidden:\n\ntoc\n```")
print(" -- File toc.md updated.")
print(" -- Auto-Remapper finished.")

View file

@ -3,16 +3,81 @@ Convert contribs' README files to proper documentation pages along with
an index.
"""
from collections import defaultdict
from os.path import abspath, dirname, join as pathjoin, sep
from glob import glob
_EVENNIA_PATH = pathjoin(dirname(dirname(dirname(abspath(__file__)))))
_DOCS_PATH = pathjoin(_EVENNIA_PATH, "docs")
_CONTRIB_PATH = pathjoin(_EVENNIA_PATH, "contrib")
_SOURCE_DIR = pathjoin(_EVENNIA_PATH, "contrib")
_SOURCE_DIR = pathjoin(_EVENNIA_PATH, "evennia", "contrib")
_OUT_DIR = pathjoin(_DOCS_PATH, "source", "Contribs")
_OUT_INDEX_FILE = pathjoin(_OUT_DIR, "Contribs.md")
_OUT_INDEX_FILE = pathjoin(_OUT_DIR, "Contrib-Overview.md")
_CATEGORY_DESCS = {
"base_systems": """
This category contains systems that are not necessarily tied to a specific
in-game mechanic but is useful for the game as a whole. Examples include
login systems, new command syntaxes, and build helpers.
""",
"full_systems": """
This category contains 'complete' game engines that can be used directly
to start creating content without no further additions (unless you want to).
""",
"game_systems": """
This category holds code implementing in-game gameplay systems like
crafting, mail, combat and more. Each system is meant to be adopted
piecemeal and adopted for your game. This does not include
roleplaying-specific systems, those are found in the `rpg` folder.
""",
"grid": """
Systems related to the game world's topology and structure. This has
contribs related to rooms, exits and map building.
""",
"rpg": """
These are systems specifically related to roleplaying
and rule implementation like character traits, dice rolling and emoting.
""",
"tutorials": """
Helper resources specifically meant to teach a development concept or
to exemplify an Evennia system. Any extra resources tied to documentation
tutorials are found here. Also the home of the Tutorial World demo adventure.
""",
"utils": """
Miscellaneous, optional tools for manipulating text, auditing connections
and more.
"""
}
_FILENAME_MAP = {
"rpsystem": "RPSystem",
"xyzgrid": "XYZGrid",
"awsstorage": "AWSStorage"
}
HEADER = """# Contribs
_Contribs_ are optional code snippets and systems contributed by
the Evennia community. They vary in size and complexity and
may be more specific about game types and styles than 'core' Evennia.
This page is auto-generated and summarizes all contribs currently included.
All contrib categories are imported from `evennia.contrib`, such as
from evennia.contrib.base_systems import building_menu
Each contrib contains installation instructions for how to integrate it
with your other code. If you want to tweak the code of a contrib, just
copy its entire folder to your game directory and modify/use it from there.
If you want to contribute yourself, see [here](Contributing)!
> Hint: Additional (potentially un-maintained) code snippets from the community can be found
in our discussion forum's [Community Contribs & Snippets](https://github.com/evennia/evennia/discussions/categories/community-contribs-snippets) category.
"""
TOCTREE = """
@ -23,26 +88,122 @@ TOCTREE = """
"""
CATEGORY = """
## {category}
def readme2doc(directory):
_{category_desc}_
{blurbs}
"""
BLURB = """
### Contrib: `{name}`
{credits}
{blurb}
[Read the documentation]({filename})
"""
FOOTER = """
----
<small>This document page is generated from `{path}`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>
"""
INDEX_FOOTER = """
----
<small>This document page is auto-generated from the sources. Manual changes
will be overwritten.</small>
"""
def readmes2docs(directory=_SOURCE_DIR):
"""
Parse directory for README files and convert them to doc pages.
"""
indexfile = []
listing = []
ncount = 0
categories = defaultdict(list)
for file_path in glob(f"directory{sep}*{sep}*{sep}README.md"):
glob_path = f"{directory}{sep}*{sep}*{sep}README.md"
for file_path in glob(glob_path):
# paths are e.g. evennia/contrib/utils/auditing/README.md
_, category, name, _ = file_path.rsplit(sep, 3)
filename = "-".join(part.capitalize() for part in name.split("_")) + ".md"
filename = "Contrib-" + "-".join(
_FILENAME_MAP.get(
part, part.capitalize() if part[0].islower() else part)
for part in name.split("_")) + ".md"
outfile = pathjoin(_OUT_DIR, filename)
with open(file_path) as fil:
data = fil.read()
clean_file_path = f"evennia{sep}contrib{file_path[len(directory):]}"
data += FOOTER.format(path=clean_file_path)
try:
credits = data.split("\n\n", 3)[1]
blurb = data.split("\n\n", 3)[2]
except IndexError:
blurb = name
with open(outfile, 'w') as fil:
fil.write(data)
categories[category].append((name, credits, blurb, filename))
ncount += 1
# build the index with blurbs
lines = [HEADER]
filenames = []
for category in sorted(categories):
contrib_tups = categories[category]
catlines = []
for tup in sorted(contrib_tups, key=lambda tup: tup[0].lower()):
catlines.append(
BLURB.format(
name=tup[0],
credits=tup[1],
blurb=tup[2],
filename=tup[3],
)
)
filenames.append(f"Contribs{sep}{tup[3]}")
lines.append(
CATEGORY.format(
category=category,
category_desc=_CATEGORY_DESCS[category].strip(),
blurbs="\n".join(catlines)
)
)
lines.append(TOCTREE.format(
listing="\n".join(filenames))
)
lines.append(INDEX_FOOTER)
text = "\n".join(lines)
with open(_OUT_INDEX_FILE, 'w') as fil:
fil.write(text)
print(f" -- Converted Contrib READMEs to {ncount} doc pages + index.")
if __name__ == "__main__":
readmes2docs(_SOURCE_DIR)

View file

@ -0,0 +1,234 @@
# AWSstorage system
Contrib by The Right Honourable Reverend (trhr) 2020
## What is this for?
This plugin migrates the Web-based portion of Evennia, namely images,
javascript, and other items located inside staticfiles into Amazon AWS (S3) for
hosting.
Files hosted on S3 are "in the cloud," and while your personal
server may be sufficient for serving multimedia to a minimal number of users,
the perfect use case for this plugin would be:
- Servers supporting heavy web-based traffic (webclient, etc) ...
- With a sizable number of users ...
- Where the users are globally distributed ...
- Where multimedia files are served to users as a part of gameplay
Bottom line - if you're sending an image to a player every time they traverse a
map, the bandwidth reduction of using this will be substantial. If not, probably
skip this contrib.
## On costs
Note that storing and serving files via S3 is not technically free outside of
Amazon's "free tier" offering, which you may or may not be eligible for;
setting up a vanilla evennia server with this contrib currently requires 1.5MB
of storage space on S3, making the current total cost of running this plugin
~$0.0005 per year. If you have substantial media assets and intend to serve
them to many users, caveat emptor on a total cost of ownership - check AWS's
pricing structure.
# Technical details
This is a drop-in replacement that operates deeper than all of Evennia's code,
so your existing code does not need to change at all to support it.
For example, when Evennia (or Django), tries to save a file permanently (say, an
image uploaded by a user), the save (or load) communication follows the path:
Evennia -> Django
Django -> Storage backend
Storage backend -> file storage location (e.g. hard drive)
[django docs](https://docs.djangoproject.com/en/3.0/ref/settings/#std:setting-STATICFILES_STORAGE)
This plugin, when enabled, overrides the default storage backend,
which defaults to saving files at mygame/website/, instead,
sending the files to S3 via the storage backend defined herein.
There is no way (or need) to directly access or use the functions here with
other contributions or custom code. Simply work how you would normally, Django
will handle the rest.
# Installation
## Set up AWS account
If you don't have an AWS S3 account, you should create one at
https://aws.amazon.com/ - documentation for AWS S3 is available at:
https://docs.aws.amazon.com/AmazonS3/latest/gsg/GetStartedWithS3.html
Credentials required within the app are AWS IAM Access Key and Secret Keys,
which can be generated/found in the AWS Console.
The following example IAM Control Policy Permissions can be added to
the IAM service inside AWS. Documentation for this can be found here:
https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html
Note that this is only required if you want to tightly secure the roles
that this plugin has access to.
```
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "evennia",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObjectAcl",
"s3:GetObject",
"s3:ListBucket",
"s3:DeleteObject",
"s3:PutObjectAcl"
],
"Resource": [
"arn:aws:s3:::YOUR_BUCKET_NAME/*",
"arn:aws:s3:::YOUR_BUCKET_NAME"
]
}
],
[
{
"Sid":"evennia",
"Effect":"Allow",
"Action":[
"s3:CreateBucket",
],
"Resource":[
"arn:aws:s3:::*"
]
}
]
}
```
Advanced Users: The second IAM statement, CreateBucket, is only needed
for initial installation. You can remove it later, or you can
create the bucket and set the ACL yourself before you continue.
## Dependencies
This package requires the dependency "boto3 >= 1.4.4", the official
AWS python package. To install, it's easiest to just install Evennia's
extra requirements;
- Activate your `virtualenv`
- `cd` to the root of the Evennia repository. There should be an `requirements_extra.txt`
file here.
- `pip install -r requirements_extra.txt`
## Configure Evennia
Customize the variables defined below in `secret_settings.py`. No further
configuration is needed. Note the three lines that you need to set to your
actual values.
```python
# START OF SECRET_SETTINGS.PY COPY/PASTE >>>
AWS_ACCESS_KEY_ID = 'THIS_IS_PROVIDED_BY_AMAZON'
AWS_SECRET_ACCESS_KEY = 'THIS_IS_PROVIDED_BY_AMAZON'
AWS_STORAGE_BUCKET_NAME = 'mygame-evennia' # CHANGE ME! I suggest yourgamename-evennia
# The settings below need to go in secret_settings,py as well, but will
# not need customization unless you want to do something particularly fancy.
AWS_S3_REGION_NAME = 'us-east-1' # N. Virginia
AWS_S3_OBJECT_PARAMETERS = { 'Expires': 'Thu, 31 Dec 2099 20:00:00 GMT',
'CacheControl': 'max-age=94608000', }
AWS_DEFAULT_ACL = 'public-read'
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % settings.AWS_BUCKET_NAME
AWS_AUTO_CREATE_BUCKET = True
STATICFILES_STORAGE = 'evennia.contrib.base_systems.awsstorage.aws-s3-cdn.S3Boto3Storage'
# <<< END OF SECRET_SETTINGS.PY COPY/PASTE
```
You may also store these keys as environment variables of the same name.
For advanced configuration, refer to the docs for django-storages.
After copying the above, run `evennia reboot`.
## Check that it works
Confirm that web assets are being served from S3 by visiting your website, then
checking the source of any image (for instance, the logo). It should read
`https://your-bucket-name.s3.amazonaws.com/path/to/file`. If so, the system
works and you shouldn't need to do anything else.
# Uninstallation
If you haven't made changes to your static files (uploaded images, etc),
you can simply remove the lines you added to `secret_settings.py`. If you
have made changes and want to uninstall at a later date, you can export
your files from your S3 bucket and put them in /static/ in the evennia
directory.
# License
Draws heavily from code provided by django-storages, for which these contributors
are authors:
Marty Alchin (S3)
David Larlet (S3)
Arne Brodowski (S3)
Sebastian Serrano (S3)
Andrew McClain (MogileFS)
Rafal Jonca (FTP)
Chris McCormick (S3 with Boto)
Ivanov E. (Database)
Ariel Núñez (packaging)
Wim Leers (SymlinkOrCopy + patches)
Michael Elsdörfer (Overwrite + PEP8 compatibility)
Christian Klein (CouchDB)
Rich Leland (Mosso Cloud Files)
Jason Christa (patches)
Adam Nelson (patches)
Erik CW (S3 encryption)
Axel Gembe (Hash path)
Waldemar Kornewald (MongoDB)
Russell Keith-Magee (Apache LibCloud patches)
Jannis Leidel (S3 and GS with Boto)
Andrei Coman (Azure)
Chris Streeter (S3 with Boto)
Josh Schneier (Fork maintainer, Bugfixes, Py3K)
Anthony Monthe (Dropbox)
EunPyo (Andrew) Hong (Azure)
Michael Barrientos (S3 with Boto3)
piglei (patches)
Matt Braymer-Hayes (S3 with Boto3)
Eirik Martiniussen Sylliaas (Google Cloud Storage native support)
Jody McIntyre (Google Cloud Storage native support)
Stanislav Kaledin (Bug fixes in SFTPStorage)
Filip Vavera (Google Cloud MIME types support)
Max Malysh (Dropbox large file support)
Scott White (Google Cloud updates)
Alex Watt (Google Cloud Storage patch)
Jumpei Yoshimura (S3 docs)
Jon Dufresne
Rodrigo Gadea (Dropbox fixes)
Martey Dodoo
Chris Rink
Shaung Cheng (S3 docs)
Andrew Perry (Bug fixes in SFTPStorage)
The repurposed code from django-storages is released under BSD 3-Clause,
same as Evennia, so for detailed licensing, refer to the Evennia license.
# Versioning
This is confirmed to work for Django 2 and Django 3.
----
<small>This document page is generated from `evennia/contrib/base_systems/awsstorage/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,77 @@
# Input/Output Auditing
Contrib - Johnny 2017
This is a tap that optionally intercepts all data sent to/from clients and the
server and passes it to a callback of your choosing.
It is intended for quality assurance, post-incident investigations and debugging
but obviously can be abused. All data is recorded in cleartext. Please
be ethical, and if you are unwilling to properly deal with the implications of
recording user passwords or private communications, please do not enable
this module.
Some checks have been implemented to protect the privacy of users.
Files included in this module:
outputs.py - Example callback methods. This module ships with examples of
callbacks that send data as JSON to a file in your game/server/logs
dir or to your native Linux syslog daemon. You can of course write
your own to do other things like post them to Kafka topics.
server.py - Extends the Evennia ServerSession object to pipe data to the
callback upon receipt.
tests.py - Unit tests that check to make sure commands with sensitive
arguments are having their PII scrubbed.
## Installation/Configuration:
Deployment is completed by configuring a few settings in server.conf. This line
is required:
SERVER_SESSION_CLASS = 'evennia.contrib.utils.auditing.server.AuditedServerSession'
This tells Evennia to use this ServerSession instead of its own. Below are the
other possible options along with the default value that will be used if unset.
# Where to send logs? Define the path to a module containing your callback
# function. It should take a single dict argument as input
AUDIT_CALLBACK = 'evennia.contrib.utils.auditing.outputs.to_file'
# Log user input? Be ethical about this; it will log all private and
# public communications between players and/or admins (default: False).
AUDIT_IN = False
# Log server output? This will result in logging of ALL system
# messages and ALL broadcasts to connected players, so on a busy game any
# broadcast to all users will yield a single event for every connected user!
AUDIT_OUT = False
# The default output is a dict. Do you want to allow key:value pairs with
# null/blank values? If you're just writing to disk, disabling this saves
# some disk space, but whether you *want* sparse values or not is more of a
# consideration if you're shipping logs to a NoSQL/schemaless database.
# (default: False)
AUDIT_ALLOW_SPARSE = False
# If you write custom commands that handle sensitive data like passwords,
# you must write a regular expression to remove that before writing to log.
# AUDIT_MASKS is a list of dictionaries that define the names of commands
# and the regexes needed to scrub them.
# The system already has defaults to filter out sensitive login/creation
# commands in the default command set. Your list of AUDIT_MASKS will be appended
# to those defaults.
#
# In the regex, the sensitive data itself must be captured in a named group with a
# label of 'secret' (see the Python docs on the `re` module for more info). For
# example: `{'authentication': r"^@auth\s+(?P<secret>[\w]+)"}`
AUDIT_MASKS = []
----
<small>This document page is generated from `evennia/contrib/utils/auditing/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,134 @@
# Barter system
Evennia contribution - Griatch 2012
This implements a full barter system - a way for players to safely
trade items between each other using code rather than simple free-form
talking. The advantage of this is increased buy/sell safety but it
also streamlines the process and makes it faster when doing many
transactions (since goods are automatically exchanged once both
agree).
This system is primarily intended for a barter economy, but can easily
be used in a monetary economy as well -- just let the "goods" on one
side be coin objects (this is more flexible than a simple "buy"
command since you can mix coins and goods in your trade).
## Installation
Just import the CmdsetTrade command into (for example) the default
cmdset. This will make the trade (or barter) command available
in-game.
```python
# in mygame/commands/default_cmdsets.py
from evennia.contrib.game_systems import barter # <---
# ...
class CharacterCmdSet(default_cmds.CharacterCmdSet):
# ...
def at cmdset_creation(self):
# ...
self.add(barter.CmdsetTrade) # <---
```
## Usage
In this module, a "barter" is generally referred to as a "trade".
Below is an example of a barter sequence. A and B are the parties.
The `A>` and `B>` are their inputs.
1) opening a trade
A> trade B: Hi, I have a nice extra sword. You wanna trade?
B sees:
A says: "Hi, I have a nice extra sword. You wanna trade?"
A wants to trade with you. Enter 'trade A <emote>' to accept.
B> trade A: Hm, I could use a good sword ...
A sees:
B says: "Hm, I could use a good sword ...
B accepts the trade. Use 'trade help' for aid.
B sees:
You are now trading with A. Use 'trade help' for aid.
2) negotiating
A> offer sword: This is a nice sword. I would need some rations in trade.
B sees: A says: "This is a nice sword. I would need some rations in trade."
[A offers Sword of might.]
B> evaluate sword
B sees:
<Sword's description and possibly stats>
B> offer ration: This is a prime ration.
A sees:
B says: "This is a prime ration."
[B offers iron ration]
A> say Hey, this is a nice sword, I need something more for it.
B sees:
A says: "Hey this is a nice sword, I need something more for it."
B> offer sword,apple: Alright. I will also include a magic apple. That's my last offer.
A sees:
B says: "Alright, I will also include a magic apple. That's my last offer."
[B offers iron ration and magic apple]
A> accept: You are killing me here, but alright.
B sees: A says: "You are killing me here, but alright."
[A accepts your offer. You must now also accept.]
B> accept: Good, nice making business with you.
You accept the deal. Deal is made and goods changed hands.
A sees: B says: "Good, nice making business with you."
B accepts the deal. Deal is made and goods changed hands.
At this point the trading system is exited and the negotiated items
are automatically exchanged between the parties. In this example B was
the only one changing their offer, but also A could have changed their
offer until the two parties found something they could agree on. The
emotes are optional but useful for RP-heavy worlds.
## Technical info
The trade is implemented by use of a TradeHandler. This object is a
common place for storing the current status of negotiations. It is
created on the object initiating the trade, and also stored on the
other party once that party agrees to trade. The trade request times
out after a certain time - this is handled by a Script. Once trade
starts, the CmdsetTrade cmdset is initiated on both parties along with
the commands relevant for the trading.
## Ideas for NPC bartering
This module is primarily intended for trade between two players. But
it can also in principle be used for a player negotiating with an
AI-controlled NPC. If the NPC uses normal commands they can use it
directly -- but more efficient is to have the NPC object send its
replies directly through the tradehandler to the player. One may want
to add some functionality to the decline command, so players can
decline specific objects in the NPC offer (decline <object>) and allow
the AI to maybe offer something else and make it into a proper
barter. Along with an AI that "needs" things or has some sort of
personality in the trading, this can make bartering with NPCs at least
moderately more interesting than just plain 'buy'.
----
<small>This document page is generated from `evennia/contrib/game_systems/barter/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,41 @@
# Batch processor examples
Contibution - Griatch 2012
The batch processor is used for generating in-game content from one or more
static files. Files can be stored with version control and then 'applied'
to the game to create content.
There are two batch processor types:
- Batch-cmd processor: A list of `#`-separated Evennia commands being executed
in sequence, such as `create`, `dig`, `north` etc. When running a script
of this type (filename ending with `.ev`), the caller of the script will be
the one performing the script's actions.
- Batch-code processor: A full Python script (filename ending with `.py` that
executes Evennia api calls to build, such as `evennia.create_object` or
`evennia.search_object` etc. It can be divided up into comment-separated
chunks so one can execute only parts of the script at a time (in this way it's
a little different than a normal Python file).
## Usage
To test the two example batch files, you need `Developer` or `superuser`
permissions, be logged into the game and run of
> batchcommand/interactive tutorials.batchprocessor.example_batch_cmds
> batchcode/interactive tutorials.batchprocessor.example_batch_code
The `/interactive` drops you in interactive mode so you can follow along what
the scripts do. Skip it to build it all at once.
Both commands produce the same results - they create a red-button object,
a table and a chair. If you run either with the `/debug` switch, the objects will
be deleted afterwards (for quick tests of syntax that you don't want to spam new
objects, for example).
----
<small>This document page is generated from `evennia/contrib/tutorials/batchprocessor/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,22 @@
# Script example
Griatch - 2012
Example script for testing. This adds a simple timer that has your
character make observations and notices at irregular intervals.
To test, use (in game)
> script me = contrib.tutorials.bodyfunctions.BodyFunctions
## Notes
Use `scripts me` to see the script running on you. Note that even though
the timer ticks down to 0, you will _not_ see an echo every tick (it's
random if an echo is given on a tick or not).
----
<small>This document page is generated from `evennia/contrib/tutorials/bodyfunctions/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,134 @@
# Building menu
Module containing the building menu system.
Evennia contributor: vincent-lg 2018
Building menus are in-game menus, not unlike `EvMenu` though using a
different approach. Building menus have been specifically designed to edit
information as a builder. Creating a building menu in a command allows
builders quick-editing of a given object, like a room. If you follow the
steps below to add the contrib, you will have access to an `@edit` command
that will edit any default object offering to change its key and description.
## Install
1. Import the `GenericBuildingCmd` class from this contrib in your
`mygame/commands/default_cmdset.py` file:
```python
from evennia.contrib.base_systems.building_menu import GenericBuildingCmd
```
2. Below, add the command in the `CharacterCmdSet`:
```python
# ... These lines should exist in the file
class CharacterCmdSet(default_cmds.CharacterCmdSet):
key = "DefaultCharacter"
def at_cmdset_creation(self):
super(CharacterCmdSet, self).at_cmdset_creation()
# ... add the line below
self.add(GenericBuildingCmd())
```
## Usage
The `edit` command will allow you to edit any object. You will need to
specify the object name or ID as an argument. For instance: `edit here`
will edit the current room. However, building menus can perform much more
than this very simple example, read on for more details.
Building menus can be set to edit about anything. Here is an example of
output you could obtain when editing the room:
```
Editing the room: Limbo(#2)
[T]itle: the limbo room
[D]escription
This is the limbo room. You can easily change this default description,
either by using the |y@desc/edit|n command, or simply by entering this
menu (enter |yd|n).
[E]xits:
north to A parking(#4)
[Q]uit this menu
```
From there, you can open the title choice by pressing t. You can then
change the room title by simply entering text, and go back to the
main menu entering @ (all this is customizable). Press q to quit this menu.
The first thing to do is to create a new module and place a class
inheriting from `BuildingMenu` in it.
```python
from evennia.contrib.base_systems.building_menu import BuildingMenu
class RoomBuildingMenu(BuildingMenu):
# ...
```
Next, override the `init` method (not `__init__`!). You can add
choices (like the title, description, and exits choices as seen above) by using
the `add_choice` method.
```python
class RoomBuildingMenu(BuildingMenu):
def init(self, room):
self.add_choice("title", "t", attr="key")
```
That will create the first choice, the title choice. If one opens your menu
and enter t, she will be in the title choice. She can change the title
(it will write in the room's `key` attribute) and then go back to the
main menu using `@`.
`add_choice` has a lot of arguments and offers a great deal of
flexibility. The most useful ones is probably the usage of callbacks,
as you can set almost any argument in `add_choice` to be a callback, a
function that you have defined above in your module. This function will be
called when the menu element is triggered.
Notice that in order to edit a description, the best method to call isn't
`add_choice`, but `add_choice_edit`. This is a convenient shortcut
which is available to quickly open an `EvEditor` when entering this choice
and going back to the menu when the editor closes.
```python
class RoomBuildingMenu(BuildingMenu):
def init(self, room):
self.add_choice("title", "t", attr="key")
self.add_choice_edit("description", key="d", attr="db.desc")
```
When you wish to create a building menu, you just need to import your
class, create it specifying your intended caller and object to edit,
then call `open`:
```python
from <wherever> import RoomBuildingMenu
class CmdEdit(Command):
key = "redit"
def func(self):
menu = RoomBuildingMenu(self.caller, self.caller.location)
menu.open()
```
This is a very short introduction. For more details, see the [online
tutorial](https://github.com/evennia/evennia/wiki/Building-menus) or read the
heavily-documented code of the contrib itself.
----
<small>This document page is generated from `evennia/contrib/base_systems/building_menu/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,90 @@
# Clothing
Evennia contribution - Tim Ashley Jenkins 2017
Provides a typeclass and commands for wearable clothing,
which is appended to a character's description when worn.
Clothing items, when worn, are added to the character's description
in a list. For example, if wearing the following clothing items:
a thin and delicate necklace
a pair of regular ol' shoes
one nice hat
a very pretty dress
## Installation
To install, import this module and have your default character
inherit from ClothedCharacter in your game's characters.py file:
```python
from evennia.contrib.game_systems.clothing import ClothedCharacter
class Character(ClothedCharacter):
```
And then add `ClothedCharacterCmdSet` in your character set in
`mygame/commands/default_cmdsets.py`:
```python
from evennia.contrib.game_systems.clothing import ClothedCharacterCmdSet <--
class CharacterCmdSet(default_cmds.CharacterCmdSet):
# ...
at_cmdset_creation(self):
super().at_cmdset_creation()
...
self.add(ClothedCharacterCmdSet) # <--
```
From here, you can use the default builder commands to create clothes
with which to test the system:
create a pretty shirt : evennia.contrib.game_systems.clothing.Clothing
set shirt/clothing_type = 'top'
wear shirt
A character's description may look like this:
Superuser(#1)
This is User #1.
Superuser is wearing one nice hat, a thin and delicate necklace,
a very pretty dress and a pair of regular ol' shoes.
Characters can also specify the style of wear for their clothing - I.E.
to wear a scarf 'tied into a tight knot around the neck' or 'draped
loosely across the shoulders' - to add an easy avenue of customization.
For example, after entering:
wear scarf draped loosely across the shoulders
The garment appears like so in the description:
Superuser(#1)
This is User #1.
Superuser is wearing a fanciful-looking scarf draped loosely
across the shoulders.
Items of clothing can be used to cover other items, and many options
are provided to define your own clothing types and their limits and
behaviors. For example, to have undergarments automatically covered
by outerwear, or to put a limit on the number of each type of item
that can be worn. The system as-is is fairly freeform - you
can cover any garment with almost any other, for example - but it
can easily be made more restrictive, and can even be tied into a
system for armor or other equipment.
----
<small>This document page is generated from `evennia/contrib/game_systems/clothing/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,63 @@
# Color markups
Contribution, Griatch 2017
Additional color markup styles for Evennia (extending or replacing the default
`|r`, `|234` etc).
## Installation
Import the desired style variables from this module into
mygame/server/conf/settings.py and add them to the settings variables below.
Each are specified as a list, and multiple such lists can be added to each
variable to support multiple formats. Note that list order affects which regexes
are applied first. You must restart both Portal and Server for color tags to
update.
Assign to the following settings variables (see below for example):
COLOR_ANSI_EXTRA_MAP - a mapping between regexes and ANSI colors
COLOR_XTERM256_EXTRA_FG - regex for defining XTERM256 foreground colors
COLOR_XTERM256_EXTRA_BG - regex for defining XTERM256 background colors
COLOR_XTERM256_EXTRA_GFG - regex for defining XTERM256 grayscale foreground colors
COLOR_XTERM256_EXTRA_GBG - regex for defining XTERM256 grayscale background colors
COLOR_ANSI_BRIGHT_BG_EXTRA_MAP = ANSI does not support bright backgrounds; we fake
this by mapping ANSI markup to matching bright XTERM256 backgrounds
COLOR_NO_DEFAULT - Set True/False. If False (default), extend the default
markup, otherwise replace it completely.
## Example
To add the {- "curly-bracket" style, add the following to your settings file,
then reboot both Server and Portal:
```python
from evennia.contrib.base_systems import color_markups
COLOR_ANSI_EXTRA_MAP = color_markups.CURLY_COLOR_ANSI_EXTRA_MAP
COLOR_XTERM256_EXTRA_FG = color_markups.CURLY_COLOR_XTERM256_EXTRA_FG
COLOR_XTERM256_EXTRA_BG = color_markups.CURLY_COLOR_XTERM256_EXTRA_BG
COLOR_XTERM256_EXTRA_GFG = color_markups.CURLY_COLOR_XTERM256_EXTRA_GFG
COLOR_XTERM256_EXTRA_GBG = color_markups.CURLY_COLOR_XTERM256_EXTRA_GBG
COLOR_ANSI_BRIGHT_BG_EXTRA_MAP = color_markups.CURLY_COLOR_ANSI_BRIGHT_BG_EXTRA_MAP
```
To add the `%c-` "mux/mush" style, add the following to your settings file, then
reboot both Server and Portal:
```python
from evennia.contrib.base_systems import color_markups
COLOR_ANSI_EXTRA_MAP = color_markups.MUX_COLOR_ANSI_EXTRA_MAP
COLOR_XTERM256_EXTRA_FG = color_markups.MUX_COLOR_XTERM256_EXTRA_FG
COLOR_XTERM256_EXTRA_BG = color_markups.MUX_COLOR_XTERM256_EXTRA_BG
COLOR_XTERM256_EXTRA_GFG = color_markups.MUX_COLOR_XTERM256_EXTRA_GFG
COLOR_XTERM256_EXTRA_GBG = color_markups.MUX_COLOR_XTERM256_EXTRA_GBG
COLOR_ANSI_BRIGHT_BGS_EXTRA_MAP = color_markups.CURLY_COLOR_ANSI_BRIGHT_BGS_EXTRA_MAP
```
----
<small>This document page is generated from `evennia/contrib/base_systems/color_markups/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,64 @@
# Cooldown contrib module.
Evennia contrib - owllex, 2021
This contrib provides a simple cooldown handler that can be attached to any
typeclassed Object or Account. A cooldown is a lightweight persistent
asynchronous timer that you can query to see if it is ready.
Cooldowns are good for modelling rate-limited actions, like how often a
character can perform a given command.
Cooldowns are completely asynchronous and must be queried to know their
state. They do not fire callbacks, so are not a good fit for use cases
where something needs to happen on a specific schedule (use delay or
a TickerHandler for that instead).
See also the evennia documentation for command cooldowns
(https://github.com/evennia/evennia/wiki/Command-Cooldown) for more information
about the concept.
## Installation
To use, simply add the following property to the typeclass definition of any
object type that you want to support cooldowns. It will expose a new `cooldowns`
property that persists data to the object's attribute storage. You can set this
on your base `Object` typeclass to enable cooldown tracking on every kind of
object, or just put it on your `Character` typeclass.
By default the CooldownHandler will use the `cooldowns` property, but you can
customize this if desired by passing a different value for the `db_attribute`
parameter.
```python
from evennia.game_systems.contrib.cooldowns import Cooldownhandler
from evennia.utils.utils import lazy_property
@lazy_property
def cooldowns(self):
return CooldownHandler(self, db_attribute="cooldowns")
```
# Example
Assuming you've installed cooldowns on your Character typeclasses, you can use a
cooldown to limit how often you can perform a command. The following code
snippet will limit the use of a Power Attack command to once every 10 seconds
per character.
```python
class PowerAttack(Command):
def func(self):
if self.caller.cooldowns.ready("power attack"):
self.do_power_attack()
self.caller.cooldowns.add("power attack", 10)
else:
self.caller.msg("That's not ready yet!")
```
----
<small>This document page is generated from `evennia/contrib/game_systems/cooldowns/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,108 @@
# Crafting system
Contrib - Griatch 2020
This implements a full crafting system. The principle is that of a 'recipe':
ingredient1 + ingredient2 + ... + tool1 + tool2 + ... + craft_recipe -> objectA, objectB, ...
Here, 'ingredients' are consumed by the crafting process, whereas 'tools' are
necessary for the process by will not be destroyed by it.
An example would be to use the tools 'bowl' and 'oven' to use the ingredients
'flour', 'salt', 'yeast' and 'water' to create 'bread' using the 'bread recipe'.
A recipe does not have to use tools, like 'snow' + 'snowball-recipe' becomes
'snowball'. Conversely one could also imagine using tools without consumables,
like using 'spell book' and 'wand' to produce 'fireball' by having the recipe
check some magic skill on the character.
The system is generic enough to be used also for adventure-like puzzles, like
combining 'stick', 'string' and 'hook' to get a 'makeshift fishing rod' that
you can use with 'storm drain' (treated as a tool) to get 'key' ...
## Intallation and Usage
Import the `CmdCraft` command from evennia/contrib/crafting/crafting.py and
add it to your Character cmdset. Reload and the `craft` command will be
available to you:
craft <recipe> [from <ingredient>,...] [using <tool>, ...]
For example
craft toy car from plank, wooden wheels, nails using saw, hammer
To use crafting you need recipes. Add a new variable to `mygame/server/conf/settings.py`:
CRAFT_RECIPE_MODULES = ['world.recipes']
All top-level classes in these modules (whose name does not start with `_`)
will be parsed by Evennia as recipes to make available to the crafting system.
Using the above example, create `mygame/world/recipes.py` and add your recipies
in there:
```python
from evennia.contrib.game_systems.crafting import CraftingRecipe, CraftingValidationError
class RecipeBread(CraftingRecipe):
"""
Bread is good for making sandwitches!
"""
name = "bread" # used to identify this recipe in 'craft' command
tool_tags = ["bowl", "oven"]
consumable_tags = ["flour", "salt", "yeast", "water"]
output_prototypes = [
{"key": "Loaf of Bread",
"aliases": ["bread"],
"desc": "A nice load of bread.",
"typeclass": "typeclasses.objects.Food", # assuming this exists
"tags": [("bread", "crafting_material")] # this makes it usable in other recipes ...
}
]
def pre_craft(self, **kwargs):
# validates inputs etc. Raise `CraftingValidationError` if fails
def craft(self, **kwargs):
# performs the craft - but it can still fail (check skills etc here)
def craft(self, result, **kwargs):
# any post-crafting effects. Always called, even if crafting failed (be
# result would be None then)
```
## Technical
The Recipe is a class that specifies the consumables, tools and output along
with various methods (that you can override) to do the the validation of inputs
and perform the crafting itself.
By default the input is a list of object-tags (using the "crafting_material"
and "crafting_tool" tag-categories respectively). Providing a set of objects
matching these tags are required for the crafting to be done. The use of tags
means that multiple different objects could all work for the same recipe, as
long as they have the right tag. This can be very useful for allowing players
to experiment and explore alternative ways to create things!
The output is given by a set of prototype-dicts. If the input is correct and
other checks are passed (such as crafting skill, for example), these prototypes
will be used to generate the new object(s) being crafted.
Each recipe is a stand-alone entity which allows for very advanced
customization for every recipe - for example one could have a recipe that
checks other properties of the inputs (like quality, color etc) and have that
affect the result. Your recipes could also (and likely would) tie into your
game's skill system to determine the success or outcome of the crafting.
----
<small>This document page is generated from `evennia/contrib/game_systems/crafting/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,53 @@
# Custom gameime
Contrib - Griatch 2017, vlgeoff 2017
This reimplements the `evennia.utils.gametime` module but supporting a custom
calendar for your game world. It allows for scheduling events to happen at given
in-game times, taking this custom calendar into account.
## Installation
Import and use this in the same way as you would the normal
`evennia.utils.gametime` module.
Customize the calendar by adding a `TIME_UNITS` dict to your settings (see
example below).
## Usage:
```python
from evennia.contrib.base_systems import custom_gametime
gametime = custom_gametime.realtime_to_gametime(days=23)
# scedule an event to fire every in-game 10 hours
custom_gametime.schedule(callback, repeat=True, hour=10)
```
The calendar can be customized by adding the `TIME_UNITS` dictionary to your
settings file. This maps unit names to their length, expressed in the smallest
unit. Here's the default as an example:
TIME_UNITS = {
"sec": 1,
"min": 60,
"hr": 60 * 60,
"hour": 60 * 60,
"day": 60 * 60 * 24,
"week": 60 * 60 * 24 * 7,
"month": 60 * 60 * 24 * 7 * 4,
"yr": 60 * 60 * 24 * 7 * 4 * 12,
"year": 60 * 60 * 24 * 7 * 4 * 12, }
When using a custom calendar, these time unit names are used as kwargs to
the converter functions in this module. Even if your calendar uses other names
for months/weeks etc the system needs the default names internally.
----
<small>This document page is generated from `evennia/contrib/base_systems/custom_gametime/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,67 @@
# Dice
Rolls dice for roleplaying, in-game gambling or GM:ing
Evennia contribution - Griatch 2012
# Installation:
Add the `CmdDice` command from this module to your character's cmdset
(and then restart the server):
```python
# in mygame/commands/default_cmdsets.py
# ...
from evennia.contrib.rpg import dice <---
class CharacterCmdSet(default_cmds.CharacterCmdSet):
# ...
def at_object_creation(self):
# ...
self.add(dice.CmdDice()) # <---
```
# Usage:
> roll 1d100 + 2
> roll 1d20
> roll 1d20 - 4
The result of the roll will be echoed to the room
One can also specify a standard Python operator in order to specify
eventual target numbers and get results in a fair and guaranteed
unbiased way. For example:
> roll 2d6 + 2 < 8
Rolling this will inform all parties if roll was indeed below 8 or not.
> roll/hidden
Informs the room that the roll is being made without telling what the result
was.
> roll/secret
Is a hidden roll that does not inform the room it happened.
## Rolling dice from code
To roll dice in code, use the `roll` function from this module:
```python
from evennia.contrib.rpg import dice
dice.roll(3, 10, ("+", 2)) # 3d10 + 2
```
----
<small>This document page is generated from `evennia/contrib/rpg/dice/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,36 @@
# Email-based login system
Evennia contrib - Griatch 2012
This is a variant of the login system that requires an email-address
instead of a username to login.
This used to be the default Evennia login before replacing it with a
more standard username + password system (having to supply an email
for some reason caused a lot of confusion when people wanted to expand
on it. The email is not strictly needed internally, nor is any
confirmation email sent out anyway).
## Installation
To your settings file, add/edit the line:
```python
CMDSET_UNLOGGEDIN = "contrib.base_systems.email_login.UnloggedinCmdSet"
CONNECTION_SCREEN_MODULE = "contrib.base_systems.email_login.connection_screens"
```
That's it. Reload the server and reconnect to see it.
## Notes:
If you want to modify the way the connection screen looks, point
`CONNECTION_SCREEN_MODULE` to your own module. Use the default as a
guide (see also Evennia docs).
----
<small>This document page is generated from `evennia/contrib/base_systems/email_login/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,128 @@
# EvscapeRoom
Evennia contrib - Griatch 2019
This 'Evennia escaperoom game engine' was created for the MUD Coders Guild game
Jam, April 14-May 15 2019. The theme for the jam was "One Room". This contains the
utilities and base classes and an empty example room.
The original code for the contest is found at
https://github.com/Griatch/evscaperoom but the version on the public Evennia
demo is more updated, so if you really want the latest bug fixes etc you should
rather look at https://github.com/evennia/evdemo/tree/master/evdemo/evscaperoom
instead. A copy of the full game can also be played on the Evennia demo server
at https://demo.evennia.com - just connect to the server and write `evscaperoom`
in the first room to start!
# Introduction
Evscaperoom is, as it sounds, an escaperoom in text form. You start locked into
a room and have to figure out how to get out. This engine contains everything
needed to make a fully-featured puzzle game of this type!
# Installation
The Evscaperoom is installed by adding the `evscaperoom` command to your
character cmdset. When you run that command in-game you're ready to play!
In `mygame/commands/default_cmdsets.py`:
```python
from evennia.contrib.full_systems.evscaperoom.commands import CmdEvscapeRoomStart
class CharacterCmdSet(...):
# ...
self.add(CmdEvscapeRoomStart())
```
Reload the server and the `evscaperoom` command will be available. The contrib
comes with a small (very small) escape room as an example.
# Making your own evscaperoom
To do this, you need to make your own states. First make sure you can play the
simple example room installed above.
Copy `evennia/contrib/full_systems/evscaperoom/states` to somewhere in your game folder (let's
assume you put it under `mygame/world/`).
Next you need to re-point Evennia to look for states in this new location. Add
the following to your `mygame/server/conf/settings.py` file:
```python
EVSCAPEROOM_STATE_PACKAGE = "world.states"
```
Reload and the example evscaperoom should still work, but you can now modify and
expand it from your game dir!
## Other useful settings
There are a few other settings that may be useful:
- `EVSCAPEROOM_START_STATE` - default is `state_001_start` and is the name of
the state-module to start from (without `.py`). You can change this if you
want some other naming scheme.
- `HELP_SUMMARY_TEXT` - this is the help blurb shown when entering `help` in
the room without an argument. The original is found at the top of
`evennia/contrib/full_systems/evscaperoom/commands.py`.
# Playing the game
You should start by `look`ing around and at objects.
The `examine <object>` command allows you to 'focus' on an object. When you do
you'll learn actions you could try for the object you are focusing on, such as
turning it around, read text on it or use it with some other object. Note that
more than one player can focus on the same object, so you won't block anyone
when you focus. Focusing on another object or use `examine` again will remove
focus.
There is also a full hint system.
# Technical
When connecting to the game, the user has the option to join an existing room
(which may already be in some state of ongoing progress), or may create a fresh
room for them to start solving on their own (but anyone may still join them later).
The room will go through a series of 'states' as the players progress through
its challenges. These states are describes as modules in .states/ and the
room will load and execute the State-object within each module to set up
and transition between states as the players progress. This allows for isolating
the states from each other and will hopefully make it easier to track
the logic and (in principle) inject new puzzles later.
Once no players remain in the room, the room and its state will be wiped.
# Design Philosophy
Some basic premises inspired the design of this.
- You should be able to resolve the room alone. So no puzzles should require the
collaboration of multiple players. This is simply because there is no telling
if others will actually be online at a given time (or stay online throughout).
- You should never be held up by the actions/inactions of other players. This
is why you cannot pick up anything (no inventory system) but only
focus/operate on items. This avoids the annoying case of a player picking up
a critical piece of a puzzle and then logging off.
- A room's state changes for everyone at once. My first idea was to have a given
room have different states depending on who looked (so a chest could be open
and closed to two different players at the same time). But not only does this
add a lot of extra complexity, it also defeats the purpose of having multiple
players. This way people can help each other and collaborate like in a 'real'
escape room. For people that want to do it all themselves I instead made it
easy to start "fresh" rooms for them to take on.
All other design decisions flowed from these.
----
<small>This document page is generated from `evennia/contrib/full_systems/evscaperoom/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,82 @@
# Extended Room
Evennia Contribution - Griatch 2012, vincent-lg 2019
This is an extended Room typeclass for Evennia. It is supported
by an extended `Look` command and an extended `desc` command, also
in this module.
## Installation/testing:
Adding the `ExtendedRoomCmdset` to the default character cmdset will add all
new commands for use.
In more detail, in `mygame/commands/default_cmdsets.py`:
```python
...
from evennia.contrib import extended_room # <---
class CharacterCmdset(default_cmds.Character_CmdSet):
...
def at_cmdset_creation(self):
...
self.add(extended_room.ExtendedRoomCmdSet) # <---
```
Then reload to make the bew commands available. Note that they only work
on rooms with the typeclass `ExtendedRoom`. Create new rooms with the right
typeclass or use the `typeclass` command to swap existing rooms.
## Features
### Time-changing description slots
This allows to change the full description text the room shows
depending on larger time variations. Four seasons (spring, summer,
autumn and winter) are used by default. The season is calculated
on-demand (no Script or timer needed) and updates the full text block.
There is also a general description which is used as fallback if
one or more of the seasonal descriptions are not set when their
time comes.
An updated `desc` command allows for setting seasonal descriptions.
The room uses the `evennia.utils.gametime.GameTime` global script. This is
started by default, but if you have deactivated it, you need to
supply your own time keeping mechanism.
### In-description changing tags
Within each seasonal (or general) description text, you can also embed
time-of-day dependent sections. Text inside such a tag will only show
during that particular time of day. The tags looks like `<timeslot> ...
</timeslot>`. By default there are four timeslots per day - morning,
afternoon, evening and night.
### Details
The Extended Room can be "detailed" with special keywords. This makes
use of a special `Look` command. Details are "virtual" targets to look
at, without there having to be a database object created for it. The
Details are simply stored in a dictionary on the room and if the look
command cannot find an object match for a `look <target>` command it
will also look through the available details at the current location
if applicable. The `detail` command is used to change details.
### Extra commands
- `CmdExtendedRoomLook` - look command supporting room details
- `CmdExtendedRoomDesc` - desc command allowing to add seasonal descs,
- `CmdExtendedRoomDetail` - command allowing to manipulate details in this room
as well as listing them
- `CmdExtendedRoomGameTime` - A simple `time` command, displaying the current
time and season.
----
<small>This document page is generated from `evennia/contrib/grid/extended_room/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,163 @@
# Easy fillable form
Contrib - Tim Ashley Jenkins 2018
This module contains a function that calls an easily customizable EvMenu - this
menu presents the player with a fillable form, with fields that can be filled
out in any order. Each field's value can be verified, with the function
allowing easy checks for text and integer input, minimum and maximum values /
character lengths, or can even be verified by a custom function. Once the form
is submitted, the form's data is submitted as a dictionary to any callable of
your choice.
The function that initializes the fillable form menu is fairly simple, and
includes the caller, the template for the form, and the callback(caller, result)
to which the form data will be sent to upon submission.
init_fill_field(formtemplate, caller, formcallback)
Form templates are defined as a list of dictionaries - each dictionary
represents a field in the form, and contains the data for the field's name and
behavior. For example, this basic form template will allow a player to fill out
a brief character profile:
PROFILE_TEMPLATE = [
{"fieldname":"Name", "fieldtype":"text"},
{"fieldname":"Age", "fieldtype":"number"},
{"fieldname":"History", "fieldtype":"text"},
]
This will present the player with an EvMenu showing this basic form:
```
Name:
Age:
History:
```
While in this menu, the player can assign a new value to any field with the
syntax <field> = <new value>, like so:
```
> name = Ashley
Field 'Name' set to: Ashley
```
Typing 'look' by itself will show the form and its current values.
```
> look
Name: Ashley
Age:
History:
```
Number fields require an integer input, and will reject any text that can't
be converted into an integer.
```
> age = youthful
Field 'Age' requires a number.
> age = 31
Field 'Age' set to: 31
```
Form data is presented as an EvTable, so text of any length will wrap cleanly.
```
> history = EVERY MORNING I WAKE UP AND OPEN PALM SLAM[...]
Field 'History' set to: EVERY MORNING I WAKE UP AND[...]
> look
Name: Ashley
Age: 31
History: EVERY MORNING I WAKE UP AND OPEN PALM SLAM A VHS INTO THE SLOT.
IT'S CHRONICLES OF RIDDICK AND RIGHT THEN AND THERE I START DOING
THE MOVES ALONGSIDE WITH THE MAIN CHARACTER, RIDDICK. I DO EVERY
MOVE AND I DO EVERY MOVE HARD.
```
When the player types 'submit' (or your specified submit command), the menu
quits and the form's data is passed to your specified function as a dictionary,
like so:
formdata = {"Name":"Ashley", "Age":31, "History":"EVERY MORNING I[...]"}
You can do whatever you like with this data in your function - forms can be used
to set data on a character, to help builders create objects, or for players to
craft items or perform other complicated actions with many variables involved.
The data that your form will accept can also be specified in your form template -
let's say, for example, that you won't accept ages under 18 or over 100. You can
do this by specifying "min" and "max" values in your field's dictionary:
```
PROFILE_TEMPLATE = [
{"fieldname":"Name", "fieldtype":"text"},
{"fieldname":"Age", "fieldtype":"number", "min":18, "max":100},
{"fieldname":"History", "fieldtype":"text"}
]
```
Now if the player tries to enter a value out of range, the form will not acept the
given value.
```
> age = 10
Field 'Age' reqiures a minimum value of 18.
> age = 900
Field 'Age' has a maximum value of 100.
```
Setting 'min' and 'max' for a text field will instead act as a minimum or
maximum character length for the player's input.
There are lots of ways to present the form to the player - fields can have default
values or show a custom message in place of a blank value, and player input can be
verified by a custom function, allowing for a great deal of flexibility. There
is also an option for 'bool' fields, which accept only a True / False input and
can be customized to represent the choice to the player however you like (E.G.
Yes/No, On/Off, Enabled/Disabled, etc.)
This module contains a simple example form that demonstrates all of the included
functionality - a command that allows a player to compose a message to another
online character and have it send after a custom delay. You can test it by
importing this module in your game's `default_cmdsets.py` module and adding
CmdTestMenu to your default character's command set.
## FIELD TEMPLATE KEYS:
### Required:
```
fieldname (str): Name of the field, as presented to the player.
fieldtype (str): Type of value required: 'text', 'number', or 'bool'.
```
### Optional:
- max (int): Maximum character length (if text) or value (if number).
- min (int): Minimum charater length (if text) or value (if number).
- truestr (str): String for a 'True' value in a bool field.
(E.G. 'On', 'Enabled', 'Yes')
- falsestr (str): String for a 'False' value in a bool field.
(E.G. 'Off', 'Disabled', 'No')
- default (str): Initial value (blank if not given).
- blankmsg (str): Message to show in place of value when field is blank.
- cantclear (bool): Field can't be cleared if True.
- required (bool): If True, form cannot be submitted while field is blank.
- verifyfunc (callable): Name of a callable used to verify input - takes
(caller, value) as arguments. If the function returns True,
the player's input is considered valid - if it returns False,
the input is rejected. Any other value returned will act as
the field's new value, replacing the player's input. This
allows for values that aren't strings or integers (such as
object dbrefs). For boolean fields, return '0' or '1' to set
the field to False or True.
----
<small>This document page is generated from `evennia/contrib/utils/fieldfill/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,55 @@
# Gendersub
Contrib - Griatch 2015
This is a simple gender-aware Character class for allowing users to
insert custom markers in their text to indicate gender-aware
messaging. It relies on a modified msg() and is meant as an
inspiration and starting point to how to do stuff like this.
An object can have the following genders:
- male (he/his)
- female (her/hers)
- neutral (it/its)
- ambiguous (they/them/their/theirs)
## Installation
Import and add the `SetGender` command to your default cmdset in
`mygame/commands/default_cmdset.py`
Make your `Character` inherit from `GenderCharacter`.
## Usage
When in use, messages can contain special tags to indicate pronouns gendered
based on the one being addressed. Capitalization will be retained.
- `|s`, `|S`: Subjective form: he, she, it, He, She, It, They
- `|o`, `|O`: Objective form: him, her, it, Him, Her, It, Them
- `|p`, `|P`: Possessive form: his, her, its, His, Her, Its, Their
- `|a`, `|A`: Absolute Possessive form: his, hers, its, His, Hers, Its, Theirs
For example,
```
char.msg("%s falls on |p face with a thud." % char.key)
"Tom falls on his face with a thud"
```
The default gender is "ambiguous" (they/them/their/theirs).
To use, have DefaultCharacter inherit from this, or change
setting.DEFAULT_CHARACTER to point to this class.
The `gender` command is used to set the gender. It needs to be added to the
default cmdset before it becomes available.
----
<small>This document page is generated from `evennia/contrib/game_systems/gendersub/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,42 @@
# Health Bar
Contrib - Tim Ashley Jenkins 2017
The function provided in this module lets you easily display visual
bars or meters - "health bar" is merely the most obvious use for this,
though these bars are highly customizable and can be used for any sort
of appropriate data besides player health.
Today's players may be more used to seeing statistics like health,
stamina, magic, and etc. displayed as bars rather than bare numerical
values, so using this module to present this data this way may make it
more accessible. Keep in mind, however, that players may also be using
a screen reader to connect to your game, which will not be able to
represent the colors of the bar in any way. By default, the values
represented are rendered as text inside the bar which can be read by
screen readers.
## Usage
No installation, just import and use `display_meter` from this
module:
```python
from evennia.contrib.rpg.health_bar import display_meter
# health is 23/100
health_bar = display_meter(23, 100)
caller.msg(prompt=health_bar)
```
The health bar will account for current values above the maximum or
below 0, rendering them as a completely full or empty bar with the
values displayed within.
----
<small>This document page is generated from `evennia/contrib/rpg/health_bar/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,888 @@
# Evennia in-game Python system
Vincent Le Goff 2017
This contrib adds the system of in-game Python in Evennia, allowing immortals
(or other trusted builders) to dynamically add features to individual objects.
Using custom Python set in-game, every immortal or privileged users could have a
specific room, exit, character, object or something else behave differently from
its "cousins". For these familiar with the use of softcode in MU`*`, like SMAUG
MudProgs, the ability to add arbitrary behavior to individual objects is a step
toward freedom. Keep in mind, however, the warning below, and read it carefully
before the rest of the documentation.
## A WARNING REGARDING SECURITY
Evennia's in-game Python system will run arbitrary Python code without much
restriction. Such a system is as powerful as potentially dangerous, and you
will have to keep in mind these points before deciding to install it:
1. Untrusted people can run Python code on your game server with this system.
Be careful about who can use this system (see the permissions below).
2. You can do all of this in Python outside the game. The in-game Python system
is not to replace all your game feature.
## Basic structure and vocabulary
- At the basis of the in-game Python system are **events**. An **event**
defines the context in which we would like to call some arbitrary code. For
instance, one event is defined on exits and will fire every time a character
traverses through this exit. Events are described on a [typeclass](../Components/Typeclasses.md)
([exits](../Components/Objects.md#exits) in our example). All objects inheriting from this
typeclass will have access to this event.
- **Callbacks** can be set on individual objects, on events defined in code.
These **callbacks** can contain arbitrary code and describe a specific
behavior for an object. When the event fires, all callbacks connected to this
object's event are executed.
To see the system in context, when an object is picked up (using the default
`get` command), a specific event is fired:
1. The event "get" is set on objects (on the `Object` typeclass).
2. When using the "get" command to pick up an object, this object's `at_get`
hook is called.
3. A modified hook of DefaultObject is set by the event system. This hook will
execute (or call) the "get" event on this object.
4. 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.
5. In individual callbacks, you can add multiple lines of Python code that will
be fired at this point. In this example, the `character` variable will
contain the character who has picked up the object, while `obj` will contain the
object that was picked up.
Following this example, if you create a callback "get" on the object "a sword",
and put in it:
```python
character.msg("You have picked up {} and have completed this quest!".format(obj.get_display_name(character)))
```
When you pick up this object you should see something like:
You pick up a sword.
You have picked up a sword and have completed this quest!
## Installation
Being in a separate contrib, the in-game Python system isn't installed by
default. You need to do it manually, following these steps:
This is the quick summary. Scroll down for more detailed help on each step.
1. Launch the main script (important!):
```py evennia.create_script("evennia.contrib.base_systems.ingame_python.scripts.EventHandler")```
2. Set the permissions (optional):
- `EVENTS_WITH_VALIDATION`: a group that can edit callbacks, but will need approval (default to
`None`).
- `EVENTS_WITHOUT_VALIDATION`: a group with permission to edit callbacks without need of
validation (default to `"immortals"`).
- `EVENTS_VALIDATING`: a group that can validate callbacks (default to `"immortals"`).
- `EVENTS_CALENDAR`: type of the calendar to be used (either `None`, `"standard"` or `"custom"`,
default to `None`).
3. Add the `call` command.
4. Inherit from the custom typeclasses of the in-game Python system.
- `evennia.contrib.base_systems.ingame_python.typeclasses.EventCharacter`: to replace `DefaultCharacter`.
- `evennia.contrib.base_systems.ingame_python.typeclasses.EventExit`: to replace `DefaultExit`.
- `evennia.contrib.base_systems.ingame_python.typeclasses.EventObject`: to replace `DefaultObject`.
- `evennia.contrib.base_systems.ingame_python.typeclasses.EventRoom`: to replace `DefaultRoom`.
The following sections describe in details each step of the installation.
> 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 `1` the error will go away.
### Starting the event script
To start the event script, you only need a single command, using `@py`.
py evennia.create_script("evennia.contrib.base_systems.ingame_python.scripts.EventHandler")
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 `callback`
handler on all objects (see below for details).
### Editing permissions
This contrib comes with its own set of permissions. They define who can edit callbacks without
validation, and who can edit callbacks but needs validation. Validation is a process in which an
administrator (or somebody trusted as such) will check the callbacks produced by others and will
accept or reject them. If accepted, the callbacks are connected, otherwise they are never run.
By default, callbacks can only be created by immortals: no one except the immortals can edit
callbacks, and immortals don't need validation. It can easily be changed, either through settings
or dynamically by changing permissions of users.
The ingame-python contrib adds three [permissions](../Components/Permissions.md)) in the settings. You can
override them by changing the settings into your `server/conf/settings.py` file (see below for an
example). The settings defined in the events contrib are:
- `EVENTS_WITH_VALIDATION`: this defines a permission that can edit callbacks, but will need
approval. If you set this to `"wizards"`, for instance, users with the permission `"wizards"`
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 `None`, meaning that no user is
allowed to edit callbacks with validation.
- `EVENTS_WITHOUT_VALIDATION`: this setting defines a permission allowing editing of callbacks
without needing validation. By default, this setting is set to `"immortals"`. It means that
immortals can edit callbacks, and they will be connected when they leave the editor, without needing
approval.
- `EVENTS_VALIDATING`: this last setting defines who can validate callbacks. By default, this is
set to `"immortals"`, meaning only immortals can see callbacks needing validation, accept or
reject them.
You can override all these settings in your `server/conf/settings.py` file. For instance:
```python
# ... other settings ...
# Event settings
EVENTS_WITH_VALIDATION = "wizards"
EVENTS_WITHOUT_VALIDATION = "immortals"
EVENTS_VALIDATING = "immortals"
```
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
`EVENTS_CALENDAR` to set it to:
- `"standard"`: the standard calendar, with standard days, months, years and so on.
- `"custom"`: a custom calendar that will use the `custom_gametime` contrib to schedule events.
This contrib defines two additional permissions that can be set on individual users:
- `events_without_validation`: this would give this user the rights to edit callbacks but not
require validation before they are connected.
- `events_validating`: this permission allows this user to run validation checks on callbacks
needing to be validated.
For instance, to give the right to edit callbacks without needing approval to the player 'kaldara',
you might do something like:
perm *kaldara = events_without_validation
To remove this same permission, just use the `/del` switch:
perm/del *kaldara = events_without_validation
The rights to use the `call` command are directly related to these permissions: by default, only
users who have the `events_without_validation` permission or are in (or above) the group defined in
the `EVENTS_WITH_VALIDATION` setting will be able to call the command (with different switches).
### Adding the `call` command
You also have to add the `@call` command to your Character CmdSet. This command allows your users
to add, edit and delete callbacks in-game. In your `commands/default_cmdsets, it might look like
this:
```python
from evennia import default_cmds
from evennia.contrib.base_systems.ingame_python.commands import CmdCallback
class CharacterCmdSet(default_cmds.CharacterCmdSet):
"""
The `CharacterCmdSet` contains general in-game commands like `look`,
`get`, etc available on in-game Character objects. It is merged with
the `PlayerCmdSet` when a Player puppets a Character.
"""
key = "DefaultCharacter"
def at_cmdset_creation(self):
"""
Populates the cmdset
"""
super(CharacterCmdSet, self).at_cmdset_creation()
self.add(CmdCallback())
```
### Changing parent classes of typeclasses
Finally, to use the in-game Python system, you need to have your typeclasses inherit from the modified event
classes. For instance, in your `typeclasses/characters.py` module, you should change inheritance
like this:
```python
from evennia.contrib.base_systems.ingame_python.typeclasses import EventCharacter
class Character(EventCharacter):
# ...
```
You should do the same thing for your rooms, exits and objects. Note that the
in-game Python system works by overriding some hooks. Some of these features
might not be accessible in your game if you don't call the parent methods when
overriding hooks.
## Using the `call` command
The in-game Python system relies, to a great extent, on its `call` command.
Who can execute this command, and who can do what with it, will depend on your
set of permissions.
The `call` 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 `call` 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.
### Examining callbacks and events
To see the events connected to an object, use the `call` command and give the name or ID of the
object to examine. For instance, `call here` to examine the events on your current location. Or
`call self` to see the events on yourself.
This command will display a table, containing:
- The name of each event in the first column.
- The number of callbacks of this name, and the number of total lines of these callbacks in the
second column.
- A short help to tell you when the event is triggered in the third column.
If you execute `call #1` for instance, you might see a table like this:
```
+------------------+---------+-----------------------------------------------+
| Event name | Number | Description |
+~~~~~~~~~~~~~~~~~~+~~~~~~~~~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| can_delete | 0 (0) | Can the character be deleted? |
| can_move | 0 (0) | Can the character move? |
| can_part | 0 (0) | Can the departing character leave this room? |
| delete | 0 (0) | Before deleting the character. |
| greet | 0 (0) | A new character arrives in the location of |
| | | this character. |
| move | 0 (0) | After the character has moved into its new |
| | | room. |
| puppeted | 0 (0) | When the character has been puppeted by a |
| | | player. |
| time | 0 (0) | A repeated event to be called regularly. |
| unpuppeted | 0 (0) | When the character is about to be un- |
| | | puppeted. |
+------------------+---------+-----------------------------------------------+
```
### Creating a new callback
The `/add` switch should be used to add a callback. It takes two arguments beyond the object's
name/DBREF:
1. After an = sign, the name of the event to be edited (if not supplied, will display the list of
possible events, like above).
2. The parameters (optional).
We'll see callbacks with parameters later. For the time being, let's try to prevent a character
from going through the "north" exit of this room:
```
@call north
+------------------+---------+-----------------------------------------------+
| Event name | Number | Description |
+~~~~~~~~~~~~~~~~~~+~~~~~~~~~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| can_traverse | 0 (0) | Can the character traverse through this exit? |
| msg_arrive | 0 (0) | Customize the message when a character |
| | | arrives through this exit. |
| msg_leave | 0 (0) | Customize the message when a character leaves |
| | | through this exit. |
| time | 0 (0) | A repeated event to be called regularly. |
| traverse | 0 (0) | After the character has traversed through |
| | | this exit. |
+------------------+---------+-----------------------------------------------+
```
If we want to prevent a character from traversing through this exit, the best event for us would be
"can_traverse".
> Why not "traverse"? If you read the description of both events, you will see "traverse" is called
**after** the character has traversed through this exit. It would be too late to prevent it. On
> the other hand, "can_traverse" is obviously checked before the character traverses.
When we edit the event, we have some more information:
call/add north = can_traverse
Can the character traverse through this exit?
This event is called when a character is about to traverse this
exit. You can use the deny() eventfunc to deny the character from
exiting for this time.
Variables you can use in this event:
- character: the character that wants to traverse this exit.
- exit: the exit to be traversed.
- room: the room in which stands the character before moving.
The section dedicated to [eventfuncs](#the-eventfuncs) will elaborate on the `deny()` function and
other eventfuncs. Let us say, for the time being, that it can prevent an action (in this case, it
can prevent the character from traversing through this exit). In the editor that opened when you
used `call/add`, you can type something like:
```python
if character.id == 1:
character.msg("You're the superuser, 'course I'll let you pass.")
else:
character.msg("Hold on, what do you think you're doing?")
deny()
```
You can now enter `:wq` to leave the editor by saving the callback.
If you enter `call north`, you should see that "can_traverse" now has an active callback. You can
use `call north = can_traverse` to see more details on the connected callbacks:
```
call north = can_traverse
+--------------+--------------+----------------+--------------+--------------+
| Number | Author | Updated | Param | Valid |
+~~~~~~~~~~~~~~+~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~+~~~~~~~~~~~~~~+
| 1 | XXXXX | 5 seconds ago | | Yes |
+--------------+--------------+----------------+--------------+--------------+
```
The left column contains callback numbers. You can use them to have even more information on a
specific event. Here, for instance:
```
call north = can_traverse 1
Callback can_traverse 1 of north:
Created by XXXXX on 2017-04-02 17:58:05.
Updated by XXXXX on 2017-04-02 18:02:50
This callback is connected and active.
Callback code:
if character.id == 1:
character.msg("You're the superuser, 'course I'll let you pass.")
else:
character.msg("Hold on, what do you think you're doing?")
deny()
```
Then try to walk through this exit. Do it with another character if possible, too, to see the
difference.
### Editing and removing a callback
You can use the `/edit` switch to the `@call` command to edit a callback. You should provide, after
the name of the object to edit and the equal sign:
1. The name of the event (as seen above).
2. A number, if several callbacks are connected at this location.
You can type `call/edit <object> = <event name>` 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, `call/edit north = can_traverse 2`).
The command `call` also provides a `/del` switch to remove a callback. It takes the same arguments
as the `/edit` switch.
When removed, callbacks are logged, so an administrator can retrieve its content, assuming the
`/del` was an error.
### The code editor
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 [a dedicated section of the EvEditor's
documentation](https://github.com/evennia/evennia/wiki/EvEditor#the-eveditor-to-edit-code).
## Using events
The following sections describe how to use events for various tasks, from the most simple to the
most complex.
### The eventfuncs
In order to make development a little easier, the in-game Python system provides eventfuncs to be used in
callbacks themselves. You don't have to use them, they are just shortcuts. An eventfunc is just a
simple function that can be used inside of your callback code.
Function | Argument | Description | Example
-----------|--------------------------|-----------------------------------|--------
deny | `()` | Prevent an action from happening. | `deny()`
get | `(**kwargs)` | Get a single object. | `char = get(id=1)`
call_event | `(obj, name, seconds=0)` | Call another event. | `call_event(char, "chain_1", 20)`
#### deny
The `deny()` function allows to interrupt the callback and the action that called it. In the
`can_*` events, it can be used to prevent the action from happening. For instance, in `can_say` on
rooms, it can prevent the character from saying something in the room. One could have a `can_eat`
event set on food that would prevent this character from eating this food.
Behind the scenes, the `deny()` function raises an exception that is being intercepted by the
handler of events. The handler will then report that the action was cancelled.
#### get
The `get` eventfunc is a shortcut to get a single object with a specific identity. It's often used
to retrieve an object with a given ID. In the section dedicated to [chained
events](#chained-events), you will see a concrete example of this function in action.
#### call_event
Some callbacks will call other events. It is particularly useful for [chained
events](#chained-events) that are described in a dedicated section. This eventfunc is used to call
another event, immediately or in a defined time.
You need to specify as first parameter the object containing the event. The second parameter is the
name of the event to call. The third parameter is the number of seconds before calling this event.
By default, this parameter is set to 0 (the event is called immediately).
### Variables in callbacks
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 `character` variable that holds the character doing the action.
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.
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.
call/add down = msg_leave
Which should display:
```
Customize the message when a character leaves through this exit.
This event is called when a character leaves through this exit.
To customize the message that will be sent to the room where the
character came from, change the value of the variable "message"
to give it your custom message. The character itself will not be
notified. You can use mapping between braces, like this:
message = "{character} falls into a hole!"
In your mapping, you can use {character} (the character who is
about to leave), {exit} (the exit), {origin} (the room in which
the character is), and {destination} (the room in which the character
is heading for). If you need to customize the message with other
information, you can also set "message" to None and send something
else instead.
Variables you can use in this event:
character: the character who is leaving through this exit.
exit: the exit being traversed.
origin: the location of the character.
destination: the destination of the character.
message: the message to be displayed in the location.
mapping: a dictionary containing additional mapping.
```
If you write something like this in your event:
```python
message = "{character} falls into a hole in the ground!"
```
And if the character Wilfred takes this exit, others in the room will see:
Wildred falls into a hole in the ground!
In this case, the in-game Python system placed the variable "message" in the callback locals, but will read
from it when the event has been executed.
### Callbacks with parameters
Some callbacks are called without parameter. It has been the case for all examples we have seen
before. In some cases, you can create callbacks that are triggered under only some conditions. A
typical example is the room's "say" event. This event is triggered when somebody says something in
the room. Individual callbacks set on this event can be configured to fire only when some words are
used in the sentence.
For instance, let's say we want to create a cool voice-operated elevator. You enter into the
elevator and say the floor number... and the elevator moves in the right direction. In this case,
we could create an callback with the parameter "one":
call/add here = say one
This callback will only fire when the user says a sentence that contains "one".
But what if we want to have a callback that would fire if the user says 1 or one? We can provide
several parameters, separated by a comma.
call/add here = say 1, one
Or, still more keywords:
call/add here = say 1, one, ground
This time, the user could say something like "take me to the ground floor" ("ground" is one of our
keywords defined in the above callback).
Not all events can take parameters, and these who do have different ways of handling them. There
isn't a single meaning to parameters that could apply to all events. Refer to the event
documentation for details.
> If you get confused between callback variables and parameters, think of parameters as checks
> performed before the callback is run. Event with parameters will only fire some specific
> callbacks, not all of them.
### Time-related events
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!
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.
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):
call here = time 12:00
```python
# This will be called every MUD day at 12:00 PM
room.msg_contents("It's noon, time to have lunch!")
```
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.
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.
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).
Some examples of syntax:
- `18:30`: every day at 6:30 PM.
- `01 12:00`: every month, the first day, at 12 PM.
- `06-15 09:58`: every year, on the 15th of June (month comes before day), at 9:58 AM.
- `2025-01-01 00:00`: January 1st, 2025 at midnight (obviously, this will trigger only once).
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 `12:00`, the smallest unit that is not defined is "day":
the event will fire every day at the specified time.
> You can use chained events (see below) in conjunction with time-related events to create more
random or frequent actions in events.
### Chained events
Callbacks can call other events, either now or a bit later. It is potentially very powerful.
To use chained events, just use the `call_event` eventfunc. It takes 2-3 arguments:
- The object containing the event.
- The name of the event to call.
- Optionally, the number of seconds to wait before calling this event.
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".
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:
call/add here = time 10:00
```python
# At 10:00 AM, the subway arrives in the room of ID 22.
# Notice that exit #23 and #24 are respectively the exit leading
# on the platform and back in the subway.
station = get(id=22)
to_exit = get(id=23)
back_exit = get(id=24)
# Open the door
to_exit.name = "platform"
to_exit.aliases = ["p"]
to_exit.location = room
to_exit.destination = station
back_exit.name = "subway"
back_exit.location = station
back_exit.destination = room
# Display some messages
room.msg_contents("The doors open and wind gushes in the subway")
station.msg_contents("The doors of the subway open with a dull clank.")
# Set the doors to close in 20 seconds
call_event(room, "chain_1", 20)
```
This callback will:
1. Be called at 10:00 AM (specify 22:00 to set it to 10:00 PM).
2. Set an exit between the subway and the station. Notice that the exits already exist (you will
not have to create them), but they don't need to have specific location and destination.
3. Display a message both in the subway and on the platform.
4. Call the event "chain_1" to execute in 20 seconds.
And now, what should we have in "chain_1"?
call/add here = chain_1
```python
# Close the doors
to_exit.location = None
to_exit.destination = None
back_exit.location = None
back_exit.destination = None
room.msg_content("After a short warning signal, the doors close and the subway begins moving.")
station.msg_content("After a short warning signal, the doors close and the subway begins moving.")
```
Behind the scenes, the `call_event` function freezes all variables ("room", "station", "to_exit",
"back_exit" in our example), so you don't need to define them again.
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 `chain_1` calls `chain_2` that calls `chain_3` that calls
`chain_`, particularly if there's no pause between them, you might run into an infinite loop.
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 `call_event()`, 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.
> 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
several chained events in the same object.
## Using events in code
This section describes callbacks and events from code, how to create new events, how to call them in
a command, and how to handle specific cases like parameters.
Along this section, we will see how to implement the following example: we would like to create a
"push" command that could be used to push objects. Objects could react to this command and have
specific events fired.
### Adding new events
Adding new events should be done in your typeclasses. Events are contained in the `_events` 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.
Here, we want to add a "push" event on objects. In your `typeclasses/objects.py` file, you should
write something like:
```python
from evennia.contrib.base_systems.ingame_python.utils import register_events
from evennia.contrib.base_systems.ingame_python.typeclasses import EventObject
EVENT_PUSH = """
A character push the object.
This event is called when a character uses the "push" command on
an object in the same room.
Variables you can use in this event:
character: the character that pushes this object.
obj: the object connected to this event.
"""
@register_events
class Object(EventObject):
"""
Class representing objects.
"""
_events = {
"push": (["character", "obj"], EVENT_PUSH),
}
```
- Line 1-2: we import several things we will need from the in-game Python system. Note that we use
`EventObject` as a parent instead of `DefaultObject`, as explained in the installation.
- 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.
- 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.
- Line 15: we create the class inheriting from `EventObject`.
- Line 20-22: we define the events of our objects in an `_events` class variable. It is a
dictionary. Keys are event names. Values are a tuple containing:
- 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).
- The event help (a str, the one we have defined above).
If you add this code and reload your game, create an object and examine its events with `@call`, you
should see the "push" event with its help. Of course, right now, the event exists, but it's not
fired.
### Calling an event in code
The in-game Python system is accessible through a handler on all objects. This handler is named `callbacks`
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.
To call an event, use the `callbacks.call` method in an object. It takes as argument:
- The name of the event to call.
- All variables that will be accessible in the event as positional arguments. They should be
specified in the order chosen when [creating new events](#adding-new-events).
Following the same example, so far, we have created an event on all objects, called "push". This
event is never fired for the time being. We could add a "push" command, taking as argument the name
of an object. If this object is valid, it will call its "push" event.
```python
from commands.command import Command
class CmdPush(Command):
"""
Push something.
Usage:
push <something>
Push something where you are, like an elevator button.
"""
key = "push"
def func(self):
"""Called when pushing something."""
if not self.args.strip():
self.msg("Usage: push <something>")
return
# Search for this object
obj = self.caller.search(self.args)
if not obj:
return
self.msg("You push {}.".format(obj.get_display_name(self.caller)))
# Call the "push" event of this object
obj.callbacks.call("push", self.caller, obj)
```
Here we use `callbacks.call` with the following arguments:
- `"push"`: the name of the event to be called.
- `self.caller`: the one who pushed the button (this is our first variable, `character`).
- `obj`: the object being pushed (our second variable, `obj`).
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).
### See it all work
To see the effect of the two modifications above (the added event and the "push" command), let us
create a simple object:
@create/drop rock
@desc rock = It's a single rock, apparently pretty heavy. Perhaps you can try to push it though.
@call/add rock = push
In the callback you could write:
```python
from random import randint
number = randint(1, 6)
character.msg("You push a rock... is... it... going... to... move?")
if number == 6:
character.msg("The rock topples over to reveal a beautiful ant-hill!")
```
You can now try to "push rock". You'll try to push the rock, and once out of six times, you will
see a message about a "beautiful ant-hill".
### Adding new eventfuncs
Eventfuncs, like `deny()`, are defined in
`contrib/base_systesm/ingame_python/eventfuncs.py`. You can add your own
eventfuncs by creating a file named `eventfuncs.py` in your `world` directory.
The functions defined in this file will be added as helpers.
You can also decide to create your eventfuncs in another location, or even in
several locations. To do so, edit the `EVENTFUNCS_LOCATION` setting in your
`server/conf/settings.py` file, specifying either a python path or a list of
Python paths in which your helper functions are defined. For instance:
```python
EVENTFUNCS_LOCATIONS = [
"world.events.functions",
]
```
### Creating events with parameters
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' `_events` 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).
- 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.
- 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).
In both cases, you need to import a function from
`evennia.contrib.base_systems.ingame_python.utils` and use it as third parameter in your
event definition.
- `keyword_event` should be used for keyword parameters.
- `phrase_event` should be used for phrase parameters.
For example, here is the definition of the "say" event:
```python
from evennia.contrib.base_systems.ingame_python.utils import register_events, phrase_event
# ...
@register_events
class SomeTypeclass:
_events = {
"say": (["speaker", "character", "message"], CHARACTER_SAY, phrase_event),
}
```
When you call an event using the `obj.callbacks.call` method, you should also provide the parameter,
using the `parameters` keyword:
```python
obj.callbacks.call(..., parameters="<put parameters here>")
```
It is necessary to specifically call the event with parameters, otherwise the system will not be
able to know how to filter down the list of callbacks.
## Disabling all events at once
When callbacks are running in an infinite loop, for instance, or sending unwanted information to
players or other sources, you, as the game administrator, have the power to restart without events.
The best way to do this is to use a custom setting, in your setting file
(`server/conf/settings.py`):
```python
# Disable all events
EVENTS_DISABLED = True
```
The in-game Python system will still be accessible (you will have access to the `call` command, to debug),
but no event will be called automatically.
----
<small>This document page is generated from `evennia/contrib/base_systems/ingame_python/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,46 @@
# In-Game Mail system
Evennia Contribution - grungies1138 2016
A simple Brandymail style mail system that uses the Msg class from Evennia
Core. It has two Commands, both of which can be used on their own:
- CmdMail - this should sit on the Account cmdset and makes the `mail` command
available both IC and OOC. Mails will always go to Accounts (other players).
- CmdMailCharacter - this should sit on the Character cmdset and makes the `mail`
command ONLY available when puppeting a character. Mails will be sent to other
Characters only and will not be available when OOC.
- If adding *both* commands to their respective cmdsets, you'll get two separate
IC and OOC mailing systems, with different lists of mail for IC and OOC modes.
## Installation:
Install one or both of the following (see above):
- CmdMail (IC + OOC mail, sent between players)
# mygame/commands/default_cmds.py
from evennia.contrib.game_systems import mail
# in AccountCmdSet.at_cmdset_creation:
self.add(mail.CmdMail())
- CmdMailCharacter (optional, IC only mail, sent between characters)
# mygame/commands/default_cmds.py
from evennia.contrib.game_systems import mail
# in CharacterCmdSet.at_cmdset_creation:
self.add(mail.CmdMailCharacter())
Once installed, use `help mail` in game for help with the mail command. Use
ic/ooc to switch in and out of IC/OOC modes.
----
<small>This document page is generated from `evennia/contrib/game_systems/mail/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,284 @@
# Map Builder
Contribution - Cloud_Keeper 2016
Build a map from a 2D ASCII map.
This is a command which takes two inputs:
≈≈≈≈≈
≈♣n♣≈ MAP_LEGEND = {("♣", "♠"): build_forest,
≈∩▲∩≈ ("∩", "n"): build_mountains,
≈♠n♠≈ ("▲"): build_temple}
≈≈≈≈≈
A string of ASCII characters representing a map and a dictionary of functions
containing build instructions. The characters of the map are iterated over and
compared to a list of trigger characters. When a match is found the
corresponding function is executed generating the rooms, exits and objects as
defined by the users build instructions. If a character is not a match to
a provided trigger character (including spaces) it is simply skipped and the
process continues.
For instance, the above map represents a temple (▲) amongst mountains (n,∩)
in a forest (♣,♠) on an island surrounded by water (≈). Each character on the
first line is iterated over but as there is no match with our `MAP_LEGEND`, it
is skipped. On the second line it finds "♣" which is a match and so the
`build_forest` function is called. Next the `build_mountains` function is
called and so on until the map is completed. Building instructions are passed
the following arguments:
x - The rooms position on the maps x axis
y - The rooms position on the maps y axis
caller - The account calling the command
iteration - The current iterations number (0, 1 or 2)
room_dict - A dictionary containing room references returned by build
functions where tuple coordinates are the keys (x, y).
ie room_dict[(2, 2)] will return the temple room above.
Building functions should return the room they create. By default these rooms
are used to create exits between valid adjacent rooms to the north, south,
east and west directions. This behaviour can turned off with the use of switch
arguments. In addition to turning off automatic exit generation the switches
allow the map to be iterated over a number of times. This is important for
something like custom exit building. Exits require a reference to both the
exits location and the exits destination. During the first iteration it is
possible that an exit is created pointing towards a destination that
has not yet been created resulting in error. By iterating over the map twice
the rooms can be created on the first iteration and room reliant code can be
be used on the second iteration. The iteration number and a dictionary of
references to rooms previously created is passed to the build commands.
You then call the command in-game using the path to the MAP and MAP_LEGEND vars
The path you provide is relative to the evennia or mygame folder.
# Installation
Use by importing and including the command in your default_cmdsets module.
For example:
```python
# mygame/commands/default_cmdsets.py
from evennia.contrib.grid import mapbuilder
...
self.add(mapbuilder.CmdMapBuilder())
```
# Usage:
mapbuilder[/switch] <path.to.file.MAPNAME> <path.to.file.MAP_LEGEND>
one - execute build instructions once without automatic exit creation.
two - execute build instructions twice without automatic exit creation.
# Examples
mapbuilder world.gamemap.MAP world.maplegend.MAP_LEGEND
mapbuilder evennia.contrib.grid.mapbuilder.EXAMPLE1_MAP EXAMPLE1_LEGEND
mapbuilder/two evennia.contrib.grid.mapbuilder.EXAMPLE2_MAP EXAMPLE2_LEGEND
(Legend path defaults to map path)
Below are two examples showcasing the use of automatic exit generation and
custom exit generation. Whilst located, and can be used, from this module for
convenience The below example code should be in mymap.py in mygame/world.
## Example One
```python
from django.conf import settings
from evennia.utils import utils
# mapbuilder evennia.contrib.grid.mapbuilder.EXAMPLE1_MAP EXAMPLE1_LEGEND
# -*- coding: utf-8 -*-
# Add the necessary imports for your instructions here.
from evennia import create_object
from typeclasses import rooms, exits
from random import randint
import random
# A map with a temple (▲) amongst mountains (n,∩) in a forest (♣,♠) on an
# island surrounded by water (≈). By giving no instructions for the water
# characters we effectively skip it and create no rooms for those squares.
EXAMPLE1_MAP = '''
≈≈≈≈≈
≈♣n♣≈
≈∩▲∩≈
≈♠n♠≈
≈≈≈≈≈
'''
def example1_build_forest(x, y, **kwargs):
'''A basic example of build instructions. Make sure to include **kwargs
in the arguments and return an instance of the room for exit generation.'''
# Create a room and provide a basic description.
room = create_object(rooms.Room, key="forest" + str(x) + str(y))
room.db.desc = "Basic forest room."
# Send a message to the account
kwargs["caller"].msg(room.key + " " + room.dbref)
# This is generally mandatory.
return room
def example1_build_mountains(x, y, **kwargs):
'''A room that is a little more advanced'''
# Create the room.
room = create_object(rooms.Room, key="mountains" + str(x) + str(y))
# Generate a description by randomly selecting an entry from a list.
room_desc = [
"Mountains as far as the eye can see",
"Your path is surrounded by sheer cliffs",
"Haven't you seen that rock before?",
]
room.db.desc = random.choice(room_desc)
# Create a random number of objects to populate the room.
for i in range(randint(0, 3)):
rock = create_object(key="Rock", location=room)
rock.db.desc = "An ordinary rock."
# Send a message to the account
kwargs["caller"].msg(room.key + " " + room.dbref)
# This is generally mandatory.
return room
def example1_build_temple(x, y, **kwargs):
'''A unique room that does not need to be as general'''
# Create the room.
room = create_object(rooms.Room, key="temple" + str(x) + str(y))
# Set the description.
room.db.desc = (
"In what, from the outside, appeared to be a grand and "
"ancient temple you've somehow found yourself in the the "
"Evennia Inn! It consists of one large room filled with "
"tables. The bardisk extends along the east wall, where "
"multiple barrels and bottles line the shelves. The "
"barkeep seems busy handing out ale and chatting with "
"the patrons, which are a rowdy and cheerful lot, "
"keeping the sound level only just below thunderous. "
"This is a rare spot of mirth on this dread moor."
)
# Send a message to the account
kwargs["caller"].msg(room.key + " " + room.dbref)
# This is generally mandatory.
return room
# Include your trigger characters and build functions in a legend dict.
EXAMPLE1_LEGEND = {
("♣", "♠"): example1_build_forest,
("∩", "n"): example1_build_mountains,
("▲"): example1_build_temple,
}
```
## Example Two
```python
# @mapbuilder/two evennia.contrib.grid.mapbuilder.EXAMPLE2_MAP EXAMPLE2_LEGEND
# -*- coding: utf-8 -*-
# Add the necessary imports for your instructions here.
# from evennia import create_object
# from typeclasses import rooms, exits
# from evennia.utils import utils
# from random import randint
# import random
# This is the same layout as Example 1 but included are characters for exits.
# We can use these characters to determine which rooms should be connected.
EXAMPLE2_MAP = '''
≈ ≈ ≈ ≈ ≈
≈ ♣-♣-♣ ≈
| |
≈ ♣ ♣ ♣ ≈
| | |
≈ ♣-♣-♣ ≈
≈ ≈ ≈ ≈ ≈
'''
def example2_build_forest(x, y, **kwargs):
'''A basic room'''
# If on anything other than the first iteration - Do nothing.
if kwargs["iteration"] > 0:
return None
room = create_object(rooms.Room, key="forest" + str(x) + str(y))
room.db.desc = "Basic forest room."
kwargs["caller"].msg(room.key + " " + room.dbref)
return room
def example2_build_verticle_exit(x, y, **kwargs):
'''Creates two exits to and from the two rooms north and south.'''
# If on the first iteration - Do nothing.
if kwargs["iteration"] == 0:
return
north_room = kwargs["room_dict"][(x, y - 1)]
south_room = kwargs["room_dict"][(x, y + 1)]
# create exits in the rooms
create_object(
exits.Exit, key="south", aliases=["s"], location=north_room, destination=south_room
)
create_object(
exits.Exit, key="north", aliases=["n"], location=south_room, destination=north_room
)
kwargs["caller"].msg("Connected: " + north_room.key + " & " + south_room.key)
def example2_build_horizontal_exit(x, y, **kwargs):
'''Creates two exits to and from the two rooms east and west.'''
# If on the first iteration - Do nothing.
if kwargs["iteration"] == 0:
return
west_room = kwargs["room_dict"][(x - 1, y)]
east_room = kwargs["room_dict"][(x + 1, y)]
create_object(exits.Exit, key="east", aliases=["e"], location=west_room, destination=east_room)
create_object(exits.Exit, key="west", aliases=["w"], location=east_room, destination=west_room)
kwargs["caller"].msg("Connected: " + west_room.key + " & " + east_room.key)
# Include your trigger characters and build functions in a legend dict.
EXAMPLE2_LEGEND = {
("♣", "♠"): example2_build_forest,
("|"): example2_build_verticle_exit,
("-"): example2_build_horizontal_exit,
}
```
----
<small>This document page is generated from `evennia/contrib/grid/mapbuilder/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,28 @@
# Menu-based login system
Contribution - Vincent-lg 2016, Griatch 2019 (rework for modern EvMenu)
This changes the Evennia login to ask for the account name and password in
sequence instead of requiring you to enter both at once. It uses EvMenu under
the hood.
## Installation
To install, add this to `mygame/server/conf/settings.py`:
CMDSET_UNLOGGEDIN = "evennia.contrib.base_systems.menu_login.UnloggedinCmdSet"
CONNECTION_SCREEN_MODULE = "contrib.base_systems.menu_login.connection_screens"
Reload the server and reconnect to see the changes.
## Notes
If you want to modify the way the connection screen looks, point
`CONNECTION_SCREEN_MODULE` to your own module. Use the default as a
guide (see also Evennia docs).
----
<small>This document page is generated from `evennia/contrib/base_systems/menu_login/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,23 @@
# TutorialMirror
A simple mirror object to experiment with.
A simple mirror object that
- echoes back the description of the object looking at it
- echoes back whatever is being sent to its .msg - to the
sender, if given, otherwise to the location of the mirror.
## Installation
Create the mirror with
create/drop mirror:contrib.tutorials.mirror.TutorialMirror
Then look at it.
----
<small>This document page is generated from `evennia/contrib/tutorials/mirror/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,30 @@
# Evennia Multidescer
Contrib - Griatch 2016
A "multidescer" is a concept from the MUSH world. It allows for
creating, managing and switching between multiple character
descriptions. This multidescer will not require any changes to the
Character class, rather it will use the `multidescs` Attribute (a
list) and create it if it does not exist.
This contrib also works well together with the rpsystem contrib (which
also adds the short descriptions and the `sdesc` command).
## Installation
Edit `mygame/commands/default_cmdsets.py` and add
`from evennia.contrib.game_systems.multidescer import CmdMultiDesc` to the top.
Next, look up the `at_cmdset_create` method of the `CharacterCmdSet`
class and add a line `self.add(CmdMultiDesc())` to the end
of it.
Reload the server and you should have the +desc command available (it
will replace the default `desc` command).
----
<small>This document page is generated from `evennia/contrib/game_systems/multidescer/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,48 @@
# Legacy Comms-commands
Contribution - Griatch 2021
In Evennia 1.0, the old Channel commands (originally inspired by MUX) were
replaced by the single `channel` command that performs all these function.
That command is still required to talk on channels. This contrib (extracted
from Evennia 0.9.5) reuses the channel-management of the base Channel command
but breaks out its functionality into separate Commands with MUX-familiar names.
- `allcom` - `channel/all` and `channel`
- `addcom` - `channel/alias`, `channel/sub` and `channel/unmute`
- `delcom` - `channel/unalias`, `alias/unsub` and `channel/mute`
- `cboot` - `channel/boot` (`channel/ban` and `/unban` not supported)
- `cwho` - `channel/who`
- `ccreate` - `channel/create`
- `cdestroy` - `channel/destroy`
- `clock` - `channel/lock`
- `cdesc` - `channel/desc`
## Installation
- Import the `CmdSetLegacyComms` cmdset from this module into `mygame/commands/default_cmdsets.py`
- Add it to the CharacterCmdSet's `at_cmdset_creation` method (see below).
- Reload the server.
```python
# in mygame/commands/default_cmdsets.py
# ..
from evennia.contrib.base_systems.mux_comms_cmds import CmdSetLegacyComms # <----
class CharacterCmdSet(default_cmds.CharacterCmdSet):
# ...
def at_cmdset_creation(self):
# ...
self.add(CmdSetLegacyComms) # <----
```
Note that you will still be able to use the `channel` command; this is actually
still used under the hood by these commands.
----
<small>This document page is generated from `evennia/contrib/base_systems/mux_comms_cmds/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -1,335 +1,625 @@
# Contrib modules
# Contribs
Contribs are found in [evennia/contrib/](evennia.contrib) and are optional game-specific code-snippets
or even full systems you can use for your game. They are contributed by the Evennia community and
released under the same license as Evennia itself. Each contrib has its own installation instructions.
Bugs are reported to the Evennia [issue tracker](github:issue) as usual.
_Contribs_ are optional code snippets and systems contributed by
the Evennia community. They vary in size and complexity and
may be more specific about game types and styles than 'core' Evennia.
This page is auto-generated and summarizes all contribs currently included.
## Character-related
All contrib categories are imported from `evennia.contrib`, such as
Contribs related to characters and character displays.
from evennia.contrib.base_systems import building_menu
### CharGen
Each contrib contains installation instructions for how to integrate it
with your other code. If you want to tweak the code of a contrib, just
copy its entire folder to your game directory and modify/use it from there.
*Griatch 2011*
If you want to contribute yourself, see [here](../Contributing.md)!
A simple Character creator for OOC mode. Meant as a starting point for a more fleshed-out system.
> Hint: Additional (potentially un-maintained) code snippets from the community can be found
in our discussion forum's [Community Contribs & Snippets](https://github.com/evennia/evennia/discussions/categories/community-contribs-snippets) category.
### Clothing
*FlutterSprite 2017*
A layered clothing system with slots for different types of garments auto-showing in description.
## base_systems
### Health Bar
_This category contains systems that are not necessarily tied to a specific
in-game mechanic but is useful for the game as a whole. Examples include
login systems, new command syntaxes, and build helpers._
*Tim Ashley Jenkins 2017*
Tool to create colorful bars/meters.
### Contrib: `awsstorage`
### Multidescer
Contrib by The Right Honourable Reverend (trhr) 2020
*Griatch 2016*
## What is this for?
Advanced descriptions combined from many separate description components, inspired by MUSH.
[Read the documentation](./Contrib-AWSStorage.md)
---
## Rooms, movement and grid
Contribs modifying locations, movement or helping to creating rooms.
### Contrib: `building_menu`
### XYZGrid
Module containing the building menu system.
*Griatch 2021*
Evennia contributor: vincent-lg 2018
Adds an XYZgrid to Evennia, with map-display and pathfinding. Created via map
strings and maintained outside of the game via Evennia launch commands.
[Read the documentation](./Contrib-Building-Menu.md)
- [XYZGrid documentation](./XYZGrid.md)
### Extended Room
*Griatch 2012*
### Contrib: `color_markups`
An expanded Room typeclass with multiple descriptions for time and season as well as details.
Contribution, Griatch 2017
### Map Builder
Additional color markup styles for Evennia (extending or replacing the default
`|r`, `|234` etc).
*CloudKeeper 2016*
[Read the documentation](./Contrib-Color-Markups.md)
Build a game area based on a 2D "graphical" unicode map. Supports asymmetric exits.
- [Static in-game map](./Static-In-Game-Map.md)
### Simple Door
### Contrib: `custom_gametime`
*Griatch 2014*
Contrib - Griatch 2017, vlgeoff 2017
Example of an exit that can be opened and closed from both sides.
This reimplements the `evennia.utils.gametime` module but supporting a custom
calendar for your game world. It allows for scheduling events to happen at given
in-game times, taking this custom calendar into account.
### Slow exit
[Read the documentation](./Contrib-Custom-Gametime.md)
*Griatch 2014*
Custom Exit class that takes different time to pass depending on if you are walking/running etc.
### Wilderness
### Contrib: `email_login`
*titeuf87 2017*
Evennia contrib - Griatch 2012
Make infinitely large wilderness areas with dynamically created locations.
This is a variant of the login system that requires an email-address
instead of a username to login.
- [Dynamic in-game map](./Dynamic-In-Game-Map.md)
[Read the documentation](./Contrib-Email-Login.md)
----
## Roleplaying and rules
Contribs supporting roleplay and in-game roleplaying actions.
### Contrib: `ingame_python`
### Barter system
Vincent Le Goff 2017
*Griatch 2012*
This contrib adds the system of in-game Python in Evennia, allowing immortals
(or other trusted builders) to dynamically add features to individual objects.
Using custom Python set in-game, every immortal or privileged users could have a
specific room, exit, character, object or something else behave differently from
its "cousins". For these familiar with the use of softcode in MU`*`, like SMAUG
MudProgs, the ability to add arbitrary behavior to individual objects is a step
toward freedom. Keep in mind, however, the warning below, and read it carefully
before the rest of the documentation.
A safe and effective barter-system for any game. Allows safe trading of any goods (including coin).
[Read the documentation](./Contrib-Ingame-Python.md)
### Crafting
*Griatch 2020*
A full, extendable crafting system.
### Contrib: `menu_login`
- [Crafting overview](./Crafting.md)
- [Crafting API documentation](evennia.contrib.crafting.crafting)
- [Example of a sword crafting tree](evennia.contrib.crafting.example_recipes)
Contribution - Vincent-lg 2016, Griatch 2019 (rework for modern EvMenu)
### Dice
This changes the Evennia login to ask for the account name and password in
sequence instead of requiring you to enter both at once. It uses EvMenu under
the hood.
*Griatch 2012*
[Read the documentation](./Contrib-Menu-Login.md)
A fully featured dice rolling system.
### Mail
*grungies1138 2016*
### Contrib: `mux_comms_cmds`
An in-game mail system for communication.
Contribution - Griatch 2021
### Puzzles
In Evennia 1.0, the old Channel commands (originally inspired by MUX) were
replaced by the single `channel` command that performs all these function.
That command is still required to talk on channels. This contrib (extracted
from Evennia 0.9.5) reuses the channel-management of the base Channel command
but breaks out its functionality into separate Commands with MUX-familiar names.
*Hendher 2019*
[Read the documentation](./Contrib-Mux-Comms-Cmds.md)
Combine objects to create new items, adventure-game style
### RP System
*Griatch 2015*
### Contrib: `unixcommand`
Full director-style emoting system replacing names with sdescs/recogs. Supports wearing masks.
Evennia contribution, Vincent Le Geoff 2017
### RP Language
This module contains a command class that allows for unix-style command syntax
in-game, using --options, positional arguments and stuff like -n 10 etc
similarly to a unix command. It might not the best syntax for the average player
but can be really useful for builders when they need to have a single command do
many things with many options. It uses the ArgumentParser from Python's standard
library under the hood.
*Griatch 2015*
[Read the documentation](./Contrib-Unixcommand.md)
Dynamic obfuscation of emotes when speaking unfamiliar languages. Also obfuscates whispers.
### Traits
*Whitenoise 2014, Griatch2021*
Powerful on-object properties (very extended Attributes) for representing
health, mana, skill-levels etc, with automatic min/max value, base, modifiers
and named tiers for different values. Also include timed rate increase/decrease
to have values change over a period of time.
## full_systems
### Turnbattle
_This category contains 'complete' game engines that can be used directly
to start creating content without no further additions (unless you want to)._
*FlutterSprite 2017*
A turn-based combat engine meant as a start to build from. Has attack/disengage and turn timeouts,
and includes optional expansions for equipment and combat movement, magic and ranged combat.
### Contrib: `evscaperoom`
----
Evennia contrib - Griatch 2019
## Building and server systems
This 'Evennia escaperoom game engine' was created for the MUD Coders Guild game
Jam, April 14-May 15 2019. The theme for the jam was "One Room". This contains the
utilities and base classes and an empty example room.
### Building menu
[Read the documentation](./Contrib-Evscaperoom.md)
*vincent-lg 2018*
An `@edit` command for modifying objects using a generated menu. Customizable for different games.
### Field Fill
*FlutterSprite 2018*
A simple system for creating an EvMenu that presents a player with a highly customizable fillable form
### In-Game-Python
## game_systems
*Vincent Le Geoff 2017*
_This category holds code implementing in-game gameplay systems like
crafting, mail, combat and more. Each system is meant to be adopted
piecemeal and adopted for your game. This does not include
roleplaying-specific systems, those are found in the `rpg` folder._
Allow Builders to add Python-scripted events to their objects (OBS-not for untrusted users!)
- [A voice-operated elevator using events](./A-voice-operated-elevator-using-events.md)
- [Dialogues using events](./Dialogues-in-events.md)
### Contrib: `barter`
### Menu-builder
Evennia contribution - Griatch 2012
A tool for building using an in-game menu instead of the normal build commands. Meant to
be expanded for the needs of your game.
This implements a full barter system - a way for players to safely
trade items between each other using code rather than simple free-form
talking. The advantage of this is increased buy/sell safety but it
also streamlines the process and makes it faster when doing many
transactions (since goods are automatically exchanged once both
agree).
- [Building Menus](./Building-menus.md)
[Read the documentation](./Contrib-Barter.md)
### Security/Auditing
*Johhny 2018*
Log server input/output for debug/security.
### Contrib: `clothing`
### Tree Select
Evennia contribution - Tim Ashley Jenkins 2017
*FlutterSprite 2017*
Provides a typeclass and commands for wearable clothing,
which is appended to a character's description when worn.
A simple system for creating a branching EvMenu with selection options sourced from a single
multi-line string.
[Read the documentation](./Contrib-Clothing.md)
---
## Snippets and config
Contribs meant to be used as part of other code, or as replacements for default settings.
### Contrib: `cooldowns`
### Color-markups
Evennia contrib - owllex, 2021
*Griatch, 2017*
This contrib provides a simple cooldown handler that can be attached to any
typeclassed Object or Account. A cooldown is a lightweight persistent
asynchronous timer that you can query to see if it is ready.
Alternative in-game color markups.
[Read the documentation](./Contrib-Cooldowns.md)
### Custom gametime
*Griatch, vlgeoff 2017*
Implements Evennia's gametime module but for custom game world-specific calendars.
### Contrib: `crafting`
### Logins
Contrib - Griatch 2020
#### Email login
This implements a full crafting system. The principle is that of a 'recipe':
*Griatch 2012*
[Read the documentation](./Contrib-Crafting.md)
A variant of the standard login system that requires an email to login rather then just name+password.
#### Menu login
*Griatch 2011, 2019, Vincent-lg 2016*
### Contrib: `gendersub`
A login system using menus asking for name/password rather than giving them as one command.
Contrib - Griatch 2015
### Random String Generator
This is a simple gender-aware Character class for allowing users to
insert custom markers in their text to indicate gender-aware
messaging. It relies on a modified msg() and is meant as an
inspiration and starting point to how to do stuff like this.
*Vincent Le Goff 2017*
[Read the documentation](./Contrib-Gendersub.md)
Simple pseudo-random generator of strings with rules, avoiding repetitions.
### UnixCommand
*Vincent Le Geoff 2017*
### Contrib: `mail`
Add commands with UNIX-style syntax.
Evennia Contribution - grungies1138 2016
----
A simple Brandymail style mail system that uses the Msg class from Evennia
Core. It has two Commands, both of which can be used on their own:
## Examples
[Read the documentation](./Contrib-Mail.md)
Contribs not meant to be used as-is, but just as examples to learn from.
### GenderSub
*Griatch 2015*
### Contrib: `multidescer`
Simple example (only) of storing gender on a character and access it in an emote with a custom marker.
Contrib - Griatch 2016
### Talking NPC
A "multidescer" is a concept from the MUSH world. It allows for
creating, managing and switching between multiple character
descriptions. This multidescer will not require any changes to the
Character class, rather it will use the `multidescs` Attribute (a
list) and create it if it does not exist.
*Griatch 2011*
[Read the documentation](./Contrib-Multidescer.md)
A talking NPC object that offers a menu-driven conversation tree.
### Tutorial examples
*Griatch 2011, 2015*
### Contrib: `puzzles`
A folder of basic example objects, commands and scripts.
Evennia contribution - Henddher 2018
### The tutorial-world
Provides a typeclass and commands for objects that can be combined (i.e. 'use'd)
to produce new objects.
*Griatch 2011, 2015*
[Read the documentation](./Contrib-Puzzles.md)
The Evennia single-player sole quest. Made to be analyzed to learn.
- [The tutorial world introduction](../Howto/Starting/Part1/Tutorial-World-Introduction.md)
----
### Contrib: `turnbattle`
## Full game systems
Contrib - Tim Ashley Jenkins 2017
Full game-dir replacement systems.
This is a framework for a simple turn-based combat system, similar
to those used in D&D-style tabletop role playing games. It allows
any character to start a fight in a room, at which point initiative
is rolled and a turn order is established. Each participant in combat
has a limited time to decide their action for that turn (30 seconds by
default), and combat progresses through the turn order, looping through
the participants until the fight ends.
### Ainneve
[Read the documentation](./Contrib-Turnbattle.md)
*Evennia community 2015-?*
This is a community attempt to make an Evennia 'example game' using good practices. It is also a good
place to jump in if you want to help in another project rather than run it alone. Development of this
has stalled a bit so we are looking for enthusiastic people to lead the charge.
- [evennia/ainneve repository](https://github.com/evennia/ainneve)
- [Original discussion thread](https://groups.google.com/g/evennia/c/48PMDirb7go/m/Z9EAuvXZn7UJ) (external link)
### Arxcode
*Tehom 2019*
Open source code release of the popular Evennia-based [Arx, after the reckoning](https://play.arxgame.org/).
This is a fantasy game with a focus on roleplay and code-supported political intrigue. This code-release
is maintained by Tehom in its own repository so bug reports should be directed there.
## grid
- [Arxcode repository on github](https://github.com/Arx-Game/arxcode)
- [Arxcode issue tracker](https://github.com/Arx-Game/arxcode/issues)
- [Arxcode installation help](./Arxcode-installing-help.md) - this may not always be fully up-to-date with
latest Evennia. Report your findings!
_Systems related to the game world's topology and structure. This has
contribs related to rooms, exits and map building._
### Evscaperoom
*Griatch 2019*
### Contrib: `extended_room`
Evennia Contribution - Griatch 2012, vincent-lg 2019
This is an extended Room typeclass for Evennia. It is supported
by an extended `Look` command and an extended `desc` command, also
in this module.
[Read the documentation](./Contrib-Extended-Room.md)
### Contrib: `mapbuilder`
Contribution - Cloud_Keeper 2016
Build a map from a 2D ASCII map.
[Read the documentation](./Contrib-Mapbuilder.md)
### Contrib: `simpledoor`
Contribution - Griatch 2016
A simple two-way exit that represents a door that can be opened and
closed. Can easily be expanded from to make it lockable, destroyable
etc. Note that the simpledoor is based on Evennia locks, so it will
not work for a superuser (which bypasses all locks) - the superuser
will always appear to be able to close/open the door over and over
without the locks stopping you. To use the door, use `@quell` or a
non-superuser account.
[Read the documentation](./Contrib-Simpledoor.md)
### Contrib: `slow_exit`
Contribution - Griatch 2014
This is an example of an Exit-type that delays its traversal. This simulates
slow movement, common in many different types of games. The contrib also
contains two commands, `CmdSetSpeed` and CmdStop for changing the movement speed
and abort an ongoing traversal, respectively.
[Read the documentation](./Contrib-Slow-Exit.md)
### Contrib: `wilderness`
Evennia contrib - titeuf87 2017
This contrib provides a wilderness map without actually creating a large number
of rooms - as you move, your room is instead updated with different
descriptions. This means you can make huge areas with little database use as
long as the rooms are relatively similar (name/desc changing).
[Read the documentation](./Contrib-Wilderness.md)
### Contrib: `xyzgrid`
Full grid coordinate- pathfinding and visualization system
Evennia Contrib by Griatch 2021
The default Evennia's rooms are non-euclidian - they can connect
to each other with any types of exits without necessarily having a clear
position relative to each other. This gives maximum flexibility, but many games
want to use cardinal movements (north, east etc) and also features like finding
the shortest-path between two points.
[Read the documentation](./Contrib-XYZGrid.md)
## rpg
_These are systems specifically related to roleplaying
and rule implementation like character traits, dice rolling and emoting._
### Contrib: `dice`
Rolls dice for roleplaying, in-game gambling or GM:ing
Evennia contribution - Griatch 2012
[Read the documentation](./Contrib-Dice.md)
### Contrib: `health_bar`
Contrib - Tim Ashley Jenkins 2017
The function provided in this module lets you easily display visual
bars or meters - "health bar" is merely the most obvious use for this,
though these bars are highly customizable and can be used for any sort
of appropriate data besides player health.
[Read the documentation](./Contrib-Health-Bar.md)
### Contrib: `rpsystem`
Roleplaying emotes/sdescs - Griatch, 2015
Language/whisper emotes - Griatch, 2015
## Roleplaying emotes
[Read the documentation](./Contrib-RPSystem.md)
### Contrib: `traits`
Whitenoise 2014, Ainneve contributors,
Griatch 2020
A `Trait` represents a modifiable property on (usually) a Character. They can
be used to represent everything from attributes (str, agi etc) to skills
(hunting 10, swords 14 etc) and dynamically changing things like HP, XP etc.
[Read the documentation](./Contrib-Traits.md)
## tutorials
_Helper resources specifically meant to teach a development concept or
to exemplify an Evennia system. Any extra resources tied to documentation
tutorials are found here. Also the home of the Tutorial World demo adventure._
### Contrib: `batchprocessor`
Contibution - Griatch 2012
The batch processor is used for generating in-game content from one or more
static files. Files can be stored with version control and then 'applied'
to the game to create content.
[Read the documentation](./Contrib-Batchprocessor.md)
### Contrib: `bodyfunctions`
Griatch - 2012
Example script for testing. This adds a simple timer that has your
character make observations and notices at irregular intervals.
[Read the documentation](./Contrib-Bodyfunctions.md)
### Contrib: `mirror`
A simple mirror object to experiment with.
A simple mirror object that
[Read the documentation](./Contrib-Mirror.md)
### Contrib: `red_button`
Griatch - 2011
This is a more advanced example object with its own functionality (commands)
on it.
[Read the documentation](./Contrib-Red-Button.md)
### Contrib: `talking_npc`
Contribution - Griatch 2011, grungies1138, 2016
This is a static NPC object capable of holding a simple menu-driven
conversation. It's just meant as an example.
[Read the documentation](./Contrib-Talking-Npc.md)
### Contrib: `tutorial_world`
Griatch 2011, 2015
This is a stand-alone tutorial area for an unmodified Evennia install.
Think of it as a sort of single-player adventure rather than a
full-fledged multi-player game world. The various rooms and objects
herein are designed to show off features of the engine, not to be a
very challenging (nor long) gaming experience. As such it's of course
only skimming the surface of what is possible.
[Read the documentation](./Contrib-Tutorial-World.md)
## utils
_Miscellaneous, optional tools for manipulating text, auditing connections
and more._
### Contrib: `auditing`
Contrib - Johnny 2017
This is a tap that optionally intercepts all data sent to/from clients and the
server and passes it to a callback of your choosing.
[Read the documentation](./Contrib-Auditing.md)
### Contrib: `fieldfill`
Contrib - Tim Ashley Jenkins 2018
This module contains a function that calls an easily customizable EvMenu - this
menu presents the player with a fillable form, with fields that can be filled
out in any order. Each field's value can be verified, with the function
allowing easy checks for text and integer input, minimum and maximum values /
character lengths, or can even be verified by a custom function. Once the form
is submitted, the form's data is submitted as a dictionary to any callable of
your choice.
[Read the documentation](./Contrib-Fieldfill.md)
### Contrib: `random_string_generator`
Contribution - Vincent Le Goff 2017
This contrib can be used to generate pseudo-random strings of information
with specific criteria. You could, for instance, use it to generate
phone numbers, license plate numbers, validation codes, non-sensivite
passwords and so on. The strings generated by the generator will be
stored and won't be available again in order to avoid repetition.
Here's a very simple example:
[Read the documentation](./Contrib-Random-String-Generator.md)
### Contrib: `tree_select`
Contrib - Tim Ashley Jenkins 2017
This module allows you to create and initialize an entire branching EvMenu
instance with nothing but a multi-line string passed to one function.
[Read the documentation](./Contrib-Tree-Select.md)
A full engine for making multiplayer 'escape-rooms' completely in code.
This is based on the 2019 MUD Game jam winner *Evscaperoom*.
- [contrib/evscaperoom](evennia.contrib.evscaperoom) - game engine to make your own escape rooms.
- [https://demo.evennia.com](https://demo.evennia.com) - a full installation of the original game can
be played by entering the *evscaperoom* exit in the first Limbo room.
- https://github.com/Griatch/evscaperoom - the original game's source code (warning for spoilers if you
want to solve the puzzles and mystery yourself).
```{toctree}
:hidden:
:depth: 2
./Crafting
../api/evennia.contrib.crafting.crafting
../api/evennia.contrib.crafting.example_recipes
./A-voice-operated-elevator-using-events
./Dialogues-in-events
./Dynamic-In-Game-Map
./Static-In-Game-Map
../Howto/Starting/Part1/Tutorial-World-Introduction
./Building-menus
Contribs/Contrib-AWSStorage.md
Contribs/Contrib-Building-Menu.md
Contribs/Contrib-Color-Markups.md
Contribs/Contrib-Custom-Gametime.md
Contribs/Contrib-Email-Login.md
Contribs/Contrib-Ingame-Python.md
Contribs/Contrib-Menu-Login.md
Contribs/Contrib-Mux-Comms-Cmds.md
Contribs/Contrib-Unixcommand.md
Contribs/Contrib-Evscaperoom.md
Contribs/Contrib-Barter.md
Contribs/Contrib-Clothing.md
Contribs/Contrib-Cooldowns.md
Contribs/Contrib-Crafting.md
Contribs/Contrib-Gendersub.md
Contribs/Contrib-Mail.md
Contribs/Contrib-Multidescer.md
Contribs/Contrib-Puzzles.md
Contribs/Contrib-Turnbattle.md
Contribs/Contrib-Extended-Room.md
Contribs/Contrib-Mapbuilder.md
Contribs/Contrib-Simpledoor.md
Contribs/Contrib-Slow-Exit.md
Contribs/Contrib-Wilderness.md
Contribs/Contrib-XYZGrid.md
Contribs/Contrib-Dice.md
Contribs/Contrib-Health-Bar.md
Contribs/Contrib-RPSystem.md
Contribs/Contrib-Traits.md
Contribs/Contrib-Batchprocessor.md
Contribs/Contrib-Bodyfunctions.md
Contribs/Contrib-Mirror.md
Contribs/Contrib-Red-Button.md
Contribs/Contrib-Talking-Npc.md
Contribs/Contrib-Tutorial-World.md
Contribs/Contrib-Auditing.md
Contribs/Contrib-Fieldfill.md
Contribs/Contrib-Random-String-Generator.md
Contribs/Contrib-Tree-Select.md
```
----
<small>This document page is auto-generated from the sources. Manual changes
will be overwritten.</small>

View file

@ -0,0 +1,74 @@
# Puzzles System
Evennia contribution - Henddher 2018
Provides a typeclass and commands for objects that can be combined (i.e. 'use'd)
to produce new objects.
A Puzzle is a recipe of what objects (aka parts) must be combined by a player so
a new set of objects (aka results) are automatically created.
## Installation
Add the PuzzleSystemCmdSet to all players (e.g. in their Character typeclass).
Alternatively:
py self.cmdset.add('evennia.contrib.game_systems.puzzles.PuzzleSystemCmdSet')
## Usage
Consider this simple Puzzle:
orange, mango, yogurt, blender = fruit smoothie
As a Builder:
create/drop orange
create/drop mango
create/drop yogurt
create/drop blender
create/drop fruit smoothie
puzzle smoothie, orange, mango, yogurt, blender = fruit smoothie
...
Puzzle smoothie(#1234) created successfuly.
destroy/force orange, mango, yogurt, blender, fruit smoothie
armpuzzle #1234
Part orange is spawned at ...
Part mango is spawned at ...
....
Puzzle smoothie(#1234) has been armed successfully
As Player:
use orange, mango, yogurt, blender
...
Genius, you blended all fruits to create a fruit smoothie!
## Details
Puzzles are created from existing objects. The given
objects are introspected to create prototypes for the
puzzle parts and results. These prototypes become the
puzzle recipe. (See PuzzleRecipe and `puzzle`
command). Once the recipe is created, all parts and result
can be disposed (i.e. destroyed).
At a later time, a Builder or a Script can arm the puzzle
and spawn all puzzle parts in their respective
locations (See armpuzzle).
A regular player can collect the puzzle parts and combine
them (See use command). If player has specified
all pieces, the puzzle is considered solved and all
its puzzle parts are destroyed while the puzzle results
are spawened on their corresponding location.
----
<small>This document page is generated from `evennia/contrib/game_systems/puzzles/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,263 @@
# Roleplaying base system for Evennia
Roleplaying emotes/sdescs - Griatch, 2015
Language/whisper emotes - Griatch, 2015
## Roleplaying emotes
This module contains the ContribRPObject, ContribRPRoom and
ContribRPCharacter typeclasses. If you inherit your
objects/rooms/character from these (or make them the defaults) from
these you will get the following features:
- Objects/Rooms will get the ability to have poses and will report
the poses of items inside them (the latter most useful for Rooms).
- Characters will get poses and also sdescs (short descriptions)
that will be used instead of their keys. They will gain commands
for managing recognition (custom sdesc-replacement), masking
themselves as well as an advanced free-form emote command.
In more detail, This RP base system introduces the following features
to a game, common to many RP-centric games:
- emote system using director stance emoting (names/sdescs).
This uses a customizable replacement noun (/me, @ etc) to
represent you in the emote. You can use /sdesc, /nick, /key or
/alias to reference objects in the room. You can use any
number of sdesc sub-parts to differentiate a local sdesc, or
use /1-sdesc etc to differentiate them. The emote also
identifies nested says and separates case.
- sdesc obscuration of real character names for use in emotes
and in any referencing such as object.search(). This relies
on an SdescHandler `sdesc` being set on the Character and
makes use of a custom Character.get_display_name hook. If
sdesc is not set, the character's `key` is used instead. This
is particularly used in the emoting system.
- recog system to assign your own nicknames to characters, can then
be used for referencing. The user may recog a user and assign
any personal nick to them. This will be shown in descriptions
and used to reference them. This is making use of the nick
functionality of Evennia.
- masks to hide your identity (using a simple lock).
- pose system to set room-persistent poses, visible in room
descriptions and when looking at the person/object. This is a
simple Attribute that modifies how the characters is viewed when
in a room as sdesc + pose.
- in-emote says, including seamless integration with language
obscuration routine (such as contrib/rplanguage.py)
### Installation:
Add `RPSystemCmdSet` from this module to your CharacterCmdSet:
```python
# mygame/commands/default_cmdsets.py
# ...
from evennia.contrib.rpg.rpsystem import RPSystemCmdSet <---
class CharacterCmdSet(default_cmds.CharacterCmdset):
# ...
def at_cmdset_creation(self):
# ...
self.add(RPSystemCmdSet()) # <---
```
You also need to make your Characters/Objects/Rooms inherit from
the typeclasses in this module:
```python
# in mygame/typeclasses/characters.py
from evennia.contrib.rpg import ContribRPCharacter
class Character(ContribRPCharacter):
# ...
```
```python
# in mygame/typeclasses/objects.py
from evennia.contrib.rpg import ContribRPObject
class Object(ContribRPObject):
# ...
```
```python
# in mygame/typeclasses/rooms.py
from evennia.contrib.rpg import ContribRPRoom
class Room(ContribRPRoom):
# ...
```
You will then need to reload the server and potentially force-reload
your objects, if you originally created them without this.
Example for your character:
> type/reset/force me = typeclasses.characters.Character
Examples:
> look
Tavern
The tavern is full of nice people
*A tall man* is standing by the bar.
Above is an example of a player with an sdesc "a tall man". It is also
an example of a static *pose*: The "standing by the bar" has been set
by the player of the tall man, so that people looking at him can tell
at a glance what is going on.
> emote /me looks at /Tall and says "Hello!"
I see:
Griatch looks at Tall man and says "Hello".
Tall man (assuming his name is Tom) sees:
The godlike figure looks at Tom and says "Hello".
Note that by default, the case of the tag matters, so `/tall` will
lead to 'tall man' while `/Tall` will become 'Tall man' and /TALL
becomes /TALL MAN. If you don't want this behavior, you can pass
case_sensitive=False to the `send_emote` function.
## Language and whisper obfuscation system
This module is intented to be used with an emoting system (such as
`contrib/rpg/rpsystem.py`). It offers the ability to obfuscate spoken words
in the game in various ways:
- Language: The language functionality defines a pseudo-language map
to any number of languages. The string will be obfuscated depending
on a scaling that (most likely) will be input as a weighted average of
the language skill of the speaker and listener.
- Whisper: The whisper functionality will gradually "fade out" a
whisper along as scale 0-1, where the fading is based on gradually
removing sections of the whisper that is (supposedly) easier to
overhear (for example "s" sounds tend to be audible even when no other
meaning can be determined).
### Installation
This module adds no new commands; embed it in your say/emote/whisper commands.
### Usage:
```python
from evennia.contrib import rplanguage
# need to be done once, here we create the "default" lang
rplanguage.add_language()
say = "This is me talking."
whisper = "This is me whispering.
print rplanguage.obfuscate_language(say, level=0.0)
<<< "This is me talking."
print rplanguage.obfuscate_language(say, level=0.5)
<<< "This is me byngyry."
print rplanguage.obfuscate_language(say, level=1.0)
<<< "Daly ly sy byngyry."
result = rplanguage.obfuscate_whisper(whisper, level=0.0)
<<< "This is me whispering"
result = rplanguage.obfuscate_whisper(whisper, level=0.2)
<<< "This is m- whisp-ring"
result = rplanguage.obfuscate_whisper(whisper, level=0.5)
<<< "---s -s -- ---s------"
result = rplanguage.obfuscate_whisper(whisper, level=0.7)
<<< "---- -- -- ----------"
result = rplanguage.obfuscate_whisper(whisper, level=1.0)
<<< "..."
```
To set up new languages, import and use the `add_language()`
helper method in this module. This allows you to customize the
"feel" of the semi-random language you are creating. Especially
the `word_length_variance` helps vary the length of translated
words compared to the original and can help change the "feel" for
the language you are creating. You can also add your own
dictionary and "fix" random words for a list of input words.
Below is an example of "elvish", using "rounder" vowels and sounds:
```python
# vowel/consonant grammar possibilities
grammar = ("v vv vvc vcc vvcc cvvc vccv vvccv vcvccv vcvcvcc vvccvvcc "
"vcvvccvvc cvcvvcvvcc vcvcvvccvcvv")
# all not in this group is considered a consonant
vowels = "eaoiuy"
# you need a representative of all of the minimal grammars here, so if a
# grammar v exists, there must be atleast one phoneme available with only
# one vowel in it
phonemes = ("oi oh ee ae aa eh ah ao aw ay er ey ow ia ih iy "
"oy ua uh uw y p b t d f v t dh s z sh zh ch jh k "
"ng g m n l r w")
# how much the translation varies in length compared to the original. 0 is
# smallest, higher values give ever bigger randomness (including removing
# short words entirely)
word_length_variance = 1
# if a proper noun (word starting with capitalized letter) should be
# translated or not. If not (default) it means e.g. names will remain
# unchanged across languages.
noun_translate = False
# all proper nouns (words starting with a capital letter not at the beginning
# of a sentence) can have either a postfix or -prefix added at all times
noun_postfix = "'la"
# words in dict will always be translated this way. The 'auto_translations'
# is instead a list or filename to file with words to use to help build a
# bigger dictionary by creating random translations of each word in the
# list *once* and saving the result for subsequent use.
manual_translations = {"the":"y'e", "we":"uyi", "she":"semi", "he":"emi",
"you": "do", 'me':'mi','i':'me', 'be':"hy'e", 'and':'y'}
rplanguage.add_language(key="elvish", phonemes=phonemes, grammar=grammar,
word_length_variance=word_length_variance,
noun_translate=noun_translate,
noun_postfix=noun_postfix, vowels=vowels,
manual_translations=manual_translations,
auto_translations="my_word_file.txt")
```
This will produce a decicively more "rounded" and "soft" language than the
default one. The few `manual_translations` also make sure to make it at least
look superficially "reasonable".
The `auto_translations` keyword is useful, this accepts either a
list or a path to a text-file (with one word per line). This listing
of words is used to 'fix' translations for those words according to the
grammatical rules. These translations are stored persistently as long as the
language exists.
This allows to quickly build a large corpus of translated words
that never change. This produces a language that seem moderately
consistent, since words like 'the' will always be translated to the same thing.
The disadvantage (or advantage, depending on your game) is that players can
end up learn what words mean even if their characters don't know the
langauge.
----
<small>This document page is generated from `evennia/contrib/rpg/rpsystem/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,58 @@
# Pseudo-random generator and registry
Contribution - Vincent Le Goff 2017
This contrib can be used to generate pseudo-random strings of information
with specific criteria. You could, for instance, use it to generate
phone numbers, license plate numbers, validation codes, non-sensivite
passwords and so on. The strings generated by the generator will be
stored and won't be available again in order to avoid repetition.
Here's a very simple example:
```python
from evennia.contrib.utils.random_string_generator import RandomStringGenerator
# Create a generator for phone numbers
phone_generator = RandomStringGenerator("phone number", r"555-[0-9]{3}-[0-9]{4}")
# Generate a phone number (555-XXX-XXXX with X as numbers)
number = phone_generator.get()
# `number` will contain something like: "555-981-2207"
# If you call `phone_generator.get`, it won't give the same anymore.phone_generator.all()
# Will return a list of all currently-used phone numbers
phone_generator.remove("555-981-2207")
# The number can be generated again
```
## Importing
1. Import the `RandomStringGenerator` class from the contrib.
2. Create an instance of this class taking two arguments:
- The name of the gemerator (like "phone number", "license plate"...).
- The regular expression representing the expected results.
3. Use the generator's `all`, `get` and `remove` methods as shown above.
To understand how to read and create regular expressions, you can refer to
[the documentation on the re module](https://docs.python.org/2/library/re.html).
Some examples of regular expressions you could use:
- `r"555-\d{3}-\d{4}"`: 555, a dash, 3 digits, another dash, 4 digits.
- `r"[0-9]{3}[A-Z][0-9]{3}"`: 3 digits, a capital letter, 3 digits.
- `r"[A-Za-z0-9]{8,15}"`: between 8 and 15 letters and digits.
- ...
Behind the scenes, a script is created to store the generated information
for a single generator. The `RandomStringGenerator` object will also
read the regular expression you give to it to see what information is
required (letters, digits, a more restricted class, simple characters...)...
More complex regular expressions (with branches for instance) might not be
available.
----
<small>This document page is generated from `evennia/contrib/utils/random_string_generator/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,40 @@
# Red Button example
Griatch - 2011
This is a more advanced example object with its own functionality (commands)
on it.
Create the button with
create/drop button:tutorials.red_button.RedButton
Note that you must drop the button before you can see its messages! It's
imperative that you press the red button. You know you want to.
Use `del button` to destroy/stop the button when you are done playing.
## Technical
The button's functionality is controlled by CmdSets that gets added and removed
depending on the 'state' the button is in.
- Lid-closed state: In this state the button is covered by a glass cover and
trying to 'push' it will fail. You can 'nudge', 'smash' or 'open' the lid.
- Lid-open state: In this state the lid is open but will close again after a
certain time. Using 'push' now will press the button and trigger the
Blind-state.
- Blind-state: In this mode you are blinded by a bright flash. This will affect
your normal commands like 'look' and help until the blindness wears off after
a certain time.
Timers are handled by persistent delays on the button. These are examples of
`evennia.utils.utils.delay` calls that wait a certain time before calling a
method - such as when closing the lid and un-blinding a character.
----
<small>This document page is generated from `evennia/contrib/tutorials/red_button/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,50 @@
# SimpleDoor
Contribution - Griatch 2016
A simple two-way exit that represents a door that can be opened and
closed. Can easily be expanded from to make it lockable, destroyable
etc. Note that the simpledoor is based on Evennia locks, so it will
not work for a superuser (which bypasses all locks) - the superuser
will always appear to be able to close/open the door over and over
without the locks stopping you. To use the door, use `@quell` or a
non-superuser account.
## Installation:
Import `SimpleDoorCmdSet` from this module into `mygame/commands/default_cmdsets`
and add it to your `CharacterCmdSet`:
```python
# in mygame/commands/default_cmdsets.py
from evennia.contrib.grid import simpledoor <---
class CharacterCmdSet(default_cmds.CharacterCmdSet):
# ...
def at_cmdset_creation(self):
# ...
self.add(simpledoor.SimpleDoorCmdSet)
```
## Usage:
To try it out, `dig` a new room and then use the (overloaded) `@open`
commmand to open a new doorway to it like this:
@open doorway:contrib.grid.simpledoor.SimpleDoor = otherroom
open doorway
close doorway
Note: This uses locks, so if you are a superuser you will not be blocked by
a locked door - `quell` yourself, if so. Normal users will find that they
cannot pass through either side of the door once it's closed from the other
side.
----
<small>This document page is generated from `evennia/contrib/grid/simpledoor/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,67 @@
# Slow Exit
Contribution - Griatch 2014
This is an example of an Exit-type that delays its traversal. This simulates
slow movement, common in many different types of games. The contrib also
contains two commands, `CmdSetSpeed` and CmdStop for changing the movement speed
and abort an ongoing traversal, respectively.
## Installation:
To try out an exit of this type, you could connect two existing rooms
using something like this:
@open north:contrib.grid.slow_exit.SlowExit = <destination>
To make this your new default exit, modify `mygame/typeclasses/exits.py`
to import this module and change the default `Exit` class to inherit
from `SlowExit` instead.
```
# in mygame/typeclasses/exits.py
from evennia.contrib.grid.slowexit import SlowExit
class Exit(SlowExit):
# ...
```
To get the ability to change your speed and abort your movement, import
```python
# in mygame/commands/default_cmdsets.py
from evennia.contrib.grid import slow_exit <---
class CharacterCmdSet(default_cmds.CharacterCmdSet):
# ...
def at_cmdset_creation(self):
# ...
self.add(slow_exit.SlowDoorCmdSet) <---
```
simply import and add CmdSetSpeed and CmdStop from this module to your
default cmdset (see tutorials on how to do this if you are unsure).
To try out an exit of this type, you could connect two existing rooms using
something like this:
@open north:contrib.grid.slow_exit.SlowExit = <destination>
## Notes:
This implementation is efficient but not persistent; so incomplete
movement will be lost in a server reload. This is acceptable for most
game types - to simulate longer travel times (more than the couple of
seconds assumed here), a more persistent variant using Scripts or the
TickerHandler might be better.
----
<small>This document page is generated from `evennia/contrib/grid/slow_exit/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,27 @@
# Talkative NPC example
Contribution - Griatch 2011, grungies1138, 2016
This is a static NPC object capable of holding a simple menu-driven
conversation. It's just meant as an example.
## Installation
Create the NPC by creating an object of typeclass `contrib.tutorials.talking_npc.TalkingNPC`,
For example:
create/drop John : contrib.tutorials.talking_npc.TalkingNPC
Use `talk` in the same room as the NPC to start a conversation.
If there are many talkative npcs in the same room you will get to choose which
one's talk command to call (Evennia handles this automatically).
This use of EvMenu is very simplistic; See EvMenu for a lot more complex
possibilities.
----
<small>This document page is generated from `evennia/contrib/tutorials/talking_npc/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,449 @@
# Traits
Whitenoise 2014, Ainneve contributors,
Griatch 2020
A `Trait` represents a modifiable property on (usually) a Character. They can
be used to represent everything from attributes (str, agi etc) to skills
(hunting 10, swords 14 etc) and dynamically changing things like HP, XP etc.
Traits differ from normal Attributes in that they track their changes and limit
themselves to particular value-ranges. One can add/subtract from them easily and
they can even change dynamically at a particular rate (like you being poisoned or
healed).
Traits use Evennia Attributes under the hood, making them persistent (they survive
a server reload/reboot).
## Installation
Traits are always added to a typeclass, such as the Character class.
There are two ways to set up Traits on a typeclass. The first sets up the `TraitHandler`
as a property `.traits` on your class and you then access traits as e.g. `.traits.strength`.
The other alternative uses a `TraitProperty`, which makes the trait available directly
as e.g. `.strength`. This solution also uses the `TraitHandler`, but you don't need to
define it explicitly. You can combine both styles if you like.
### Traits with TraitHandler
Here's an example for adding the TraitHandler to the Character class:
```python
# mygame/typeclasses/objects.py
from evennia import DefaultCharacter
from evennia.utils import lazy_property
from evennia.contrib.rpg.traits import TraitHandler
# ...
class Character(DefaultCharacter):
...
@lazy_property
def traits(self):
# this adds the handler as .traits
return TraitHandler(self)
def at_object_creation(self):
# (or wherever you want)
self.traits.add("str", "Strength", trait_type="static", base=10, mod=2)
self.traits.add("hp", "Health", trait_type="gauge", min=0, max=100)
self.traits.add("hunting", "Hunting Skill", trait_type="counter",
base=10, mod=1, min=0, max=100)
```
When adding the trait, you supply the name of the property (`hunting`) along
with a more human-friendly name ("Hunting Skill"). The latter will show if you
print the trait etc. The `trait_type` is important, this specifies which type
of trait this is (see below).
### TraitProperties
Using `TraitProperties` makes the trait available directly on the class, much like Django model
fields. The drawback is that you must make sure that the name of your Traits don't collide with any
other properties/methods on your class.
```python
# mygame/typeclasses/objects.py
from evennia import DefaultObject
from evennia.utils import lazy_property
from evennia.contrib.rpg.traits import TraitProperty
# ...
class Object(DefaultObject):
...
strength = TraitProperty("Strength", trait_type="static", base=10, mod=2)
health = TraitProperty("Health", trait_type="gauge", min=0, base=100, mod=2)
hunting = TraitProperty("Hunting Skill", trait_type="counter", base=10, mod=1, min=0, max=100)
```
> Note that the property-name will become the name of the trait and you don't supply `trait_key`
> separately.
> The `.traits` TraitHandler will still be created (it's used under the
> hood. But it will only be created when the TraitProperty has been accessed at least once,
> so be careful if mixing the two styles. If you want to make sure `.traits` is always available,
> add the `TraitHandler` manually like shown earlier - the `TraitProperty` will by default use
> the same handler (`.traits`).
## Using traits
A trait is added to the traithandler (if you use `TraitProperty` the handler is just created under
the hood) after which one can access it as a property on the handler (similarly to how you can do
.db.attrname for Attributes in Evennia).
All traits have a _read-only_ field `.value`. This is only used to read out results, you never
manipulate it directly (if you try, it will just remain unchanged). The `.value` is calculated based
on combining fields, like `.base` and `.mod` - which fields are available and how they relate to
each other depends on the trait type.
```python
> obj.traits.strength.value
12 # base + mod
> obj.traits.strength.base += 5
obj.traits.strength.value
17
> obj.traits.hp.value
102 # base + mod
> obj.traits.hp.base -= 200
> obj.traits.hp.value
0 # min of 0
> obj.traits.hp.reset()
> obj.traits.hp.value
100
# you can also access properties like a dict
> obj.traits.hp["value"]
100
# you can store arbitrary data persistently for easy reference
> obj.traits.hp.effect = "poisoned!"
> obj.traits.hp.effect
"poisoned!"
# with TraitProperties:
> obj.hunting.value
12
> obj.strength.value += 5
> obj.strength.value
17
```
## Trait types
All default traits have a read-only `.value` property that shows the relevant or
'current' value of the trait. Exactly what this means depends on the type of trait.
Traits can also be combined to do arithmetic with their .value, if both have a
compatible type.
```python
> trait1 + trait2
54
> trait1.value
3
> trait1 + 2
> trait1.value
5
```
Two numerical traits can also be compared (bigger-than etc), which is useful in
all sorts of rule-resolution.
```python
if trait1 > trait2:
# do stuff
```
## Static trait
`value = base + mod`
The static trait has a `base` value and an optional `mod`-ifier. A typical use
of a static trait would be a Strength stat or Skill value. That is, something
that varies slowly or not at all, and which may be modified in-place.
```python
> obj.traits.add("str", "Strength", trait_type="static", base=10, mod=2)
> obj.traits.mytrait.value
12 # base + mod
> obj.traits.mytrait.base += 2
> obj.traits.mytrait.mod += 1
> obj.traits.mytrait.value
15
> obj.traits.mytrait.mod = 0
> obj.traits.mytrait.value
12
```
### Counter
min/unset base base+mod max/unset
|--------------|--------|---------X--------X------------|
current value
= current
+ mod
A counter describes a value that can move from a base. The `.current` property
is the thing usually modified. It starts at the `.base`. One can also add a
modifier, which will both be added to the base and to current (forming
`.value`). The min/max of the range are optional, a boundary set to None will
remove it. A suggested use for a Counter Trait would be to track skill values.
```python
> obj.traits.add("hunting", "Hunting Skill", trait_type="counter",
base=10, mod=1, min=0, max=100)
> obj.traits.hunting.value
11 # current starts at base + mod
> obj.traits.hunting.current += 10
> obj.traits.hunting.value
21
# reset back to base+mod by deleting current
> del obj.traits.hunting.current
> obj.traits.hunting.value
11
> obj.traits.hunting.max = None # removing upper bound
# for TraitProperties, pass the args/kwargs of traits.add() to the
# TraitProperty constructor instead.
```
Counters have some extra properties:
#### .descs
The `descs` property is a dict `{upper_bound:text_description}`. This allows for easily
storing a more human-friendly description of the current value in the
interval. Here is an example for skill values between 0 and 10:
{0: "unskilled", 1: "neophyte", 5: "trained", 7: "expert", 9: "master"}
The keys must be supplied from smallest to largest. Any values below the lowest and above the
highest description will be considered to be included in the closest description slot.
By calling `.desc()` on the Counter, you will get the text matching the current `value`.
```python
# (could also have passed descs= to traits.add())
> obj.traits.hunting.descs = {
0: "unskilled", 10: "neophyte", 50: "trained", 70: "expert", 90: "master"}
> obj.traits.hunting.value
11
> obj.traits.hunting.desc()
"neophyte"
> obj.traits.hunting.current += 60
> obj.traits.hunting.value
71
> obj.traits.hunting.desc()
"expert"
```
#### .rate
The `rate` property defaults to 0. If set to a value different from 0, it
allows the trait to change value dynamically. This could be used for example
for an attribute that was temporarily lowered but will gradually (or abruptly)
recover after a certain time. The rate is given as change of the current
`.value` per-second, and this will still be restrained by min/max boundaries,
if those are set.
It is also possible to set a `.ratetarget`, for the auto-change to stop at
(rather than at the min/max boundaries). This allows the value to return to
a previous value.
```python
> obj.traits.hunting.value
71
> obj.traits.hunting.ratetarget = 71
# debuff hunting for some reason
> obj.traits.hunting.current -= 30
> obj.traits.hunting.value
41
> obj.traits.hunting.rate = 1 # 1/s increase
# Waiting 5s
> obj.traits.hunting.value
46
# Waiting 8s
> obj.traits.hunting.value
54
# Waiting 100s
> obj.traits.hunting.value
71 # we have stopped at the ratetarget
> obj.traits.hunting.rate = 0 # disable auto-change
```
Note that when retrieving the `current`, the result will always be of the same
type as the `.base` even `rate` is a non-integer value. So if `base` is an `int`
(default)`, the `current` value will also be rounded the closest full integer.
If you want to see the exact `current` value, set `base` to a float - you
will then need to use `round()` yourself on the result if you want integers.
#### .percent()
If both min and max are defined, the `.percent()` method of the trait will
return the value as a percentage.
```python
> obj.traits.hunting.percent()
"71.0%"
> obj.traits.hunting.percent(formatting=None)
71.0
```
### Gauge
This emulates a [fuel-] gauge that empties from a base+mod value.
min/0 max=base+mod
|-----------------------X---------------------------|
value
= current
The `.current` value will start from a full gauge. The .max property is
read-only and is set by `.base` + `.mod`. So contrary to a `Counter`, the
`.mod` modifier only applies to the max value of the gauge and not the current
value. The minimum bound defaults to 0 if not set explicitly.
This trait is useful for showing commonly depletable resources like health,
stamina and the like.
```python
> obj.traits.add("hp", "Health", trait_type="gauge", base=100)
> obj.traits.hp.value # (or .current)
100
> obj.traits.hp.mod = 10
> obj.traits.hp.value
110
> obj.traits.hp.current -= 30
> obj.traits.hp.value
80
```
The Gauge trait is subclass of the Counter, so you have access to the same
methods and properties where they make sense. So gauges can also have a
`.descs` dict to describe the intervals in text, and can use `.percent()` to
get how filled it is as a percentage etc.
The `.rate` is particularly relevant for gauges - useful for everything
from poison slowly draining your health, to resting gradually increasing it.
### Trait
A single value of any type.
This is the 'base' Trait, meant to inherit from if you want to invent
trait-types from scratch (most of the time you'll probably inherit from some of
the more advanced trait-type classes though).
Unlike other Trait-types, the single `.value` property of the base `Trait` can
be editied. The value can hold any data that can be stored in an Attribute. If
it's an integer/float you can do arithmetic with it, but otherwise this acts just
like a glorified Attribute.
```python
> obj.traits.add("mytrait", "My Trait", trait_type="trait", value=30)
> obj.traits.mytrait.value
30
> obj.traits.mytrait.value = "stringvalue"
> obj.traits.mytrait.value
"stringvalue"
```
## Expanding with your own Traits
A Trait is a class inhering from `evennia.contrib.rpg.traits.Trait` (or from one of
the existing Trait classes).
```python
# in a file, say, 'mygame/world/traits.py'
from evennia.contrib.rpg.traits import StaticTrait
class RageTrait(StaticTrait):
trait_type = "rage"
default_keys = {
"rage": 0
}
def berserk(self):
self.mod = 100
def sedate(self):
self.mod = 0
```
Above is an example custom-trait-class "rage" that stores a property "rage" on
itself, with a default value of 0. This has all the functionality of a Trait -
for example, if you do del on the `rage` property, it will be set back to its
default (0). Above we also added some helper methods.
To add your custom RageTrait to Evennia, add the following to your settings file
(assuming your class is in mygame/world/traits.py):
TRAIT_CLASS_PATHS = ["world.traits.RageTrait"]
Reload the server and you should now be able to use your trait:
```python
> obj.traits.add("mood", "A dark mood", rage=30, trait_type='rage')
> obj.traits.mood.rage
30
# as TraitProperty
class Character(DefaultCharacter):
rage = TraitProperty("A dark mood", rage=30, trait_type='rage')
```
----
<small>This document page is generated from `evennia/contrib/rpg/traits/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,167 @@
# Easy menu selection tree
Contrib - Tim Ashley Jenkins 2017
This module allows you to create and initialize an entire branching EvMenu
instance with nothing but a multi-line string passed to one function.
EvMenu is incredibly powerful and flexible, but using it for simple menus
can often be fairly cumbersome - a simple menu that can branch into five
categories would require six nodes, each with options represented as a list
of dictionaries.
This module provides a function, `init_tree_selection`, which acts as a frontend
for EvMenu, dynamically sourcing the options from a multi-line string you
provide. For example, if you define a string as such:
TEST_MENU = '''Foo
Bar
Baz
Qux'''
And then use `TEST_MENU` as the 'treestr' source when you call
`init_tree_selection` on a player:
init_tree_selection(TEST_MENU, caller, callback)
The player will be presented with an EvMenu, like so:
___________________________
Make your selection:
___________________________
Foo
Bar
Baz
Qux
Making a selection will pass the selection's key to the specified callback as a
string along with the caller, as well as the index of the selection (the line
number on the source string) along with the source string for the tree itself.
In addition to specifying selections on the menu, you can also specify
categories. Categories are indicated by putting options below it preceded with
a '-' character. If a selection is a category, then choosing it will bring up a
new menu node, prompting the player to select between those options, or to go
back to the previous menu. In addition, categories are marked by default with a
'[+]' at the end of their key. Both this marker and the option to go back can be
disabled.
Categories can be nested in other categories as well - just go another '-'
deeper. You can do this as many times as you like. There's no hard limit to the
number of categories you can go down.
For example, let's add some more options to our menu, turning 'Bar' into a
category.
TEST_MENU = '''Foo
Bar
-You've got to know
--When to hold em
--When to fold em
--When to walk away
Baz
Qux'''
Now when we call the menu, we can see that 'Bar' has become a category instead of a
selectable option.
_______________________________
Make your selection:
_______________________________
Foo
Bar [+]
Baz
Qux
Note the [+] next to 'Bar'. If we select 'Bar', it'll show us the option listed
under it.
________________________________________________________________
Bar
________________________________________________________________
You've got to know [+]
<< Go Back: Return to the previous menu.
Just the one option, which is a category itself, and the option to go back,
which will take us back to the previous menu. Let's select 'You've got to know'.
________________________________________________________________
You've got to know
________________________________________________________________
When to hold em
When to fold em
When to walk away
<< Go Back: Return to the previous menu.
Now we see the three options listed under it, too. We can select one of them or
use 'Go Back' to return to the 'Bar' menu we were just at before. It's very
simple to make a branching tree of selections!
One last thing - you can set the descriptions for the various options simply by
adding a ':' character followed by the description to the option's line. For
example, let's add a description to 'Baz' in our menu:
TEST_MENU = '''Foo
Bar
-You've got to know
--When to hold em
--When to fold em
--When to walk away
Baz: Look at this one: the best option.
Qux'''
Now we see that the Baz option has a description attached that's separate from its key:
_______________________________________________________________
Make your selection:
_______________________________________________________________
Foo
Bar [+]
Baz: Look at this one: the best option.
Qux
Once the player makes a selection - let's say, 'Foo' - the menu will terminate
and call your specified callback with the selection, like so:
callback(caller, TEST_MENU, 0, "Foo")
The index of the selection is given along with a string containing the
selection's key. That way, if you have two selections in the menu with the same
key, you can still differentiate between them.
And that's all there is to it! For simple branching-tree selections, using this
system is much easier than manually creating EvMenu nodes. It also makes
generating menus with dynamic options much easier - since the source of the menu
tree is just a string, you could easily generate that string procedurally before
passing it to the `init_tree_selection` function. For example, if a player casts
a spell or does an attack without specifying a target, instead of giving them an
error, you could present them with a list of valid targets to select by
generating a multi-line string of targets and passing it to
`init_tree_selection`, with the callable performing the maneuver once a
selection is made.
This selection system only works for simple branching trees - doing anything
really complicated like jumping between categories or prompting for arbitrary
input would still require a full EvMenu implementation. For simple selections,
however, I'm sure you will find using this function to be much easier!
Included in this module is a sample menu and function which will let a player
change the color of their name - feel free to mess with it to get a feel for how
this system works by importing this module in your game's `default_cmdsets.py`
module and adding `CmdNameColor` to your default character's command set.
----
<small>This document page is generated from `evennia/contrib/utils/tree_select/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,61 @@
# Turn based battle system framework
Contrib - Tim Ashley Jenkins 2017
This is a framework for a simple turn-based combat system, similar
to those used in D&D-style tabletop role playing games. It allows
any character to start a fight in a room, at which point initiative
is rolled and a turn order is established. Each participant in combat
has a limited time to decide their action for that turn (30 seconds by
default), and combat progresses through the turn order, looping through
the participants until the fight ends.
This folder contains multiple examples of how such a system can be
implemented and customized:
tb_basic.py - The simplest system, which implements initiative and turn
order, attack rolls against defense values, and damage to hit
points. Only very basic game mechanics are included.
tb_equip.py - Adds weapons and armor to the basic implementation of
the battle system, including commands for wielding weapons and
donning armor, and modifiers to accuracy and damage based on
currently used equipment.
tb_items.py - Adds usable items and conditions/status effects, and gives
a lot of examples for each. Items can perform nearly any sort of
function, including healing, adding or curing conditions, or
being used to attack. Conditions affect a fighter's attributes
and options in combat and persist outside of fights, counting
down per turn in combat and in real time outside combat.
tb_magic.py - Adds a spellcasting system, allowing characters to cast
spells with a variety of effects by spending MP. Spells are
linked to functions, and as such can perform any sort of action
the developer can imagine - spells for attacking, healing and
conjuring objects are included as examples.
tb_range.py - Adds a system for abstract positioning and movement, which
tracks the distance between different characters and objects in
combat, as well as differentiates between melee and ranged
attacks.
This system is meant as a basic framework to start from, and is modeled
after the combat systems of popular tabletop role playing games rather than
the real-time battle systems that many MMOs and some MUDs use. As such, it
may be better suited to role-playing or more story-oriented games, or games
meant to closely emulate the experience of playing a tabletop RPG.
Each of these modules contains the full functionality of the battle system
with different customizations added in - the instructions to install each
one is contained in the module itself. It's recommended that you install
and test `tb_basic` first, so you can better understand how the other
modules expand on it and get a better idea of how you can customize the
system to your liking and integrate the subsystems presented here into
your own combat system.
----
<small>This document page is generated from `evennia/contrib/game_systems/turnbattle/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,113 @@
# Evennia Tutorial World
Griatch 2011, 2015
This is a stand-alone tutorial area for an unmodified Evennia install.
Think of it as a sort of single-player adventure rather than a
full-fledged multi-player game world. The various rooms and objects
herein are designed to show off features of the engine, not to be a
very challenging (nor long) gaming experience. As such it's of course
only skimming the surface of what is possible.
The tutorial world also includes a game tutor menu example, exemplifying
Evmenu.
## Installation
Log in as superuser (#1), then run
batchcommand tutorials.tutorial_world.build
Wait a little while for building to complete and don't run the command
again even if it's slow. This builds the world and connect it to Limbo
and creates a new exit `tutorial`.
If you are a superuser (User `#1`), use the `quell` command to play
the tutorial as intended.
## Comments
The tutorial world is intended to be explored and analyzed. It will help you
learn how to accomplish some more advanced effects and might give some good
ideas along the way.
It's suggested you play it through (as a normal user, NOT as Superuser!) and
explore it a bit, then come back here and start looking into the (heavily
documented) build/source code to find out how things tick - that's the
"tutorial" in Tutorial world after all.
Please report bugs in the tutorial to the Evennia issue tracker.
**Spoilers below - don't read on unless you already played the
tutorial game**
## Tutorial World Room map
?
|
+---+----+ +-------------------+ +--------+ +--------+
| | | | |gate | |corner |
| cliff +----+ bridge +----+ +---+ |
| | | | | | | |
+---+---\+ +---------------+---+ +---+----+ +---+----+
| \ | | castle |
| \ +--------+ +----+---+ +---+----+ +---+----+
| \ |under- | |ledge | |along | |court- |
| \|ground +--+ | |wall +---+yard |
| \ | | | | | | |
| +------\-+ +--------+ +--------+ +---+----+
| \ |
++---------+ \ +--------+ +--------+ +---+----+
|intro | \ |cell | |trap | |temple |
o--+ | \| +----+ | | |
L | | \ | /| | | |
I +----+-----+ +--------+ / ---+-+-+-+ +---+----+
M | / | | | |
B +----+-----+ +--------+/ +--+-+-+---------+----+
O |outro | |tomb | |antechamber |
o--+ +----------+ | | |
| | | | | |
+----------+ +--------+ +---------------------+
## Hints/Notes:
* o-- connections to/from Limbo
* intro/outro areas are rooms that automatically sets/cleans the
Character of any settings assigned to it during the
tutorial game.
* The Cliff is a good place to get an overview of the surroundings.
* The Bridge may seem like a big room, but it is really only one room
with custom move commands to make it take longer to cross. You can
also fall off the bridge if you are unlucky or take your time to
take in the view too long.
* In the Castle areas an aggressive mob is patrolling. It implements
rudimentary AI but packs quite a punch unless you have
found yourself a weapon that can harm it. Combat is only
possible once you find a weapon.
* The Antechamber features a puzzle for finding the correct Grave
chamber.
* The Cell is your reward if you fail in various ways. Finding a
way out of it is a small puzzle of its own.
* The Tomb is a nice place to find a weapon that can hurt the
castle guardian. This is the goal of the tutorial.
Explore on, or take the exit to finish the tutorial.
* ? - look into the code if you cannot find this bonus area!
----
<small>This document page is generated from `evennia/contrib/tutorials/tutorial_world/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,71 @@
# Unix-like Command style parent
Evennia contribution, Vincent Le Geoff 2017
This module contains a command class that allows for unix-style command syntax
in-game, using --options, positional arguments and stuff like -n 10 etc
similarly to a unix command. It might not the best syntax for the average player
but can be really useful for builders when they need to have a single command do
many things with many options. It uses the ArgumentParser from Python's standard
library under the hood.
## Installation
To use, inherit `UnixCommand` from this module from your own commands. You need
to override two methods:
- The `init_parser` method, which adds options to the parser. Note that you
should normally *not* override the normal `parse` method when inheriting from
`UnixCommand`.
- The `func` method, called to execute the command once parsed (like any Command).
Here's a short example:
```python
from evennia.contrib.base_systems.unixcommand import UnixCommand
class CmdPlant(UnixCommand):
'''
Plant a tree or plant.
This command is used to plant something in the room you are in.
Examples:
plant orange -a 8
plant strawberry --hidden
plant potato --hidden --age 5
'''
key = "plant"
def init_parser(self):
"Add the arguments to the parser."
# 'self.parser' inherits `argparse.ArgumentParser`
self.parser.add_argument("key",
help="the key of the plant to be planted here")
self.parser.add_argument("-a", "--age", type=int,
default=1, help="the age of the plant to be planted")
self.parser.add_argument("--hidden", action="store_true",
help="should the newly-planted plant be hidden to players?")
def func(self):
"func is called only if the parser succeeded."
# 'self.opts' contains the parsed options
key = self.opts.key
age = self.opts.age
hidden = self.opts.hidden
self.msg("Going to plant '{}', age={}, hidden={}.".format(
key, age, hidden))
```
To see the full power of argparse and the types of supported options, visit
[the documentation of argparse](https://docs.python.org/2/library/argparse.html).
----
<small>This document page is generated from `evennia/contrib/base_systems/unixcommand/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,119 @@
# Wilderness system
Evennia contrib - titeuf87 2017
This contrib provides a wilderness map without actually creating a large number
of rooms - as you move, your room is instead updated with different
descriptions. This means you can make huge areas with little database use as
long as the rooms are relatively similar (name/desc changing).
## Installation
This contrib does not provide any new commands. Instead the default `py` command
is used to call functions/classes in this contrib directly.
## Usage
A wilderness map needs to created first. There can be different maps, all
with their own name. If no name is provided, then a default one is used. Internally,
the wilderness is stored as a Script with the name you specify. If you don't
specify the name, a script named "default" will be created and used.
@py from evennia.contrib.grid import wilderness; wilderness.create_wilderness()
Once created, it is possible to move into that wilderness map:
@py from evennia.contrib.grid import wilderness; wilderness.enter_wilderness(me)
All coordinates used by the wilderness map are in the format of `(x, y)`
tuples. x goes from left to right and y goes from bottom to top. So `(0, 0)`
is the bottom left corner of the map.
## Customisation
The defaults, while useable, are meant to be customised. When creating a
new wilderness map it is possible to give a "map provider": this is a
python object that is smart enough to create the map.
The default provider, `WildernessMapProvider`, just creates a grid area that
is unlimited in size.
This `WildernessMapProvider` can be subclassed to create more interesting
maps and also to customize the room/exit typeclass used.
There is also no command that allows players to enter the wilderness. This
still needs to be added: it can be a command or an exit, depending on your
needs.
## Example
To give an example of how to customize, we will create a very simple (and
small) wilderness map that is shaped like a pyramid. The map will be
provided as a string: a "." symbol is a location we can walk on.
Let's create a file `world/pyramid.py`:
```python
# mygame/world/pyramid.py
map_str = '''
.
...
.....
.......
'''
from evennia.contrib.grid import wilderness
class PyramidMapProvider(wilderness.WildernessMapProvider):
def is_valid_coordinates(self, wilderness, coordinates):
"Validates if these coordinates are inside the map"
x, y = coordinates
try:
lines = map_str.split("\n")
# The reverse is needed because otherwise the pyramid will be
# upside down
lines.reverse()
line = lines[y]
column = line[x]
return column == "."
except IndexError:
return False
def get_location_name(self, coordinates):
"Set the location name"
x, y = coordinates
if y == 3:
return "Atop the pyramid."
else:
return "Inside a pyramid."
def at_prepare_room(self, coordinates, caller, room):
"Any other changes done to the room before showing it"
x, y = coordinates
desc = "This is a room in the pyramid."
if y == 3 :
desc = "You can see far and wide from the top of the pyramid."
room.db.desc = desc
```
Now we can use our new pyramid-shaped wilderness map. From inside Evennia we
create a new wilderness (with the name "default") but using our new map provider:
py from world import pyramid as p; p.wilderness.create_wilderness(mapprovider=p.PyramidMapProvider())
py from evennia.contrib import wilderness; wilderness.enter_wilderness(me, coordinates=(4, 1))
## Implementation details
When a character moves into the wilderness, they get their own room. If they
move, instead of moving the character, the room changes to match the new
coordinates. If a character meets another character in the wilderness, then
their room merges. When one of the character leaves again, they each get their
own separate rooms. Rooms are created as needed. Unneeded rooms are stored away
to avoid the overhead cost of creating new rooms again in the future.
----
<small>This document page is generated from `evennia/contrib/grid/wilderness/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -0,0 +1,72 @@
# XYZgrid
Full grid coordinate- pathfinding and visualization system
Evennia Contrib by Griatch 2021
The default Evennia's rooms are non-euclidian - they can connect
to each other with any types of exits without necessarily having a clear
position relative to each other. This gives maximum flexibility, but many games
want to use cardinal movements (north, east etc) and also features like finding
the shortest-path between two points.
This contrib forces each room to exist on a 3-dimensional XYZ grid and also
implements very efficient pathfinding along with tools for displaying
your current visual-range and a lot of related features.
The rooms of the grid are entirely controlled from outside the game, using
python modules with strings and dicts defining the map(s) of the game. It's
possible to combine grid- with non-grid rooms, and you can decorate
grid rooms as much as you like in-game, but you cannot spawn new grid
rooms without editing the map files outside of the game.
The full docs are found as
[Contribs/XYZGrid](https://evennia.com/docs/latest/Contributions/XYZGrid.html)
in the docs.
## Installation
1. If you haven't before, install the extra contrib requirements.
You can do so by doing `pip install -r requirements_extra.txt` from the
`evennia/` folder.
2. Import and add the `evennia.contrib.grid.xyzgrid.commands.XYZGridCmdSet` to the
`CharacterCmdset` cmdset in `mygame/commands.default_cmds.py`. Reload
the server. This makes the `map`, `goto/path` and modified `teleport` and
`open` commands available in-game.
3. Edit `mygame/server/conf/settings.py` and set
EXTRA_LAUNCHER_COMMANDS['xyzgrid'] = 'evennia.contrib.grid.xyzgrid.launchcmd.xyzcommand'
4. Run the new `evennia xyzgrid help` for instructions on how to spawn the grid.
## Example usage
After installation, do the following (from your command line, where the
`evennia` command is available) to install an example grid:
evennia xyzgrid init
evennia xyzgrid add evennia.contrib.grid.xyzgrid.example
evennia xyzgrid list
evennia xyzgrid show "the large tree"
evennia xyzgrid show "the small cave"
evennia xyzgrid spawn
evennia reload
(remember to reload the server after spawn operations).
Now you can log into the
server and do `teleport (3,0,the large tree)` to teleport into the map.
You can use `open togrid = (3, 0, the large tree)` to open a permanent (one-way)
exit from your current location into the grid. To make a way back to a non-grid
location just stand in a grid room and open a new exit out of it:
`open tolimbo = #2`.
Try `goto view` to go to the top of the tree and `goto dungeon` to go down to
the dungeon entrance at the bottom of the tree.
----
<small>This document page is generated from `evennia/contrib/grid/xyzgrid/README.md`. Changes to this
file will be overwritten, so edit that file rather than this one.</small>

View file

@ -1,18 +0,0 @@
```{eval-rst}
evennia.contrib.awsstorage
==================================
.. automodule:: evennia.contrib.awsstorage
:members:
:undoc-members:
:show-inheritance:
.. toctree::
:maxdepth: 6
evennia.contrib.awsstorage.aws_s3_cdn
evennia.contrib.awsstorage.tests
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.awsstorage.tests
=======================================
.. automodule:: evennia.contrib.awsstorage.tests
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.barter
=============================
.. automodule:: evennia.contrib.barter
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.awsstorage.aws\_s3\_cdn
============================================================
.. automodule:: evennia.contrib.base_systems.awsstorage.aws_s3_cdn
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,18 @@
```{eval-rst}
evennia.contrib.base\_systems.awsstorage
================================================
.. automodule:: evennia.contrib.base_systems.awsstorage
:members:
:undoc-members:
:show-inheritance:
.. toctree::
:maxdepth: 6
evennia.contrib.base_systems.awsstorage.aws_s3_cdn
evennia.contrib.base_systems.awsstorage.tests
```

View file

@ -1,8 +1,8 @@
```{eval-rst}
evennia.contrib.ingame\_python.callbackhandler
evennia.contrib.base\_systems.awsstorage.tests
=====================================================
.. automodule:: evennia.contrib.ingame_python.callbackhandler
.. automodule:: evennia.contrib.base_systems.awsstorage.tests
:members:
:undoc-members:
:show-inheritance:

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.building\_menu.building\_menu
==================================================================
.. automodule:: evennia.contrib.base_systems.building_menu.building_menu
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,18 @@
```{eval-rst}
evennia.contrib.base\_systems.building\_menu
====================================================
.. automodule:: evennia.contrib.base_systems.building_menu
:members:
:undoc-members:
:show-inheritance:
.. toctree::
:maxdepth: 6
evennia.contrib.base_systems.building_menu.building_menu
evennia.contrib.base_systems.building_menu.tests
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.building\_menu.tests
=========================================================
.. automodule:: evennia.contrib.base_systems.building_menu.tests
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.color\_markups.color\_markups
==================================================================
.. automodule:: evennia.contrib.base_systems.color_markups.color_markups
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,18 @@
```{eval-rst}
evennia.contrib.base\_systems.color\_markups
====================================================
.. automodule:: evennia.contrib.base_systems.color_markups
:members:
:undoc-members:
:show-inheritance:
.. toctree::
:maxdepth: 6
evennia.contrib.base_systems.color_markups.color_markups
evennia.contrib.base_systems.color_markups.tests
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.color\_markups.tests
=========================================================
.. automodule:: evennia.contrib.base_systems.color_markups.tests
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.custom\_gametime.custom\_gametime
======================================================================
.. automodule:: evennia.contrib.base_systems.custom_gametime.custom_gametime
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,18 @@
```{eval-rst}
evennia.contrib.base\_systems.custom\_gametime
======================================================
.. automodule:: evennia.contrib.base_systems.custom_gametime
:members:
:undoc-members:
:show-inheritance:
.. toctree::
:maxdepth: 6
evennia.contrib.base_systems.custom_gametime.custom_gametime
evennia.contrib.base_systems.custom_gametime.tests
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.custom\_gametime.tests
===========================================================
.. automodule:: evennia.contrib.base_systems.custom_gametime.tests
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.email\_login.connection\_screens
=====================================================================
.. automodule:: evennia.contrib.base_systems.email_login.connection_screens
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,8 +1,8 @@
```{eval-rst}
evennia.contrib.tutorial\_examples.example\_batch\_code
evennia.contrib.base\_systems.email\_login.email\_login
==============================================================
.. automodule:: evennia.contrib.tutorial_examples.example_batch_code
.. automodule:: evennia.contrib.base_systems.email_login.email_login
:members:
:undoc-members:
:show-inheritance:

View file

@ -0,0 +1,19 @@
```{eval-rst}
evennia.contrib.base\_systems.email\_login
==================================================
.. automodule:: evennia.contrib.base_systems.email_login
:members:
:undoc-members:
:show-inheritance:
.. toctree::
:maxdepth: 6
evennia.contrib.base_systems.email_login.connection_screens
evennia.contrib.base_systems.email_login.email_login
evennia.contrib.base_systems.email_login.tests
```

View file

@ -1,8 +1,8 @@
```{eval-rst}
evennia.contrib.tutorial\_examples.bodyfunctions
evennia.contrib.base\_systems.email\_login.tests
=======================================================
.. automodule:: evennia.contrib.tutorial_examples.bodyfunctions
.. automodule:: evennia.contrib.base_systems.email_login.tests
:members:
:undoc-members:
:show-inheritance:

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.ingame\_python.callbackhandler
===================================================================
.. automodule:: evennia.contrib.base_systems.ingame_python.callbackhandler
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.ingame\_python.commands
============================================================
.. automodule:: evennia.contrib.base_systems.ingame_python.commands
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.ingame\_python.eventfuncs
==============================================================
.. automodule:: evennia.contrib.base_systems.ingame_python.eventfuncs
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,23 @@
```{eval-rst}
evennia.contrib.base\_systems.ingame\_python
====================================================
.. automodule:: evennia.contrib.base_systems.ingame_python
:members:
:undoc-members:
:show-inheritance:
.. toctree::
:maxdepth: 6
evennia.contrib.base_systems.ingame_python.callbackhandler
evennia.contrib.base_systems.ingame_python.commands
evennia.contrib.base_systems.ingame_python.eventfuncs
evennia.contrib.base_systems.ingame_python.scripts
evennia.contrib.base_systems.ingame_python.tests
evennia.contrib.base_systems.ingame_python.typeclasses
evennia.contrib.base_systems.ingame_python.utils
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.ingame\_python.scripts
===========================================================
.. automodule:: evennia.contrib.base_systems.ingame_python.scripts
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.ingame\_python.tests
=========================================================
.. automodule:: evennia.contrib.base_systems.ingame_python.tests
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.ingame\_python.typeclasses
===============================================================
.. automodule:: evennia.contrib.base_systems.ingame_python.typeclasses
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.ingame\_python.utils
=========================================================
.. automodule:: evennia.contrib.base_systems.ingame_python.utils
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,24 @@
```{eval-rst}
evennia.contrib.base\_systems
=====================================
.. automodule:: evennia.contrib.base_systems
:members:
:undoc-members:
:show-inheritance:
.. toctree::
:maxdepth: 6
evennia.contrib.base_systems.awsstorage
evennia.contrib.base_systems.building_menu
evennia.contrib.base_systems.color_markups
evennia.contrib.base_systems.custom_gametime
evennia.contrib.base_systems.email_login
evennia.contrib.base_systems.ingame_python
evennia.contrib.base_systems.menu_login
evennia.contrib.base_systems.mux_comms_cmds
evennia.contrib.base_systems.unixcommand
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.menu\_login.connection\_screens
====================================================================
.. automodule:: evennia.contrib.base_systems.menu_login.connection_screens
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,19 @@
```{eval-rst}
evennia.contrib.base\_systems.menu\_login
=================================================
.. automodule:: evennia.contrib.base_systems.menu_login
:members:
:undoc-members:
:show-inheritance:
.. toctree::
:maxdepth: 6
evennia.contrib.base_systems.menu_login.connection_screens
evennia.contrib.base_systems.menu_login.menu_login
evennia.contrib.base_systems.menu_login.tests
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.menu\_login.menu\_login
============================================================
.. automodule:: evennia.contrib.base_systems.menu_login.menu_login
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.menu\_login.tests
======================================================
.. automodule:: evennia.contrib.base_systems.menu_login.tests
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,18 @@
```{eval-rst}
evennia.contrib.base\_systems.mux\_comms\_cmds
======================================================
.. automodule:: evennia.contrib.base_systems.mux_comms_cmds
:members:
:undoc-members:
:show-inheritance:
.. toctree::
:maxdepth: 6
evennia.contrib.base_systems.mux_comms_cmds.mux_comms_cmds
evennia.contrib.base_systems.mux_comms_cmds.tests
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.mux\_comms\_cmds.mux\_comms\_cmds
======================================================================
.. automodule:: evennia.contrib.base_systems.mux_comms_cmds.mux_comms_cmds
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.mux\_comms\_cmds.tests
===========================================================
.. automodule:: evennia.contrib.base_systems.mux_comms_cmds.tests
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,18 @@
```{eval-rst}
evennia.contrib.base\_systems.unixcommand
=================================================
.. automodule:: evennia.contrib.base_systems.unixcommand
:members:
:undoc-members:
:show-inheritance:
.. toctree::
:maxdepth: 6
evennia.contrib.base_systems.unixcommand.tests
evennia.contrib.base_systems.unixcommand.unixcommand
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.unixcommand.tests
======================================================
.. automodule:: evennia.contrib.base_systems.unixcommand.tests
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.base\_systems.unixcommand.unixcommand
============================================================
.. automodule:: evennia.contrib.base_systems.unixcommand.unixcommand
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.building\_menu
=====================================
.. automodule:: evennia.contrib.building_menu
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.chargen
==============================
.. automodule:: evennia.contrib.chargen
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.clothing
===============================
.. automodule:: evennia.contrib.clothing
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,19 +0,0 @@
```{eval-rst}
evennia.contrib.crafting
================================
.. automodule:: evennia.contrib.crafting
:members:
:undoc-members:
:show-inheritance:
.. toctree::
:maxdepth: 6
evennia.contrib.crafting.crafting
evennia.contrib.crafting.example_recipes
evennia.contrib.crafting.tests
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.crafting.tests
=====================================
.. automodule:: evennia.contrib.crafting.tests
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.dice
===========================
.. automodule:: evennia.contrib.dice
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.email\_login
===================================
.. automodule:: evennia.contrib.email_login
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,24 +0,0 @@
```{eval-rst}
evennia.contrib.evscaperoom
===================================
.. automodule:: evennia.contrib.evscaperoom
:members:
:undoc-members:
:show-inheritance:
.. toctree::
:maxdepth: 6
evennia.contrib.evscaperoom.commands
evennia.contrib.evscaperoom.menu
evennia.contrib.evscaperoom.objects
evennia.contrib.evscaperoom.room
evennia.contrib.evscaperoom.scripts
evennia.contrib.evscaperoom.state
evennia.contrib.evscaperoom.tests
evennia.contrib.evscaperoom.utils
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.evscaperoom.menu
=======================================
.. automodule:: evennia.contrib.evscaperoom.menu
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.evscaperoom.objects
==========================================
.. automodule:: evennia.contrib.evscaperoom.objects
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.evscaperoom.room
=======================================
.. automodule:: evennia.contrib.evscaperoom.room
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.evscaperoom.scripts
==========================================
.. automodule:: evennia.contrib.evscaperoom.scripts
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.evscaperoom.state
========================================
.. automodule:: evennia.contrib.evscaperoom.state
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.evscaperoom.tests
========================================
.. automodule:: evennia.contrib.evscaperoom.tests
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.evscaperoom.utils
========================================
.. automodule:: evennia.contrib.evscaperoom.utils
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.extended\_room
=====================================
.. automodule:: evennia.contrib.extended_room
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -1,10 +0,0 @@
```{eval-rst}
evennia.contrib.fieldfill
================================
.. automodule:: evennia.contrib.fieldfill
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,10 @@
```{eval-rst}
evennia.contrib.full\_systems.evscaperoom.commands
=========================================================
.. automodule:: evennia.contrib.full_systems.evscaperoom.commands
:members:
:undoc-members:
:show-inheritance:
```

View file

@ -0,0 +1,24 @@
```{eval-rst}
evennia.contrib.full\_systems.evscaperoom
=================================================
.. automodule:: evennia.contrib.full_systems.evscaperoom
:members:
:undoc-members:
:show-inheritance:
.. toctree::
:maxdepth: 6
evennia.contrib.full_systems.evscaperoom.commands
evennia.contrib.full_systems.evscaperoom.menu
evennia.contrib.full_systems.evscaperoom.objects
evennia.contrib.full_systems.evscaperoom.room
evennia.contrib.full_systems.evscaperoom.scripts
evennia.contrib.full_systems.evscaperoom.state
evennia.contrib.full_systems.evscaperoom.tests
evennia.contrib.full_systems.evscaperoom.utils
```

View file

@ -1,8 +1,8 @@
```{eval-rst}
evennia.contrib.tutorial\_examples.red\_button
evennia.contrib.full\_systems.evscaperoom.menu
=====================================================
.. automodule:: evennia.contrib.tutorial_examples.red_button
.. automodule:: evennia.contrib.full_systems.evscaperoom.menu
:members:
:undoc-members:
:show-inheritance:

Some files were not shown because too many files have changed in this diff Show more