The sailing script now stores particular aliases to manipulate the exits to simulate sailing. Created George, the tinkering dwarf and his project that he needs help completing. Created an adventuring Hobbit who sails the sea. Created a "summarizing script" to limit the amount of chat history each Chatbot needs in order to carry on a conversation. Created a stateful object that changes its appearance based on "who" is looking. This allows a George's project to be seen as a complete bird to those who have given George some feathers.
179 lines
5.4 KiB
Python
179 lines
5.4 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 re import match
|
|
|
|
from evennia.objects.objects import DefaultExit
|
|
from evennia.commands.cmdset import CmdSet
|
|
from evennia.commands.command import Command
|
|
from evennia.utils import utils, logger
|
|
|
|
from .objects import ObjectParent, Object
|
|
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(Object):
|
|
"""
|
|
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:
|
|
logger.info(f"Opening {exit_obj.key} and {room_obj.key}")
|
|
if exit_obj and room_obj:
|
|
exit_obj.move_to(room_obj, quiet=True)
|
|
|
|
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())
|