Refactoring contribs

This commit is contained in:
Griatch 2021-12-18 18:02:37 +01:00
parent f5f75bd04d
commit 0ab1c30716
103 changed files with 3203 additions and 604 deletions

View file

@ -0,0 +1,5 @@
"""
Extened Room - Griatch 2012, vincent-lg 2019
"""

View file

@ -0,0 +1,76 @@
# 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.

View file

@ -0,0 +1,11 @@
"""
Extended Room - Griatch 2012, vincent-lg 2019
"""
from .extended_room import ExtendedRoom # noqa
from .extended_room import ExtendedRoomCmdSet # noqa
from .extended_room import CmdExtendedRoomLook # noqa
from .extended_room import CmdExtendedRoomDesc # noqa
from .extended_room import CmdExtendedRoomDetail # noqa
from .extended_room import CmdExtendedRoomGameTime # noqa

View file

@ -45,7 +45,7 @@ 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.
if applicable. The `detail` command is used to change details.
4) Extra commands
@ -67,13 +67,13 @@ In more detail, in mygame/commands/default_cmdsets.py:
```
...
from evennia.contrib import extended_room # <-new
from evennia.contrib import extended_room # <---
class CharacterCmdset(default_cmds.Character_CmdSet):
...
def at_cmdset_creation(self):
...
self.add(extended_room.ExtendedRoomCmdSet) # <-new
self.add(extended_room.ExtendedRoomCmdSet) # <---
```

View file

@ -0,0 +1,278 @@
# 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.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.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.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,
}
```

View file

@ -0,0 +1,6 @@
"""
Mapbuilder - Cloud Keeper 2016
"""
from .mapbuilder import CmdMapBuilder # noqa

View file

@ -51,43 +51,46 @@ 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 import mapbuilder
from evennia.contrib.grid import mapbuilder
...
self.add(mapbuilder.CmdMapBuilder())
```
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.
Usage:
@mapbuilder[/switch] <path.to.file.MAPNAME> <path.to.file.MAP_LEGEND>
## Usage
Switches:
one - execute build instructions once without automatic exit creation.
two - execute build instructions twice without automatic exit creation.
mapbuilder[/switch] <path.to.file.MAPNAME> <path.to.file.MAP_LEGEND>
Example:
@mapbuilder world.gamemap.MAP world.maplegend.MAP_LEGEND
@mapbuilder evennia.contrib.mapbuilder.EXAMPLE1_MAP EXAMPLE1_LEGEND
@mapbuilder/two evennia.contrib.mapbuilder.EXAMPLE2_MAP EXAMPLE2_LEGEND
one - execute build instructions once without automatic exit creation.
two - execute build instructions twice without automatic exit creation.
## Example
mapbuilder world.gamemap.MAP world.maplegend.MAP_LEGEND
mapbuilder evennia.contrib.grid.mapbuilder.EXAMPLE1_MAP EXAMPLE1_LEGEND
mapbuilder/two evennia.contrib.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:
from django.conf import settings
from evennia.utils import utils
# ---------- EXAMPLE 1 ---------- #
```python
# @mapbuilder evennia.contrib.mapbuilder.EXAMPLE1_MAP EXAMPLE1_LEGEND
# -*- coding: utf-8 -*-
@ -102,18 +105,17 @@ 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 = """\
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."""
'''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))
@ -127,7 +129,7 @@ def example1_build_forest(x, y, **kwargs):
def example1_build_mountains(x, y, **kwargs):
"""A room that is a little more advanced"""
'''A room that is a little more advanced'''
# Create the room.
room = create_object(rooms.Room, key="mountains" + str(x) + str(y))
@ -153,7 +155,7 @@ def example1_build_mountains(x, y, **kwargs):
def example1_build_temple(x, y, **kwargs):
"""A unique room that does not need to be as general"""
'''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))
@ -184,8 +186,11 @@ EXAMPLE1_LEGEND = {
("", "n"): example1_build_mountains,
(""): example1_build_temple,
}
```
# ---------- EXAMPLE 2 ---------- #
# Example two
```python
# @mapbuilder/two evennia.contrib.mapbuilder.EXAMPLE2_MAP EXAMPLE2_LEGEND
# -*- coding: utf-8 -*-
@ -199,7 +204,7 @@ EXAMPLE1_LEGEND = {
# 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 = """\
EXAMPLE2_MAP = '''
--
@ -209,11 +214,10 @@ EXAMPLE2_MAP = """\
--
"""
'''
def example2_build_forest(x, y, **kwargs):
"""A basic room"""
'''A basic room'''
# If on anything other than the first iteration - Do nothing.
if kwargs["iteration"] > 0:
return None
@ -227,7 +231,7 @@ def example2_build_forest(x, y, **kwargs):
def example2_build_verticle_exit(x, y, **kwargs):
"""Creates two exits to and from the two rooms north and south."""
'''Creates two exits to and from the two rooms north and south.'''
# If on the first iteration - Do nothing.
if kwargs["iteration"] == 0:
return
@ -248,7 +252,7 @@ def example2_build_verticle_exit(x, y, **kwargs):
def example2_build_horizontal_exit(x, y, **kwargs):
"""Creates two exits to and from the two rooms east and west."""
'''Creates two exits to and from the two rooms east and west.'''
# If on the first iteration - Do nothing.
if kwargs["iteration"] == 0:
return
@ -270,7 +274,14 @@ EXAMPLE2_LEGEND = {
("-"): example2_build_horizontal_exit,
}
# ---------- END OF EXAMPLES ---------- #
```
---
"""
from django.conf import settings
from evennia.utils import utils
from evennia import create_object
from typeclasses import exits
COMMAND_DEFAULT_CLASS = utils.class_from_module(settings.COMMAND_DEFAULT_CLASS)

View file

@ -0,0 +1,44 @@
# 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.

View file

@ -0,0 +1,7 @@
"""
Simple Door - Griatch 2016
"""
from .simpledoor import SimpleDoorCmdSet # noqa
from .simpledoor import SimpleDoor # noqa

View file

@ -13,14 +13,29 @@ non-superuser account.
Installation:
Import this module in mygame/commands/default_cmdsets and add
the CmdOpen and CmdOpenCloseDoor commands to the CharacterCmdSet;
then reload the server.
To try it out, `@dig` a new room and then use the (overloaded) `@open`
Import this module in mygame/commands/default_cmdsets and add
the SimpleDoorCmdSet 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.simpledoor.SimpleDoor = otherroom
@open doorway:contrib.grid.simpledoor.SimpleDoor = otherroom
You can then use `open doorway' and `close doorway` to change the open
state. If you are not superuser (`@quell` yourself) you'll find you
@ -30,6 +45,7 @@ other side.
"""
from evennia import DefaultExit, default_cmds
from evennia.commands.cmdset import CmdSet
from evennia.utils.utils import inherits_from
@ -170,3 +186,9 @@ class CmdOpenCloseDoor(default_cmds.MuxCommand):
else:
door.setlock("traverse:false()")
self.caller.msg("You close %s." % door.key)
class SimpleDoorCmdSet(CmdSet):
def at_cmdset_creation(self):
self.add(CmdOpen())
self.add(CmdOpenCloseDoor())

View file

@ -0,0 +1,61 @@
# 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.

View file

@ -0,0 +1,9 @@
"""
Slow Exit - Griatch 2014
"""
from .slow_exit import SlowExitCmdSet # noqa
from .slow_exit import SlowExit # noqa
from .slow_exit import CmdSetSpeed # noqa
from .slow_exit import CmdStop # noqa

View file

@ -4,28 +4,48 @@ Slow Exit typeclass
Contribution - Griatch 2014
This is an example of an Exit-type that delays its traversal.This
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
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.slow_exit.SlowExit = <destination>
@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.
Installation:
```
# in mygame/typeclasses/exits.py
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.
from evennia.contrib.grid.slowexit import SlowExit
To get the ability to change your speed and abort your movement,
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).
class Exit(SlowExit):
# ...
Notes:
```
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) <---
```
## Notes:
This implementation is efficient but not persistent; so incomplete
movement will be lost in a server reload. This is acceptable for most
@ -35,7 +55,11 @@ TickerHandler might be better.
"""
from evennia import DefaultExit, utils, Command
from evennia.objects.objects import DefaultExit
from evennia.utils import utils
from evennia.commands.command import Command
from evennia.commands.cmdset import CmdSet
MOVE_DELAY = {"stroll": 6, "walk": 4, "run": 2, "sprint": 1}
@ -142,3 +166,9 @@ class CmdStop(Command):
observer.msg("%s stops." % self.caller.get_display_name(observer))
else:
self.caller.msg("You are not moving.")
class SlowExitCmdSet(CmdSet):
def at_cmdset_creation(self):
self.add(CmdSetSpeed())
self.add(CmdStop())

View file

@ -0,0 +1,113 @@
# 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.

View file

@ -0,0 +1,14 @@
"""
Wilderness contrib - titeuf87, 2017
"""
from .wilderness import create_wilderness # noqa
from .wilderness import enter_wilderness # noqa
from .wilderness import get_new_coordinates # noqa
from .wilderness import WildernessScript # noqa
from .wilderness import WildernessExit # noqa
from .wilderness import WildernessRoom # noqa
from .wilderness import WildernessMapProvider # noqa
from .wilderness import Wilderness # noqa
from .wilderness import WildernessMap # noqa

View file

@ -7,43 +7,43 @@ This contrib provides a wilderness map. This is an area that can be huge where
the rooms are mostly similar, except for some small cosmetic changes like the
room name.
Usage:
## Usage
This contrib does not provide any commands. Instead the @py command can be
used.
This contrib does not provide any new commands. Instead the default `py` command
is used.
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.
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 import wilderness; wilderness.create_wilderness()
@py from evennia.contrib.grid import wilderness; wilderness.create_wilderness()
Once created, it is possible to move into that wilderness map:
Once created, it is possible to move into that wilderness map:
@py from evennia.contrib import wilderness; wilderness.enter_wilderness(me)
@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.
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:
## 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 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.
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.
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.
Customisation example:
## 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
@ -51,59 +51,56 @@ Customisation example:
Let's create a file world/pyramid.py:
```python
map_str = \"\"\"
.
...
.....
.......
\"\"\"
```python
map_str = '''
.
...
.....
.......
'''
from evennia.contrib import wilderness
from evennia.contrib.grid import wilderness
class PyramidMapProvider(wilderness.WildernessMapProvider):
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 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 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
```
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:
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 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))
@py from evennia.contrib import wilderness; wilderness.enter_wilderness(me, coordinates=(4, 1))
```
Implementation details:
## 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

View file

@ -0,0 +1,15 @@
"""
XYZGrid - Evennia 2021
"""
from . import commands # noqa
from . import example # noqa
from . import launchcmd # noqa
from . import prototypes # noqa
from . import tests # noqa
from . import utils # noqa
from . import xymap # noqa
from . import xymap_legend # noqa
from . import xyzgrid # noqa
from . import xyzroom # noqa

View file

@ -12,8 +12,8 @@ from django.conf import settings
from evennia import InterruptCommand
from evennia import default_cmds, CmdSet
from evennia.commands.default import building
from evennia.contrib.xyzgrid.xyzroom import XYZRoom
from evennia.contrib.xyzgrid.xyzgrid import get_xyzgrid
from evennia.contrib.grid.xyzgrid.xyzroom import XYZRoom
from evennia.contrib.grid.xyzgrid.xyzgrid import get_xyzgrid
from evennia.utils import ansi
from evennia.utils.utils import list_to_string, class_from_module, delay

View file

@ -17,7 +17,7 @@ Then
"""
from evennia.contrib.xyzgrid import xymap_legend
from evennia.contrib.grid.xyzgrid import xymap_legend
# default prototype parent. It's important that
# the typeclass inherits from the XYZRoom (or XYZExit)

View file

@ -20,7 +20,7 @@ from os.path import join as pathjoin
from django.conf import settings
import evennia
from evennia.utils import ansi
from evennia.contrib.xyzgrid.xyzgrid import get_xyzgrid
from evennia.contrib.grid.xyzgrid.xyzgrid import get_xyzgrid
_HELP_SHORT = """

View file

@ -4,7 +4,6 @@ Tests for the XYZgrid system.
"""
from time import time
from random import randint
from parameterized import parameterized
from django.test import TestCase

View file

@ -18,7 +18,7 @@ The grid has three main functions:
"""
from evennia.scripts.scripts import DefaultScript
from evennia.utils import logger
from evennia.utils.utils import variable_from_module, make_iter
from evennia.utils.utils import variable_from_module
from .xymap import XYMap
from .xyzroom import XYZRoom, XYZExit

View file

@ -10,7 +10,6 @@ used as stand-alone XYZ-coordinate-aware rooms.
from django.db.models import Q
from evennia.objects.objects import DefaultRoom, DefaultExit
from evennia.objects.manager import ObjectManager
from evennia.utils.utils import make_iter
# name of all tag categories. Note that the Z-coordinate is
# the `map_name` of the XYZgrid