A sconce, both a producer of long-lasting candles, as well as an "opener" that when pulled opens a secret passage.
177 lines
5.3 KiB
Python
177 lines
5.3 KiB
Python
"""
|
|
Exits
|
|
|
|
Exits are connectors between Rooms. An exit always has a destination property
|
|
set and has a single command defined on itself with the same name as its key,
|
|
for allowing Characters to traverse the exit to its destination.
|
|
|
|
"""
|
|
|
|
from evennia.objects.objects import DefaultExit
|
|
from evennia.commands.cmdset import CmdSet
|
|
from evennia.commands.command import Command
|
|
from evennia.utils import utils
|
|
|
|
from .objects import ObjectParent
|
|
from utils.word_list import choices
|
|
|
|
MOVE_DELAY = {"stroll": 6, "walk": 4, "run": 2, "sprint": 1}
|
|
|
|
SPEED_DESCS = {"stroll": "strolling", "walk": "walking", "run": "running", "sprint": "sprinting"}
|
|
|
|
|
|
class Exit(ObjectParent, DefaultExit):
|
|
"""
|
|
Exits are connectors between rooms. Exits are normal Objects except
|
|
they defines the `destination` property and overrides some hooks
|
|
and methods to represent the exits.
|
|
|
|
See mygame/typeclasses/objects.py for a list of
|
|
properties and methods available on all Objects child classes like this.
|
|
"""
|
|
|
|
def at_traverse(self, traveler, destination):
|
|
"""
|
|
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 = traveler.db.move_speed or "walk"
|
|
move_delay = MOVE_DELAY.get(move_speed, 4)
|
|
pre_check = traveler.at_pre_move(destination)
|
|
|
|
def move_callback():
|
|
"This callback will be called by utils.delay after move_delay seconds."
|
|
source_location = traveler.location
|
|
if traveler.move_to(destination, move_type="traverse"):
|
|
self.at_post_traverse(traveler, 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(traveler)
|
|
|
|
if pre_check:
|
|
moving = SPEED_DESCS[move_speed]
|
|
if self.db.traverse_msg:
|
|
msg = choices(f"\n{self.db.traverse_msg}\n", move_speed, moving)
|
|
else:
|
|
if self.key in ['north', 'south', 'east', 'west']:
|
|
msg = f"You start {moving} {self.key}."
|
|
else:
|
|
msg = f"You start {moving} on {self.key}."
|
|
|
|
traveler.msg(msg)
|
|
else:
|
|
if self.db.err_traverse:
|
|
# if exit has a better error message, let's use it.
|
|
self.caller.msg(self.db.err_traverse)
|
|
return False
|
|
|
|
# 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.
|
|
traveler.ndb.currently_moving = t
|
|
|
|
|
|
class Opener():
|
|
"""
|
|
A mixin that can open or close an exit.
|
|
Done by moving an Exit to/from None and a Room.
|
|
"""
|
|
def do_open(self, room_obj=None, exit_obj=None):
|
|
"""
|
|
Move a stored exit into a room.
|
|
"""
|
|
if not room_obj:
|
|
room_obj = self.db.room
|
|
if not exit_obj:
|
|
exit_obj = self.db.exit
|
|
# Do the move:
|
|
if exit_obj and room_obj:
|
|
exit_obj.location = room_obj
|
|
|
|
def do_close(self, exit_obj=None):
|
|
"""
|
|
Remove an exit.
|
|
"""
|
|
if not exit_obj:
|
|
exit_obj = self.db.exit
|
|
# Do the move:
|
|
if exit_obj:
|
|
exit_obj.location = None
|
|
|
|
#
|
|
# set speed - command
|
|
#
|
|
|
|
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"
|
|
|
|
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
|
|
#
|
|
|
|
|
|
class CmdStop(Command):
|
|
"""
|
|
stop moving
|
|
|
|
Usage:
|
|
stop
|
|
|
|
Stops the current movement, if any.
|
|
"""
|
|
|
|
key = "stop"
|
|
|
|
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.")
|
|
|
|
|
|
class SlowExitCmdSet(CmdSet):
|
|
def at_cmdset_creation(self):
|
|
self.add(CmdSetSpeed())
|
|
self.add(CmdStop())
|