Auto-convert contrib readmes to doc pages
This commit is contained in:
parent
bc5ba46851
commit
b922cf9b3c
254 changed files with 7117 additions and 1060 deletions
|
|
@ -9,7 +9,7 @@ import re
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from sphinx.errors import DocumentError
|
from sphinx.errors import DocumentError
|
||||||
from pathlib import Path
|
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 = []
|
_IGNORE_FILES = []
|
||||||
_SOURCEDIR_NAME = "source"
|
_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
|
# 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```")
|
fil.write("\n```\n\n```{toctree}\n :hidden:\n\ntoc\n```")
|
||||||
|
print(" -- File toc.md updated.")
|
||||||
|
|
||||||
print(" -- Auto-Remapper finished.")
|
print(" -- Auto-Remapper finished.")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,81 @@ Convert contribs' README files to proper documentation pages along with
|
||||||
an index.
|
an index.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
from collections import defaultdict
|
||||||
from os.path import abspath, dirname, join as pathjoin, sep
|
from os.path import abspath, dirname, join as pathjoin, sep
|
||||||
from glob import glob
|
from glob import glob
|
||||||
|
|
||||||
_EVENNIA_PATH = pathjoin(dirname(dirname(dirname(abspath(__file__)))))
|
_EVENNIA_PATH = pathjoin(dirname(dirname(dirname(abspath(__file__)))))
|
||||||
_DOCS_PATH = pathjoin(_EVENNIA_PATH, "docs")
|
_DOCS_PATH = pathjoin(_EVENNIA_PATH, "docs")
|
||||||
|
|
||||||
_CONTRIB_PATH = pathjoin(_EVENNIA_PATH, "contrib")
|
_SOURCE_DIR = pathjoin(_EVENNIA_PATH, "evennia", "contrib")
|
||||||
_SOURCE_DIR = pathjoin(_EVENNIA_PATH, "contrib")
|
|
||||||
_OUT_DIR = pathjoin(_DOCS_PATH, "source", "Contribs")
|
_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 = """
|
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.
|
Parse directory for README files and convert them to doc pages.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
indexfile = []
|
ncount = 0
|
||||||
listing = []
|
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
|
# paths are e.g. evennia/contrib/utils/auditing/README.md
|
||||||
_, category, name, _ = file_path.rsplit(sep, 3)
|
_, 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)
|
outfile = pathjoin(_OUT_DIR, filename)
|
||||||
|
|
||||||
with open(file_path) as fil:
|
with open(file_path) as fil:
|
||||||
data = fil.read()
|
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:
|
with open(outfile, 'w') as fil:
|
||||||
fil.write(data)
|
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)
|
||||||
|
|
|
||||||
234
docs/source/Contribs/Contrib-AWSStorage.md
Normal file
234
docs/source/Contribs/Contrib-AWSStorage.md
Normal 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>
|
||||||
77
docs/source/Contribs/Contrib-Auditing.md
Normal file
77
docs/source/Contribs/Contrib-Auditing.md
Normal 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>
|
||||||
134
docs/source/Contribs/Contrib-Barter.md
Normal file
134
docs/source/Contribs/Contrib-Barter.md
Normal 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>
|
||||||
41
docs/source/Contribs/Contrib-Batchprocessor.md
Normal file
41
docs/source/Contribs/Contrib-Batchprocessor.md
Normal 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>
|
||||||
22
docs/source/Contribs/Contrib-Bodyfunctions.md
Normal file
22
docs/source/Contribs/Contrib-Bodyfunctions.md
Normal 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>
|
||||||
134
docs/source/Contribs/Contrib-Building-Menu.md
Normal file
134
docs/source/Contribs/Contrib-Building-Menu.md
Normal 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>
|
||||||
90
docs/source/Contribs/Contrib-Clothing.md
Normal file
90
docs/source/Contribs/Contrib-Clothing.md
Normal 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>
|
||||||
63
docs/source/Contribs/Contrib-Color-Markups.md
Normal file
63
docs/source/Contribs/Contrib-Color-Markups.md
Normal 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>
|
||||||
64
docs/source/Contribs/Contrib-Cooldowns.md
Normal file
64
docs/source/Contribs/Contrib-Cooldowns.md
Normal 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>
|
||||||
108
docs/source/Contribs/Contrib-Crafting.md
Normal file
108
docs/source/Contribs/Contrib-Crafting.md
Normal 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>
|
||||||
53
docs/source/Contribs/Contrib-Custom-Gametime.md
Normal file
53
docs/source/Contribs/Contrib-Custom-Gametime.md
Normal 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>
|
||||||
67
docs/source/Contribs/Contrib-Dice.md
Normal file
67
docs/source/Contribs/Contrib-Dice.md
Normal 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>
|
||||||
36
docs/source/Contribs/Contrib-Email-Login.md
Normal file
36
docs/source/Contribs/Contrib-Email-Login.md
Normal 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>
|
||||||
128
docs/source/Contribs/Contrib-Evscaperoom.md
Normal file
128
docs/source/Contribs/Contrib-Evscaperoom.md
Normal 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>
|
||||||
82
docs/source/Contribs/Contrib-Extended-Room.md
Normal file
82
docs/source/Contribs/Contrib-Extended-Room.md
Normal 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>
|
||||||
163
docs/source/Contribs/Contrib-Fieldfill.md
Normal file
163
docs/source/Contribs/Contrib-Fieldfill.md
Normal 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>
|
||||||
55
docs/source/Contribs/Contrib-Gendersub.md
Normal file
55
docs/source/Contribs/Contrib-Gendersub.md
Normal 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>
|
||||||
42
docs/source/Contribs/Contrib-Health-Bar.md
Normal file
42
docs/source/Contribs/Contrib-Health-Bar.md
Normal 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>
|
||||||
888
docs/source/Contribs/Contrib-Ingame-Python.md
Normal file
888
docs/source/Contribs/Contrib-Ingame-Python.md
Normal 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>
|
||||||
46
docs/source/Contribs/Contrib-Mail.md
Normal file
46
docs/source/Contribs/Contrib-Mail.md
Normal 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>
|
||||||
284
docs/source/Contribs/Contrib-Mapbuilder.md
Normal file
284
docs/source/Contribs/Contrib-Mapbuilder.md
Normal 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>
|
||||||
28
docs/source/Contribs/Contrib-Menu-Login.md
Normal file
28
docs/source/Contribs/Contrib-Menu-Login.md
Normal 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>
|
||||||
23
docs/source/Contribs/Contrib-Mirror.md
Normal file
23
docs/source/Contribs/Contrib-Mirror.md
Normal 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>
|
||||||
30
docs/source/Contribs/Contrib-Multidescer.md
Normal file
30
docs/source/Contribs/Contrib-Multidescer.md
Normal 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>
|
||||||
48
docs/source/Contribs/Contrib-Mux-Comms-Cmds.md
Normal file
48
docs/source/Contribs/Contrib-Mux-Comms-Cmds.md
Normal 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>
|
||||||
|
|
@ -1,335 +1,625 @@
|
||||||
# Contrib modules
|
# Contribs
|
||||||
|
|
||||||
Contribs are found in [evennia/contrib/](evennia.contrib) and are optional game-specific code-snippets
|
_Contribs_ are optional code snippets and systems contributed by
|
||||||
or even full systems you can use for your game. They are contributed by the Evennia community and
|
the Evennia community. They vary in size and complexity and
|
||||||
released under the same license as Evennia itself. Each contrib has its own installation instructions.
|
may be more specific about game types and styles than 'core' Evennia.
|
||||||
Bugs are reported to the Evennia [issue tracker](github:issue) as usual.
|
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
|
[Read the documentation](./Contrib-Building-Menu.md)
|
||||||
strings and maintained outside of the game via Evennia launch commands.
|
|
||||||
|
|
||||||
- [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)
|
Contribution - Vincent-lg 2016, Griatch 2019 (rework for modern EvMenu)
|
||||||
- [Crafting API documentation](evennia.contrib.crafting.crafting)
|
|
||||||
- [Example of a sword crafting tree](evennia.contrib.crafting.example_recipes)
|
|
||||||
|
|
||||||
### 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,
|
### Contrib: `evscaperoom`
|
||||||
and includes optional expansions for equipment and combat movement, magic and ranged combat.
|
|
||||||
|
|
||||||
----
|
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)
|
### Contrib: `barter`
|
||||||
- [Dialogues using events](./Dialogues-in-events.md)
|
|
||||||
|
|
||||||
### Menu-builder
|
Evennia contribution - Griatch 2012
|
||||||
|
|
||||||
A tool for building using an in-game menu instead of the normal build commands. Meant to
|
This implements a full barter system - a way for players to safely
|
||||||
be expanded for the needs of your game.
|
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
|
[Read the documentation](./Contrib-Clothing.md)
|
||||||
multi-line string.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 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/).
|
## grid
|
||||||
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.
|
|
||||||
|
|
||||||
- [Arxcode repository on github](https://github.com/Arx-Game/arxcode)
|
_Systems related to the game world's topology and structure. This has
|
||||||
- [Arxcode issue tracker](https://github.com/Arx-Game/arxcode/issues)
|
contribs related to rooms, exits and map building._
|
||||||
- [Arxcode installation help](./Arxcode-installing-help.md) - this may not always be fully up-to-date with
|
|
||||||
latest Evennia. Report your findings!
|
|
||||||
|
|
||||||
### 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}
|
```{toctree}
|
||||||
:hidden:
|
:depth: 2
|
||||||
|
|
||||||
./Crafting
|
Contribs/Contrib-AWSStorage.md
|
||||||
../api/evennia.contrib.crafting.crafting
|
Contribs/Contrib-Building-Menu.md
|
||||||
../api/evennia.contrib.crafting.example_recipes
|
Contribs/Contrib-Color-Markups.md
|
||||||
./A-voice-operated-elevator-using-events
|
Contribs/Contrib-Custom-Gametime.md
|
||||||
./Dialogues-in-events
|
Contribs/Contrib-Email-Login.md
|
||||||
./Dynamic-In-Game-Map
|
Contribs/Contrib-Ingame-Python.md
|
||||||
./Static-In-Game-Map
|
Contribs/Contrib-Menu-Login.md
|
||||||
../Howto/Starting/Part1/Tutorial-World-Introduction
|
Contribs/Contrib-Mux-Comms-Cmds.md
|
||||||
./Building-menus
|
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>
|
||||||
|
|
|
||||||
74
docs/source/Contribs/Contrib-Puzzles.md
Normal file
74
docs/source/Contribs/Contrib-Puzzles.md
Normal 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>
|
||||||
263
docs/source/Contribs/Contrib-RPSystem.md
Normal file
263
docs/source/Contribs/Contrib-RPSystem.md
Normal 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>
|
||||||
58
docs/source/Contribs/Contrib-Random-String-Generator.md
Normal file
58
docs/source/Contribs/Contrib-Random-String-Generator.md
Normal 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>
|
||||||
40
docs/source/Contribs/Contrib-Red-Button.md
Normal file
40
docs/source/Contribs/Contrib-Red-Button.md
Normal 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>
|
||||||
50
docs/source/Contribs/Contrib-Simpledoor.md
Normal file
50
docs/source/Contribs/Contrib-Simpledoor.md
Normal 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>
|
||||||
67
docs/source/Contribs/Contrib-Slow-Exit.md
Normal file
67
docs/source/Contribs/Contrib-Slow-Exit.md
Normal 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>
|
||||||
27
docs/source/Contribs/Contrib-Talking-Npc.md
Normal file
27
docs/source/Contribs/Contrib-Talking-Npc.md
Normal 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>
|
||||||
449
docs/source/Contribs/Contrib-Traits.md
Normal file
449
docs/source/Contribs/Contrib-Traits.md
Normal 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>
|
||||||
167
docs/source/Contribs/Contrib-Tree-Select.md
Normal file
167
docs/source/Contribs/Contrib-Tree-Select.md
Normal 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>
|
||||||
61
docs/source/Contribs/Contrib-Turnbattle.md
Normal file
61
docs/source/Contribs/Contrib-Turnbattle.md
Normal 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>
|
||||||
113
docs/source/Contribs/Contrib-Tutorial-World.md
Normal file
113
docs/source/Contribs/Contrib-Tutorial-World.md
Normal 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>
|
||||||
71
docs/source/Contribs/Contrib-Unixcommand.md
Normal file
71
docs/source/Contribs/Contrib-Unixcommand.md
Normal 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>
|
||||||
119
docs/source/Contribs/Contrib-Wilderness.md
Normal file
119
docs/source/Contribs/Contrib-Wilderness.md
Normal 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>
|
||||||
72
docs/source/Contribs/Contrib-XYZGrid.md
Normal file
72
docs/source/Contribs/Contrib-XYZGrid.md
Normal 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>
|
||||||
|
|
@ -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
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.awsstorage.tests
|
|
||||||
=======================================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.awsstorage.tests
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.barter
|
|
||||||
=============================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.barter
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
18
docs/source/api/evennia.contrib.base_systems.awsstorage.md
Normal file
18
docs/source/api/evennia.contrib.base_systems.awsstorage.md
Normal 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
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
```{eval-rst}
|
```{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:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
```{eval-rst}
|
```{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:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
19
docs/source/api/evennia.contrib.base_systems.email_login.md
Normal file
19
docs/source/api/evennia.contrib.base_systems.email_login.md
Normal 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
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
```{eval-rst}
|
```{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:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
24
docs/source/api/evennia.contrib.base_systems.md
Normal file
24
docs/source/api/evennia.contrib.base_systems.md
Normal 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
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
19
docs/source/api/evennia.contrib.base_systems.menu_login.md
Normal file
19
docs/source/api/evennia.contrib.base_systems.menu_login.md
Normal 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
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
```
|
||||||
18
docs/source/api/evennia.contrib.base_systems.unixcommand.md
Normal file
18
docs/source/api/evennia.contrib.base_systems.unixcommand.md
Normal 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
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
```{eval-rst}
|
||||||
|
evennia.contrib.base\_systems.unixcommand.tests
|
||||||
|
======================================================
|
||||||
|
|
||||||
|
.. automodule:: evennia.contrib.base_systems.unixcommand.tests
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
```{eval-rst}
|
||||||
|
evennia.contrib.base\_systems.unixcommand.unixcommand
|
||||||
|
============================================================
|
||||||
|
|
||||||
|
.. automodule:: evennia.contrib.base_systems.unixcommand.unixcommand
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.building\_menu
|
|
||||||
=====================================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.building_menu
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.chargen
|
|
||||||
==============================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.chargen
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.clothing
|
|
||||||
===============================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.clothing
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.crafting.tests
|
|
||||||
=====================================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.crafting.tests
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.dice
|
|
||||||
===========================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.dice
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.email\_login
|
|
||||||
===================================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.email_login
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.evscaperoom.menu
|
|
||||||
=======================================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.evscaperoom.menu
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.evscaperoom.objects
|
|
||||||
==========================================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.evscaperoom.objects
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.evscaperoom.room
|
|
||||||
=======================================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.evscaperoom.room
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.evscaperoom.scripts
|
|
||||||
==========================================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.evscaperoom.scripts
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.evscaperoom.state
|
|
||||||
========================================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.evscaperoom.state
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.evscaperoom.tests
|
|
||||||
========================================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.evscaperoom.tests
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.evscaperoom.utils
|
|
||||||
========================================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.evscaperoom.utils
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.extended\_room
|
|
||||||
=====================================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.extended_room
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
```{eval-rst}
|
|
||||||
evennia.contrib.fieldfill
|
|
||||||
================================
|
|
||||||
|
|
||||||
.. automodule:: evennia.contrib.fieldfill
|
|
||||||
:members:
|
|
||||||
:undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
```{eval-rst}
|
||||||
|
evennia.contrib.full\_systems.evscaperoom.commands
|
||||||
|
=========================================================
|
||||||
|
|
||||||
|
.. automodule:: evennia.contrib.full_systems.evscaperoom.commands
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
```
|
||||||
24
docs/source/api/evennia.contrib.full_systems.evscaperoom.md
Normal file
24
docs/source/api/evennia.contrib.full_systems.evscaperoom.md
Normal 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
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
```{eval-rst}
|
```{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:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue