Source code for evennia.contrib.grid.slow_exit.slow_exit
"""
Slow Exit typeclass
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) <---
```
## 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.
"""
from evennia.commands.cmdset import CmdSet
from evennia.commands.command import Command
from evennia.objects.objects import DefaultExit
from evennia.utils import utils
MOVE_DELAY = {"stroll": 6, "walk": 4, "run": 2, "sprint": 1}
[docs]class SlowExit(DefaultExit):
"""
This overloads the way moving happens.
"""
[docs] def at_traverse(self, traversing_object, target_location):
"""
Implements the actual traversal, using utils.delay to delay the move_to.
"""
# if the traverser has an Attribute move_speed, use that,
# otherwise default to "walk" speed
move_speed = traversing_object.db.move_speed or "walk"
move_delay = MOVE_DELAY.get(move_speed, 4)
def move_callback():
"This callback will be called by utils.delay after move_delay seconds."
source_location = traversing_object.location
if traversing_object.move_to(target_location, move_type="traverse"):
self.at_post_traverse(traversing_object, source_location)
else:
if self.db.err_traverse:
# if exit has a better error message, let's use it.
self.caller.msg(self.db.err_traverse)
else:
# No shorthand error message. Call hook.
self.at_failed_traverse(traversing_object)
traversing_object.msg("You start moving %s at a %s." % (self.key, move_speed))
# create a delayed movement
t = utils.delay(move_delay, move_callback)
# we store the deferred on the character, this will allow us
# to abort the movement. We must use an ndb here since
# deferreds cannot be pickled.
traversing_object.ndb.currently_moving = t
#
# set speed - command
#
SPEED_DESCS = {"stroll": "strolling", "walk": "walking", "run": "running", "sprint": "sprinting"}
[docs]class CmdSetSpeed(Command):
"""
set your movement speed
Usage:
setspeed stroll|walk|run|sprint
This will set your movement speed, determining how long time
it takes to traverse exits. If no speed is set, 'walk' speed
is assumed.
"""
key = "setspeed"
[docs] def func(self):
"""
Simply sets an Attribute used by the SlowExit above.
"""
speed = self.args.lower().strip()
if speed not in SPEED_DESCS:
self.caller.msg("Usage: setspeed stroll||walk||run||sprint")
elif self.caller.db.move_speed == speed:
self.caller.msg("You are already %s." % SPEED_DESCS[speed])
else:
self.caller.db.move_speed = speed
self.caller.msg("You are now %s." % SPEED_DESCS[speed])
#
# stop moving - command
#
[docs]class CmdStop(Command):
"""
stop moving
Usage:
stop
Stops the current movement, if any.
"""
key = "stop"
[docs] def func(self):
"""
This is a very simple command, using the
stored deferred from the exit traversal above.
"""
currently_moving = self.caller.ndb.currently_moving
if currently_moving and not currently_moving.called:
currently_moving.cancel()
self.caller.msg("You stop moving.")
for observer in self.caller.location.contents_get(self.caller):
observer.msg("%s stops." % self.caller.get_display_name(observer))
else:
self.caller.msg("You are not moving.")
[docs]class SlowExitCmdSet(CmdSet):
[docs] def at_cmdset_creation(self):
self.add(CmdSetSpeed())
self.add(CmdStop())