Adding a batchcommands file with descriptions
And fixed a number of bugs with starting from scratch.
This commit is contained in:
parent
0850301c65
commit
3d1ebfa3fc
9 changed files with 1255 additions and 343 deletions
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from commands.command import Command
|
||||
from evennia import CmdSet
|
||||
from evennia import Command, CmdSet
|
||||
# from .command import Command
|
||||
|
||||
class CmdLight(Command):
|
||||
"""
|
||||
|
|
@ -11,19 +11,17 @@ class CmdLight(Command):
|
|||
key = "light"
|
||||
aliases = ["burn"]
|
||||
# only allow this command if command.obj is carried by caller.
|
||||
locks = "cmd:holds()"
|
||||
# locks = "cmd:holds()"
|
||||
|
||||
def func(self):
|
||||
"""
|
||||
Implements the light command. Since this command is designed
|
||||
to sit on a "lightable" object, we operate only on self.obj.
|
||||
"""
|
||||
|
||||
if self.obj.light():
|
||||
self.caller.msg("You light %s." % self.obj.key)
|
||||
self.caller.location.msg_contents(
|
||||
"%s lights %s!" % (self.caller, self.obj.key), exclude=[self.caller]
|
||||
)
|
||||
"%s lights %s!" % (self.caller, self.obj.key), exclude=[self.caller])
|
||||
else:
|
||||
self.caller.msg("%s is already burning." % self.obj.key)
|
||||
|
||||
|
|
@ -31,10 +29,6 @@ class CmdLight(Command):
|
|||
class CmdSetLight(CmdSet):
|
||||
"""CmdSet for the lightsource commands"""
|
||||
|
||||
key = "lightsource_cmdset"
|
||||
# this is higher than the dark cmdset - important!
|
||||
priority = 3
|
||||
|
||||
def at_cmdset_creation(self):
|
||||
"""called at cmdset creation"""
|
||||
self.add(CmdLight())
|
||||
self.add(CmdLight)
|
||||
|
|
|
|||
97
typeclasses/lightables.py
Executable file
97
typeclasses/lightables.py
Executable file
|
|
@ -0,0 +1,97 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from commands.lighting import CmdSetLight
|
||||
|
||||
# -------------------------------------------------------------
|
||||
#
|
||||
# LightSource
|
||||
#
|
||||
# This object emits light. Once it has been turned on it
|
||||
# cannot be turned off. When it burns out it will delete
|
||||
# itself.
|
||||
#
|
||||
# This could be implemented using a single-repeat Script or by
|
||||
# registering with the TickerHandler. We do it simpler by
|
||||
# using the delay() utility function. This is very simple
|
||||
# to use but does not survive a server @reload. Because of
|
||||
# where the light matters (in the Dark Room where you can
|
||||
# find new light sources easily), this is okay here.
|
||||
#
|
||||
# -------------------------------------------------------------
|
||||
|
||||
class LightSource(Object):
|
||||
"""
|
||||
This implements a light source object.
|
||||
|
||||
When burned out, the object will be deleted.
|
||||
"""
|
||||
|
||||
def at_init(self):
|
||||
"""
|
||||
If this is called with the Attribute is_giving_light already
|
||||
set, we know that the timer got killed by a server
|
||||
reload/reboot before it had time to finish. So we kill it here
|
||||
instead. This is the price we pay for the simplicity of the
|
||||
non-persistent delay() method.
|
||||
"""
|
||||
if self.db.is_giving_light:
|
||||
self.delete()
|
||||
|
||||
def at_object_creation(self):
|
||||
"""Called when object is first created."""
|
||||
super().at_object_creation()
|
||||
|
||||
self.db.is_giving_light = False
|
||||
self.db.burntime = 60 * 3 # 3 minutes
|
||||
# this is the default desc, it can of course be customized
|
||||
# when created.
|
||||
self.db.desc = "A tapered candle."
|
||||
# add the Light command
|
||||
self.cmdset.add_default(CmdSetLight, persistent=True)
|
||||
|
||||
def _burnout(self):
|
||||
"""
|
||||
This is called when this light source burns out. We make no
|
||||
use of the return value.
|
||||
"""
|
||||
# delete ourselves from the database
|
||||
self.db.is_giving_light = False
|
||||
try:
|
||||
self.location.location.msg_contents(
|
||||
"%s's %s flickers and dies." % (self.location, self.key), exclude=self.location
|
||||
)
|
||||
self.location.msg("Your %s flickers and dies." % self.key)
|
||||
self.location.location.check_light_state()
|
||||
except AttributeError:
|
||||
try:
|
||||
self.location.msg_contents("A %s on the floor flickers and dies." % self.key)
|
||||
self.location.location.check_light_state()
|
||||
except AttributeError:
|
||||
# Mainly happens if we happen to be in a None location
|
||||
pass
|
||||
self.delete()
|
||||
|
||||
def light(self):
|
||||
"""
|
||||
Light this object - this is called by Light command.
|
||||
"""
|
||||
if self.db.is_giving_light:
|
||||
return False
|
||||
# burn for 3 minutes before calling _burnout
|
||||
self.db.is_giving_light = True
|
||||
# if we are in a dark room, trigger its light check
|
||||
try:
|
||||
self.location.location.check_light_state()
|
||||
except AttributeError:
|
||||
try:
|
||||
# maybe we are directly in the room
|
||||
self.location.check_light_state()
|
||||
except AttributeError:
|
||||
# we are in a None location
|
||||
pass
|
||||
finally:
|
||||
# start the burn timer. When it runs out, self._burnout
|
||||
# will be called. We store the deferred so it can be
|
||||
# killed in unittesting.
|
||||
self.deferred = delay(60 * 3, self._burnout)
|
||||
return True
|
||||
110
typeclasses/objects.py
Normal file → Executable file
110
typeclasses/objects.py
Normal file → Executable file
|
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Object
|
||||
|
||||
|
|
@ -9,9 +11,8 @@ with a location in the game world (like Characters, Rooms, Exits).
|
|||
"""
|
||||
|
||||
from evennia.objects.objects import DefaultObject
|
||||
from evennia.utils import delay, search
|
||||
from evennia.utils import delay, logger, search
|
||||
|
||||
from commands.lighting import CmdSetLight
|
||||
|
||||
class ObjectParent:
|
||||
"""
|
||||
|
|
@ -231,96 +232,27 @@ class Object(ObjectParent, DefaultObject):
|
|||
elif i == item:
|
||||
return i
|
||||
|
||||
# -------------------------------------------------------------
|
||||
#
|
||||
# LightSource
|
||||
#
|
||||
# This object emits light. Once it has been turned on it
|
||||
# cannot be turned off. When it burns out it will delete
|
||||
# itself.
|
||||
#
|
||||
# This could be implemented using a single-repeat Script or by
|
||||
# registering with the TickerHandler. We do it simpler by
|
||||
# using the delay() utility function. This is very simple
|
||||
# to use but does not survive a server @reload. Because of
|
||||
# where the light matters (in the Dark Room where you can
|
||||
# find new light sources easily), this is okay here.
|
||||
#
|
||||
# -------------------------------------------------------------
|
||||
|
||||
class LightSource(Object):
|
||||
"""
|
||||
This implements a light source object.
|
||||
|
||||
When burned out, the object will be deleted.
|
||||
"""
|
||||
|
||||
def at_init(self):
|
||||
def at_look(self, target, **kwargs):
|
||||
"""
|
||||
If this is called with the Attribute is_giving_light already
|
||||
set, we know that the timer got killed by a server
|
||||
reload/reboot before it had time to finish. So we kill it here
|
||||
instead. This is the price we pay for the simplicity of the
|
||||
non-persistent delay() method.
|
||||
"""
|
||||
if self.db.is_giving_light:
|
||||
self.delete()
|
||||
When we look at something that _might_ be hidden, we check
|
||||
if we are looking at something that _is_ hidden, i.e. has a
|
||||
view lock of a particular tag, and if so, we interpret this as
|
||||
'you are looking at something by name', therefore you see it.
|
||||
So we give ourselves the right to see it from now on.
|
||||
|
||||
def at_object_creation(self):
|
||||
"""Called when object is first created."""
|
||||
super().at_object_creation()
|
||||
To use this, simply add the following lock:
|
||||
|
||||
self.db.is_giving_light = False
|
||||
self.db.burntime = 60 * 3 # 3 minutes
|
||||
# this is the default desc, it can of course be customized
|
||||
# when created.
|
||||
self.db.desc = "A tapered candle."
|
||||
# add the Light command
|
||||
self.cmdset.add_default(CmdSetLight, persistent=True)
|
||||
@lock thing = view:tag(hidden_thing, mp)
|
||||
|
||||
def _burnout(self):
|
||||
Where thing is the single name of the hidden object.
|
||||
"""
|
||||
This is called when this light source burns out. We make no
|
||||
use of the return value.
|
||||
"""
|
||||
# delete ourselves from the database
|
||||
self.db.is_giving_light = False
|
||||
try:
|
||||
self.location.location.msg_contents(
|
||||
"%s's %s flickers and dies." % (self.location, self.key), exclude=self.location
|
||||
)
|
||||
self.location.msg("Your %s flickers and dies." % self.key)
|
||||
self.location.location.check_light_state()
|
||||
except AttributeError:
|
||||
try:
|
||||
self.location.msg_contents("A %s on the floor flickers and dies." % self.key)
|
||||
self.location.location.check_light_state()
|
||||
except AttributeError:
|
||||
# Mainly happens if we happen to be in a None location
|
||||
pass
|
||||
self.delete()
|
||||
hidden_tag = f"hidden_{target}"
|
||||
lock_string = f"view:tag({hidden_tag}, mp)"
|
||||
view_lock = target.locks.get("view")
|
||||
|
||||
def light(self):
|
||||
"""
|
||||
Light this object - this is called by Light command.
|
||||
"""
|
||||
if self.db.is_giving_light:
|
||||
return False
|
||||
# burn for 3 minutes before calling _burnout
|
||||
self.db.is_giving_light = True
|
||||
# if we are in a dark room, trigger its light check
|
||||
try:
|
||||
self.location.location.check_light_state()
|
||||
except AttributeError:
|
||||
try:
|
||||
# maybe we are directly in the room
|
||||
self.location.check_light_state()
|
||||
except AttributeError:
|
||||
# we are in a None location
|
||||
pass
|
||||
finally:
|
||||
# start the burn timer. When it runs out, self._burnout
|
||||
# will be called. We store the deferred so it can be
|
||||
# killed in unittesting.
|
||||
self.deferred = delay(60 * 3, self._burnout)
|
||||
return True
|
||||
if view_lock == lock_string:
|
||||
self.tags.add(hidden_tag, category="mp")
|
||||
|
||||
# Regardless of what happened before, we return the normal
|
||||
# function call.
|
||||
return super().at_look(target)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ Each level of pet requires more aspects for interaction.
|
|||
|
||||
"""
|
||||
|
||||
from typeclasses.objects import Object, LightSource
|
||||
from typeclasses.objects import Object
|
||||
# from typeclasses.lightables import LightSource
|
||||
from commands.feedables import CmdFeed, CmdFeedSet
|
||||
from utils.word_list import squish
|
||||
|
||||
|
|
@ -180,12 +181,12 @@ class Fire(Pet):
|
|||
gets_up = "gets up and"
|
||||
|
||||
if self.db.hunger_level < 5:
|
||||
feeder.msg(squish(f"You {get_up} put some {adj} wood in the "
|
||||
feeder.msg(squish(f"You {get_up} put {adj} wood in the "
|
||||
f"fireplace, and start a fire."))
|
||||
self.location.msg_contents(squish(f"{feeder.name} {gets_up} starts a fire."),
|
||||
exclude=feeder)
|
||||
else:
|
||||
feeder.msg(squish(f"You {get_up} put some {adj} wood on the "
|
||||
feeder.msg(squish(f"You {get_up} put {adj} wood on the "
|
||||
f"fire in the fireplace."))
|
||||
self.location.msg_contents(squish(f"{feeder.name} {gets_up} puts {adj} wood on the fire."),
|
||||
exclude=feeder)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from evennia.objects.objects import DefaultRoom
|
|||
from evennia.contrib.grid.extended_room import ExtendedRoom
|
||||
from evennia.prototypes.spawner import spawn
|
||||
|
||||
from .objects import LightSource
|
||||
# from .objects import LightSource
|
||||
from .drinkables import TEACUP_DESCS
|
||||
from .pets import Hunger
|
||||
from commands.drinkables import CmdSetTrolley
|
||||
|
|
@ -35,7 +35,6 @@ from evennia import (
|
|||
utils,
|
||||
)
|
||||
|
||||
# from .objects import LightSource
|
||||
|
||||
_SEARCH_AT_RESULT = utils.object_from_module(settings.SEARCH_AT_RESULT)
|
||||
from .objects import ObjectParent
|
||||
|
|
@ -54,242 +53,6 @@ class Room(ObjectParent, ExtendedRoom):
|
|||
is_dark = False
|
||||
has_weather = False
|
||||
|
||||
pass
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
#
|
||||
# Dark Room - a room with states
|
||||
#
|
||||
# This room limits the movemenets of its denizens unless they carry an active
|
||||
# LightSource object (LightSource is defined in objects.LightSource)
|
||||
#
|
||||
# -------------------------------------------------------------------------------
|
||||
|
||||
|
||||
DARK_MESSAGES = (
|
||||
"It is pitch black. You are likely to be eaten by a grue.",
|
||||
"It's pitch black. You fumble around but cannot find anything.",
|
||||
"You don't see a thing. You feel around, managing to bump your fingers hard against something. Ouch!",
|
||||
"You don't see a thing! Blindly grasping the air around you, you find nothing.",
|
||||
"It's totally dark here. You almost stumble over something on the floor.",
|
||||
"You are completely blind. For a moment you think you hear someone breathing nearby ... "
|
||||
"\n ... surely you must be mistaken.",
|
||||
)
|
||||
|
||||
ALREADY_LIGHTSOURCE = (
|
||||
"You don't want to stumble around in blindness anymore. You already "
|
||||
"found what you need. Let's get the fireplace lit already!"
|
||||
)
|
||||
|
||||
FOUND_LIGHTSOURCE = (
|
||||
"Your fingers bump against a candle on a candleabra."
|
||||
"You pick it up, holding it firmly. Now you just need to"
|
||||
" |wlight|n it using the flint and steel you carry with you."
|
||||
)
|
||||
|
||||
|
||||
class CmdLookDark(Command):
|
||||
"""
|
||||
Look around in darkness
|
||||
|
||||
Usage:
|
||||
look
|
||||
|
||||
Look around in the darkness, trying
|
||||
to find something.
|
||||
"""
|
||||
|
||||
key = "look"
|
||||
aliases = ["l", "feel", "search", "feel around", "fiddle"]
|
||||
locks = "cmd:all()"
|
||||
|
||||
def func(self):
|
||||
"""
|
||||
Implement the command.
|
||||
|
||||
This works both as a look and a search command; there is a
|
||||
random chance of eventually finding a light source.
|
||||
"""
|
||||
caller = self.caller
|
||||
|
||||
# count how many searches we've done
|
||||
nr_searches = caller.ndb.dark_searches
|
||||
if nr_searches is None:
|
||||
nr_searches = 0
|
||||
caller.ndb.dark_searches = nr_searches
|
||||
|
||||
if nr_searches < 4 and random.random() < 0.90:
|
||||
# we don't find anything
|
||||
caller.msg(random.choice(DARK_MESSAGES))
|
||||
caller.ndb.dark_searches += 1
|
||||
else:
|
||||
# we could have found something!
|
||||
if any(obj for obj in caller.contents if utils.inherits_from(obj, LightSource)):
|
||||
# we already carry a LightSource object.
|
||||
caller.msg(ALREADY_LIGHTSOURCE)
|
||||
else:
|
||||
# don't have a light source, create a new one.
|
||||
create_object(LightSource, key="candle", location=caller)
|
||||
caller.msg(FOUND_LIGHTSOURCE)
|
||||
|
||||
|
||||
class CmdDarkHelp(Command):
|
||||
"""
|
||||
Help command for the dark state.
|
||||
"""
|
||||
key = "help"
|
||||
locks = "cmd:all()"
|
||||
|
||||
def func(self):
|
||||
"""
|
||||
Replace the the help command with a not-so-useful help
|
||||
"""
|
||||
string = (
|
||||
"Can't help you until you find some light! Try looking/feeling around for something to burn. "
|
||||
"You shouldn't give up even if you don't find anything right away."
|
||||
)
|
||||
self.caller.msg(string)
|
||||
|
||||
|
||||
class CmdDarkNoMatch(Command):
|
||||
"""
|
||||
This is a system command. Commands with special keys are used to
|
||||
override special sitations in the game. The CMD_NOMATCH is used
|
||||
when the given command is not found in the current command set (it
|
||||
replaces Evennia's default behavior or offering command
|
||||
suggestions)
|
||||
"""
|
||||
|
||||
key = syscmdkeys.CMD_NOMATCH
|
||||
locks = "cmd:all()"
|
||||
|
||||
def func(self):
|
||||
"""Implements the command."""
|
||||
self.caller.msg(
|
||||
"Until you find some light, there's not much you can do. "
|
||||
"Try feeling around, maybe you'll find something helpful!"
|
||||
)
|
||||
|
||||
|
||||
class DarkCmdSet(CmdSet):
|
||||
"""
|
||||
Groups the commands of the dark room together. We also import the
|
||||
default say command here so that players can still talk in the
|
||||
darkness.
|
||||
|
||||
We give the cmdset the mergetype "Replace" to make sure it
|
||||
completely replaces whichever command set it is merged onto
|
||||
(usually the default cmdset)
|
||||
"""
|
||||
|
||||
key = "darkroom_cmdset"
|
||||
mergetype = "Replace"
|
||||
priority = 2
|
||||
|
||||
def at_cmdset_creation(self):
|
||||
"""populate the cmdset."""
|
||||
self.add(CmdLookDark())
|
||||
self.add(CmdDarkHelp())
|
||||
self.add(CmdDarkNoMatch())
|
||||
self.add(default_cmds.CmdSay())
|
||||
self.add(default_cmds.CmdQuit())
|
||||
self.add(default_cmds.CmdHome())
|
||||
|
||||
|
||||
class DarkRoom(Room):
|
||||
"""A dark room. This tries to start the DarkState script on all
|
||||
objects entering. The script is responsible for making sure it is
|
||||
valid (that is, that there is no light source shining in the room).
|
||||
|
||||
The is_lit Attribute is used to define if the room is currently lit
|
||||
or not, so as to properly echo state changes.
|
||||
|
||||
Since this room is meant as a sort of catch-all, we also make sure
|
||||
to heal characters ending up here.
|
||||
|
||||
"""
|
||||
|
||||
def at_object_creation(self):
|
||||
"""
|
||||
Called when object is first created.
|
||||
"""
|
||||
super().at_object_creation()
|
||||
# the room starts dark.
|
||||
self.db.is_lit = False
|
||||
self.cmdset.add(DarkCmdSet, persistent=True)
|
||||
|
||||
def at_init(self):
|
||||
"""
|
||||
Called when room is first recached (such as after a reload)
|
||||
"""
|
||||
self.check_light_state()
|
||||
|
||||
def _carries_light(self, obj):
|
||||
"""
|
||||
Checks if the given object carries anything that gives light.
|
||||
|
||||
Note that we do NOT look for a specific LightSource typeclass,
|
||||
but for the Attribute is_giving_light - this makes it easy to
|
||||
later add other types of light-giving items. We also accept
|
||||
if there is a light-giving object in the room overall (like if
|
||||
a candle was dropped in the room or the fireplace is lit).
|
||||
"""
|
||||
return (
|
||||
obj.is_superuser
|
||||
or obj.db.is_giving_light
|
||||
or any(o for o in obj.contents if o.db.is_giving_light)
|
||||
)
|
||||
|
||||
def check_light_state(self, exclude=None):
|
||||
"""
|
||||
This method checks if there are any light sources in the room.
|
||||
If there isn't it makes sure to add the dark cmdset to all
|
||||
characters in the room. It is called whenever characters enter
|
||||
the room and also by the Light sources when they turn on.
|
||||
|
||||
Args:
|
||||
exclude (Object): An object to not include in the light check.
|
||||
"""
|
||||
if any(self._carries_light(obj) for obj in self.contents if obj != exclude):
|
||||
self.locks.add("view:all()")
|
||||
self.cmdset.remove(DarkCmdSet)
|
||||
self.db.is_lit = True
|
||||
for char in (obj for obj in self.contents if obj.has_account):
|
||||
# this won't do anything if it is already removed
|
||||
char.msg("The room is lit up.")
|
||||
else:
|
||||
# noone is carrying light - darken the room
|
||||
self.db.is_lit = False
|
||||
self.locks.add("view:false()")
|
||||
self.cmdset.add(DarkCmdSet, persistent=True)
|
||||
for char in (obj for obj in self.contents if obj.has_account):
|
||||
if char.is_superuser:
|
||||
char.msg("You are Superuser, so you are not affected by the dark state.")
|
||||
else:
|
||||
# put players in darkness
|
||||
char.msg("The room is completely dark.")
|
||||
|
||||
def at_object_receive(self, obj, source_location, move_type="move", **kwargs):
|
||||
"""
|
||||
Called when an object enters the room.
|
||||
"""
|
||||
if obj.has_account:
|
||||
# a puppeted object, that is, a Character
|
||||
self._heal(obj)
|
||||
# in case the new guy carries light with them
|
||||
self.check_light_state()
|
||||
|
||||
def at_object_leave(self, obj, target_location, move_type="move", **kwargs):
|
||||
"""
|
||||
In case people leave with the light, we make sure to clear the
|
||||
DarkCmdSet if necessary. This also works if they are
|
||||
teleported away.
|
||||
"""
|
||||
# since this hook is called while the object is still in the room,
|
||||
# we exclude it from the light check, to ignore any light sources
|
||||
# it may be carrying.
|
||||
self.check_light_state(exclude=obj)
|
||||
|
||||
|
||||
class DabblersRoom(Room):
|
||||
teacup_prototype = {
|
||||
|
|
|
|||
235
typeclasses/rooms_dark.py
Executable file
235
typeclasses/rooms_dark.py
Executable file
|
|
@ -0,0 +1,235 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
#
|
||||
# Dark Room - a room with states
|
||||
#
|
||||
# This room limits the movemenets of its denizens unless they carry an active
|
||||
# LightSource object (LightSource is defined in objects.LightSource)
|
||||
#
|
||||
# -------------------------------------------------------------------------------
|
||||
|
||||
|
||||
DARK_MESSAGES = (
|
||||
"It is pitch black. You are likely to be eaten by a grue.",
|
||||
"It's pitch black. You fumble around but cannot find anything.",
|
||||
"You don't see a thing. You feel around, managing to bump your fingers hard against something. Ouch!",
|
||||
"You don't see a thing! Blindly grasping the air around you, you find nothing.",
|
||||
"It's totally dark here. You almost stumble over something on the floor.",
|
||||
"You are completely blind. For a moment you think you hear someone breathing nearby ... "
|
||||
"\n ... surely you must be mistaken.",
|
||||
)
|
||||
|
||||
ALREADY_LIGHTSOURCE = (
|
||||
"You don't want to stumble around in blindness anymore. You already "
|
||||
"found what you need. Let's get the fireplace lit already!"
|
||||
)
|
||||
|
||||
FOUND_LIGHTSOURCE = (
|
||||
"Your fingers bump against a candle on a candleabra."
|
||||
"You pick it up, holding it firmly. Now you just need to"
|
||||
" |wlight|n it using the flint and steel you carry with you."
|
||||
)
|
||||
|
||||
|
||||
class CmdLookDark(Command):
|
||||
"""
|
||||
Look around in darkness
|
||||
|
||||
Usage:
|
||||
look
|
||||
|
||||
Look around in the darkness, trying
|
||||
to find something.
|
||||
"""
|
||||
|
||||
key = "look"
|
||||
aliases = ["l", "feel", "search", "feel around", "fiddle"]
|
||||
locks = "cmd:all()"
|
||||
|
||||
def func(self):
|
||||
"""
|
||||
Implement the command.
|
||||
|
||||
This works both as a look and a search command; there is a
|
||||
random chance of eventually finding a light source.
|
||||
"""
|
||||
caller = self.caller
|
||||
|
||||
# count how many searches we've done
|
||||
nr_searches = caller.ndb.dark_searches
|
||||
if nr_searches is None:
|
||||
nr_searches = 0
|
||||
caller.ndb.dark_searches = nr_searches
|
||||
|
||||
if nr_searches < 4 and random.random() < 0.90:
|
||||
# we don't find anything
|
||||
caller.msg(random.choice(DARK_MESSAGES))
|
||||
caller.ndb.dark_searches += 1
|
||||
else:
|
||||
# we could have found something!
|
||||
if any(obj for obj in caller.contents if utils.inherits_from(obj, LightSource)):
|
||||
# we already carry a LightSource object.
|
||||
caller.msg(ALREADY_LIGHTSOURCE)
|
||||
else:
|
||||
# don't have a light source, create a new one.
|
||||
create_object(LightSource, key="candle", location=caller)
|
||||
caller.msg(FOUND_LIGHTSOURCE)
|
||||
|
||||
|
||||
class CmdDarkHelp(Command):
|
||||
"""
|
||||
Help command for the dark state.
|
||||
"""
|
||||
key = "help"
|
||||
locks = "cmd:all()"
|
||||
|
||||
def func(self):
|
||||
"""
|
||||
Replace the the help command with a not-so-useful help
|
||||
"""
|
||||
string = (
|
||||
"Can't help you until you find some light! Try looking/feeling around for something to burn. "
|
||||
"You shouldn't give up even if you don't find anything right away."
|
||||
)
|
||||
self.caller.msg(string)
|
||||
|
||||
|
||||
class CmdDarkNoMatch(Command):
|
||||
"""
|
||||
This is a system command. Commands with special keys are used to
|
||||
override special sitations in the game. The CMD_NOMATCH is used
|
||||
when the given command is not found in the current command set (it
|
||||
replaces Evennia's default behavior or offering command
|
||||
suggestions)
|
||||
"""
|
||||
|
||||
key = syscmdkeys.CMD_NOMATCH
|
||||
locks = "cmd:all()"
|
||||
|
||||
def func(self):
|
||||
"""Implements the command."""
|
||||
self.caller.msg(
|
||||
"Until you find some light, there's not much you can do. "
|
||||
"Try feeling around, maybe you'll find something helpful!"
|
||||
)
|
||||
|
||||
|
||||
class DarkCmdSet(CmdSet):
|
||||
"""
|
||||
Groups the commands of the dark room together. We also import the
|
||||
default say command here so that players can still talk in the
|
||||
darkness.
|
||||
|
||||
We give the cmdset the mergetype "Replace" to make sure it
|
||||
completely replaces whichever command set it is merged onto
|
||||
(usually the default cmdset)
|
||||
"""
|
||||
|
||||
key = "darkroom_cmdset"
|
||||
mergetype = "Replace"
|
||||
priority = 2
|
||||
|
||||
def at_cmdset_creation(self):
|
||||
"""populate the cmdset."""
|
||||
self.add(CmdLookDark())
|
||||
self.add(CmdDarkHelp())
|
||||
self.add(CmdDarkNoMatch())
|
||||
self.add(default_cmds.CmdSay())
|
||||
self.add(default_cmds.CmdQuit())
|
||||
self.add(default_cmds.CmdHome())
|
||||
|
||||
|
||||
class DarkRoom(Room):
|
||||
"""A dark room. This tries to start the DarkState script on all
|
||||
objects entering. The script is responsible for making sure it is
|
||||
valid (that is, that there is no light source shining in the room).
|
||||
|
||||
The is_lit Attribute is used to define if the room is currently lit
|
||||
or not, so as to properly echo state changes.
|
||||
|
||||
Since this room is meant as a sort of catch-all, we also make sure
|
||||
to heal characters ending up here.
|
||||
|
||||
"""
|
||||
|
||||
def at_object_creation(self):
|
||||
"""
|
||||
Called when object is first created.
|
||||
"""
|
||||
super().at_object_creation()
|
||||
# the room starts dark.
|
||||
self.db.is_lit = False
|
||||
self.cmdset.add(DarkCmdSet, persistent=True)
|
||||
|
||||
def at_init(self):
|
||||
"""
|
||||
Called when room is first recached (such as after a reload)
|
||||
"""
|
||||
self.check_light_state()
|
||||
|
||||
def _carries_light(self, obj):
|
||||
"""
|
||||
Checks if the given object carries anything that gives light.
|
||||
|
||||
Note that we do NOT look for a specific LightSource typeclass,
|
||||
but for the Attribute is_giving_light - this makes it easy to
|
||||
later add other types of light-giving items. We also accept
|
||||
if there is a light-giving object in the room overall (like if
|
||||
a candle was dropped in the room or the fireplace is lit).
|
||||
"""
|
||||
return (
|
||||
obj.is_superuser
|
||||
or obj.db.is_giving_light
|
||||
or any(o for o in obj.contents if o.db.is_giving_light)
|
||||
)
|
||||
|
||||
def check_light_state(self, exclude=None):
|
||||
"""
|
||||
This method checks if there are any light sources in the room.
|
||||
If there isn't it makes sure to add the dark cmdset to all
|
||||
characters in the room. It is called whenever characters enter
|
||||
the room and also by the Light sources when they turn on.
|
||||
|
||||
Args:
|
||||
exclude (Object): An object to not include in the light check.
|
||||
"""
|
||||
if any(self._carries_light(obj) for obj in self.contents if obj != exclude):
|
||||
self.locks.add("view:all()")
|
||||
self.cmdset.remove(DarkCmdSet)
|
||||
self.db.is_lit = True
|
||||
for char in (obj for obj in self.contents if obj.has_account):
|
||||
# this won't do anything if it is already removed
|
||||
char.msg("The room is lit up.")
|
||||
else:
|
||||
# noone is carrying light - darken the room
|
||||
self.db.is_lit = False
|
||||
self.locks.add("view:false()")
|
||||
self.cmdset.add(DarkCmdSet, persistent=True)
|
||||
for char in (obj for obj in self.contents if obj.has_account):
|
||||
if char.is_superuser:
|
||||
char.msg("You are Superuser, so you are not affected by the dark state.")
|
||||
else:
|
||||
# put players in darkness
|
||||
char.msg("The room is completely dark.")
|
||||
|
||||
def at_object_receive(self, obj, source_location, move_type="move", **kwargs):
|
||||
"""
|
||||
Called when an object enters the room.
|
||||
"""
|
||||
if obj.has_account:
|
||||
# a puppeted object, that is, a Character
|
||||
self._heal(obj)
|
||||
# in case the new guy carries light with them
|
||||
self.check_light_state()
|
||||
|
||||
def at_object_leave(self, obj, target_location, move_type="move", **kwargs):
|
||||
"""
|
||||
In case people leave with the light, we make sure to clear the
|
||||
DarkCmdSet if necessary. This also works if they are
|
||||
teleported away.
|
||||
"""
|
||||
# since this hook is called while the object is still in the room,
|
||||
# we exclude it from the light check, to ignore any light sources
|
||||
# it may be carrying.
|
||||
self.check_light_state(exclude=obj)
|
||||
|
|
@ -69,6 +69,8 @@ class Sittables(Sittable):
|
|||
multiple = True
|
||||
|
||||
def sit_msg(self):
|
||||
aliases = self.aliases.all()
|
||||
|
||||
adjective = self.db.adjective or "on"
|
||||
article = self.db.article or "the"
|
||||
name = aliases[-1] # Last alias is singular
|
||||
|
|
@ -76,8 +78,6 @@ class Sittables(Sittable):
|
|||
singular = self.db.singular or default
|
||||
extra = self.db.extra or ""
|
||||
|
||||
aliases = self.aliases.all()
|
||||
|
||||
return routput(f"You sit {adjective} {singular}. {extra}")
|
||||
|
||||
def stand_msg(self):
|
||||
|
|
|
|||
|
|
@ -20,6 +20,12 @@ from random import choice, random
|
|||
import re
|
||||
|
||||
|
||||
class Unhider(Object):
|
||||
"""
|
||||
This thing has the ability to "unhide" other things.
|
||||
The idea is .... ugh.
|
||||
@set thing/
|
||||
"""
|
||||
class Returnable(Object):
|
||||
"""
|
||||
This object can't go far from one or two locations.
|
||||
|
|
|
|||
884
world/version1.ev
Normal file
884
world/version1.ev
Normal file
|
|
@ -0,0 +1,884 @@
|
|||
# [[file:../../../projects/mud.org::*Shell][Shell:4]]
|
||||
# # -*- mode:ruby; -*-
|
||||
# Shell:4 ends here
|
||||
|
||||
|
||||
# Can I rename myself?
|
||||
|
||||
|
||||
# [[file:../../../projects/mud.org::*Character: Dabble][Character: Dabble:1]]
|
||||
@name self = Dabbler;gnome;old gnome
|
||||
# Character: Dabble:1 ends here
|
||||
|
||||
|
||||
|
||||
# And a good description that I can rework:
|
||||
|
||||
|
||||
# [[file:../../../projects/mud.org::*Character: Dabble][Character: Dabble:2]]
|
||||
@desc self = A small, hunched old man with a gray vandyke and an eye
|
||||
twinkle. Spectacles perched precariously on the end of his hooked
|
||||
nose, wobble with his head. A jaunty crimson cap contrasts with his
|
||||
dark brown cloak.
|
||||
# Character: Dabble:2 ends here
|
||||
|
||||
|
||||
# Rename the Limbo (or starting place) with the name *Forest*. Note the term =mp01= as a global label that matches my map.
|
||||
|
||||
|
||||
# [[file:../../../projects/mud.org::*The Forest][The Forest:1]]
|
||||
@name here = The Forest;mp01
|
||||
# The Forest:1 ends here
|
||||
|
||||
|
||||
|
||||
# The description will take advantage of the /seasons/ and /times/ of the day:
|
||||
|
||||
|
||||
# [[file:../../../projects/mud.org::*The Forest][The Forest:2]]
|
||||
@desc here = A giant, moss-covered boulder stands among immense trees
|
||||
that etch the sky and slice the clouds in the <evening>darkening
|
||||
twilight</evening><morning>awakening dawn</morning><afternoon>lazy
|
||||
afternoon</afternoon><night>night sky</night>. A footpath winds around
|
||||
the giant, moss-covered tree roots to the East and West. To the south,
|
||||
a dock lounges on a large pond.
|
||||
# The Forest:2 ends here
|
||||
|
||||
|
||||
|
||||
# Need to add weather and time data to this:
|
||||
|
||||
# [[file:../../../projects/mud.org::*The Forest][The Forest:3]]
|
||||
# from evennia.contrib.tutorials.tutorial_world.rooms import WeatherRoom
|
||||
@update here = typeclasses.rooms_weather.TimeWeatherRoom
|
||||
# The Forest:3 ends here
|
||||
|
||||
|
||||
# More details about the room that describes aspects of the boulder in the =desc= above. First, the symbol:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Boulder][Boulder:1]]
|
||||
@detail symbol = You move an ivy runner to see three curves join
|
||||
together as if it were three legs.
|
||||
# Boulder:1 ends here
|
||||
|
||||
|
||||
|
||||
# The moss is purdy:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Boulder][Boulder:2]]
|
||||
@detail moss = "Even in this light, the moss radiates a surreal color of green."
|
||||
# Boulder:2 ends here
|
||||
|
||||
|
||||
|
||||
# And the ivy is … uh.
|
||||
|
||||
# [[file:../../../projects/mud.org::*Boulder][Boulder:3]]
|
||||
@detail ivy = "You see...well, ivy. Uhm, it's green, and..."
|
||||
# Boulder:3 ends here
|
||||
|
||||
|
||||
|
||||
# The runes use multibyte unicode which screws up the =telnet= client.
|
||||
|
||||
# [[file:../../../projects/mud.org::*Boulder][Boulder:4]]
|
||||
@detail runes = "The runes read ᛞ ᚪ ᛒ ᛚ ᚱ"
|
||||
# Boulder:4 ends here
|
||||
|
||||
|
||||
|
||||
# The top of the boulder should be another room, accessible by the =climb=, but maybe it isn’t “seen” until the boulder has been looked? First, we put some weather at the top of the boulder:
|
||||
|
||||
|
||||
# [[file:../../../projects/mud.org::*Boulder][Boulder:5]]
|
||||
@dig Top of Boulder;mp02 : typeclasses.rooms_weather.TimeWeatherRoom = boulder,climb
|
||||
# Boulder:5 ends here
|
||||
|
||||
|
||||
|
||||
# The ability to /climb/ the boulder isn’t immediately obvious, so let’s make it a bit of a secret:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Boulder][Boulder:6]]
|
||||
@desc boulder = A boulder with patches of moss and delicate clover.
|
||||
A carved symbol and even some runes try to hide behind tendrils of ivy
|
||||
as if keeping a secret. Wait! You notice a foot hold, and then
|
||||
another. You can |bclimb|n this boulder!
|
||||
# Boulder:6 ends here
|
||||
|
||||
|
||||
|
||||
# To take advantage of our [[Hidden Things]], we put the right tag on it:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Boulder][Boulder:7]]
|
||||
@lock boulder = view:tag(hidden_boulder, mp)
|
||||
# Boulder:7 ends here
|
||||
|
||||
|
||||
|
||||
# And give it some aliases:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Boulder][Boulder:8]]
|
||||
@name boulder = boulder;climb;climb up
|
||||
# Boulder:8 ends here
|
||||
|
||||
# [[file:../../../projects/mud.org::*Boulder][Boulder:9]]
|
||||
@set boulder/traverse_msg = "You move some ivy out of the way and pick your way up the boulder from one hold to another..."
|
||||
# Boulder:9 ends here
|
||||
|
||||
|
||||
|
||||
# Let’s jump to the top of the boulder to proceed:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Top of Boulder][Top of Boulder:1]]
|
||||
@teleport mp02
|
||||
# @name here = Top of Boulder;mp02
|
||||
# Top of Boulder:1 ends here
|
||||
|
||||
|
||||
|
||||
# And the description:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Top of Boulder][Top of Boulder:2]]
|
||||
@desc here = While high, the trees still tower over you. Still, a nice view. Lots of patches of moss to sit down and relax.
|
||||
# Top of Boulder:2 ends here
|
||||
|
||||
|
||||
|
||||
# Describe the climb down:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Top of Boulder][Top of Boulder:3]]
|
||||
@name climb = climb back down;climb down;climb;down
|
||||
# Top of Boulder:3 ends here
|
||||
|
||||
|
||||
# And a description of the climb:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Top of Boulder][Top of Boulder:4]]
|
||||
@desc climb = The climb seemed easy, but you're not sure you can
|
||||
handle the footholds going the other way around.
|
||||
# Top of Boulder:4 ends here
|
||||
|
||||
|
||||
# And describe the journey:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Top of Boulder][Top of Boulder:5]]
|
||||
@set climb/traverse_msg = "You crawl backwards, feeling with your foot for a hold. Got it! Then another one...hoping the moss' rhizoids hold..."
|
||||
# Top of Boulder:5 ends here
|
||||
|
||||
|
||||
|
||||
# Let’s make a nice spot to sit down on:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Top of Boulder][Top of Boulder:6]]
|
||||
@create/drop moss;patch:typeclasses.sittables.Sittable
|
||||
# Top of Boulder:6 ends here
|
||||
|
||||
|
||||
# With a nice description:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Top of Boulder][Top of Boulder:7]]
|
||||
@desc moss = A cushioned patch of moss of the most vibrant green.
|
||||
# Top of Boulder:7 ends here
|
||||
|
||||
|
||||
# Can’t take the moss with you:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Top of Boulder][Top of Boulder:8]]
|
||||
@lock moss = get:false()
|
||||
# Top of Boulder:8 ends here
|
||||
|
||||
|
||||
# Can we hide it too?
|
||||
|
||||
# [[file:../../../projects/mud.org::*Top of Boulder][Top of Boulder:9]]
|
||||
@lock moss = view:tag(hidden_moss, mp)
|
||||
# Top of Boulder:9 ends here
|
||||
|
||||
|
||||
# And a lovely message about why you can’t steal moss:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Top of Boulder][Top of Boulder:10]]
|
||||
@set moss/get_err_msg = The moss is a bryophyte, and as such, has
|
||||
attached itself to boulder by rhizoids, which are one cell thick root
|
||||
structures. While this helps with water absorption, you didn't think
|
||||
you were going to get a biology lesson, did you? tl;dr You can't get it.
|
||||
# Top of Boulder:10 ends here
|
||||
|
||||
|
||||
# To the east, let’s make a nice meadow. Start at the Forest:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Field][Field:1]]
|
||||
@teleport mp01
|
||||
# Field:1 ends here
|
||||
|
||||
|
||||
|
||||
# And we use the =tunnel= command this time:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Field][Field:2]]
|
||||
@tunnel e = path
|
||||
# Field:2 ends here
|
||||
|
||||
|
||||
# And a nice journey message to go east out of the forest:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Field][Field:3]]
|
||||
@set east/traverse_msg = "The mossy tree roots that borders this
|
||||
footpath begin to thin out to clover and flowers..."
|
||||
# Field:3 ends here
|
||||
|
||||
|
||||
|
||||
# Before we label it, we follow =east=:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Field][Field:4]]
|
||||
east
|
||||
# Field:4 ends here
|
||||
|
||||
|
||||
|
||||
# And we give this area a name:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Field][Field:5]]
|
||||
@name here = Meadow;mp05
|
||||
# Field:5 ends here
|
||||
|
||||
|
||||
|
||||
# And a description that takes advantage of the time of day. We should get busy and get some seasonal description here.
|
||||
|
||||
|
||||
# [[file:../../../projects/mud.org::*Field][Field:6]]
|
||||
@desc here = The giant trees ring this meadow full of tall grass and
|
||||
large yellow flowers, who nod their heads to you as you pass by in the
|
||||
<evening>darkening twilight</evening><morning>awakening
|
||||
dawn</morning><afternoon>lazy afternoon</afternoon><night>night
|
||||
sky</night>. A gap in the trees show how you can return to the
|
||||
footpath in the forest.
|
||||
# Field:6 ends here
|
||||
|
||||
|
||||
|
||||
# Since we use the =tunnel= command, we need to update the weather system:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Field][Field:7]]
|
||||
@update here = typeclasses.rooms_weather.TimeWeatherRoom
|
||||
# Field:7 ends here
|
||||
|
||||
|
||||
# And describe the way out:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Field][Field:8]]
|
||||
@name west = footpath;forest;west
|
||||
# Field:8 ends here
|
||||
|
||||
|
||||
# Along with a mesage:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Field][Field:9]]
|
||||
@set footpath/traverse_msg = "You leave the open meadow for the footpath through the giant trees. The yellow flowers nod goodbye to you..."
|
||||
# Field:9 ends here
|
||||
|
||||
|
||||
# The dock leads out into the large pond. The break in the trees lets you see the sky. Looks like a nice place to relax.
|
||||
|
||||
# Return to the Forest:
|
||||
|
||||
# [[file:../../../projects/mud.org::*The Dock][The Dock:1]]
|
||||
@teleport mp01
|
||||
# The Dock:1 ends here
|
||||
|
||||
|
||||
# And tunnel to the pond:
|
||||
|
||||
# [[file:../../../projects/mud.org::*The Dock][The Dock:2]]
|
||||
@tunnel s = dock
|
||||
# The Dock:2 ends here
|
||||
|
||||
|
||||
# With a mesage about leaving the trees so that I don’t have to repeat that in the room description:
|
||||
|
||||
# [[file:../../../projects/mud.org::*The Dock][The Dock:3]]
|
||||
@set south/traverse_msg = "You follow a path down and step out from under giant trees to see the sky."
|
||||
# The Dock:3 ends here
|
||||
|
||||
|
||||
# And move ourselves there:
|
||||
|
||||
# [[file:../../../projects/mud.org::*The Dock][The Dock:4]]
|
||||
south
|
||||
# The Dock:4 ends here
|
||||
|
||||
|
||||
|
||||
# Since we are on a dock in the pond, we’ll emphasize that:
|
||||
|
||||
# [[file:../../../projects/mud.org::*The Dock][The Dock:5]]
|
||||
@name here = Lazy Dock;mp06
|
||||
# The Dock:5 ends here
|
||||
|
||||
|
||||
# And describe this.
|
||||
|
||||
# [[file:../../../projects/mud.org::*The Dock][The Dock:6]]
|
||||
@desc here = The dock you stand on juts into an immense pond. Someone has set a nice chair for viewing.
|
||||
# The Dock:6 ends here
|
||||
|
||||
|
||||
|
||||
# And describe the walk back into the forest:
|
||||
|
||||
# [[file:../../../projects/mud.org::*The Dock][The Dock:7]]
|
||||
@set north/traverse_msg = "You walk up a path and back into the forest of giant trees."
|
||||
# The Dock:7 ends here
|
||||
|
||||
|
||||
# A nice chair to sit on the dock by the bay, watching the clouds as they drift away.
|
||||
|
||||
# [[file:../../../projects/mud.org::*Chair][Chair:1]]
|
||||
@create/drop chair;lounge chair:typeclasses.sittables.Sittable
|
||||
# Chair:1 ends here
|
||||
|
||||
|
||||
|
||||
# How descriptive:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Chair][Chair:2]]
|
||||
@desc chair = A cushioned wood chair of craftsmanship.
|
||||
Looks good for being out in the weather.
|
||||
# Chair:2 ends here
|
||||
|
||||
|
||||
|
||||
# Can’t steal this chair either:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Chair][Chair:3]]
|
||||
@lock chair = get:false()
|
||||
# Chair:3 ends here
|
||||
|
||||
# [[file:../../../projects/mud.org::*Chair][Chair:4]]
|
||||
@set chair/get_err_msg = "It's way too heavy for you to lift."
|
||||
# Chair:4 ends here
|
||||
|
||||
|
||||
# And a fishing pole?
|
||||
|
||||
# First we need to make a =PermanentObject= (from the regular =Object=), but one that offers a
|
||||
|
||||
|
||||
# [[file:../../../projects/mud.org::*Fishing Pole][Fishing Pole:1]]
|
||||
@create/drop fishing pole;pole:typeclasses.things.FishingPole
|
||||
@desc pole = A nice pole for catching fish. It even has a hook.
|
||||
@detail hook = One of those shiny lures, made from gold coins. Curiouser.
|
||||
@detail water = Despite the weather, the water looks fine. Perhaps there is a hole
|
||||
# Fishing Pole:1 ends here
|
||||
|
||||
|
||||
|
||||
# Return to the forest:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Forest Path][Forest Path:1]]
|
||||
@teleport mp01
|
||||
# Forest Path:1 ends here
|
||||
|
||||
|
||||
# Let’s travel west along the path in the forest:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Forest Path][Forest Path:2]]
|
||||
@tunnel w = path
|
||||
# Forest Path:2 ends here
|
||||
|
||||
|
||||
# With a nice message about wandering:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Forest Path][Forest Path:3]]
|
||||
@set west/traverse_msg = "You meander between mossy tree roots along a
|
||||
footpath for a while..."
|
||||
# Forest Path:3 ends here
|
||||
|
||||
|
||||
# And some aliases:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Forest Path][Forest Path:4]]
|
||||
@name west = west;w;footpath
|
||||
# Forest Path:4 ends here
|
||||
|
||||
|
||||
|
||||
# Jump into the new room:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Forest Path][Forest Path:5]]
|
||||
west
|
||||
# Forest Path:5 ends here
|
||||
|
||||
|
||||
# And name it:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Forest Path][Forest Path:6]]
|
||||
@name here = Forest Path;mp04
|
||||
# Forest Path:6 ends here
|
||||
|
||||
|
||||
|
||||
# And describe the tree and the door:
|
||||
|
||||
|
||||
# [[file:../../../projects/mud.org::*Forest Path][Forest Path:7]]
|
||||
@desc here = Moss-covered tree roots border the meandering footpath. A
|
||||
red door with a round top lies at the base of a giant tree, a carved
|
||||
sign over it reads, Dabblers.
|
||||
# Forest Path:7 ends here
|
||||
|
||||
|
||||
# The knocker has the ability to make the door “open” using [[https://www.evennia.com/docs/latest/api/evennia.objects.objects.html][on_traverse]] hooks?
|
||||
|
||||
# Most of the work of the /knocker/ is in the Python code:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Knocker][Knocker:1]]
|
||||
@create/drop knocker:typeclasses.things.Knocker
|
||||
# Knocker:1 ends here
|
||||
|
||||
|
||||
# If it /looks/ like a goblin…
|
||||
|
||||
# [[file:../../../projects/mud.org::*Knocker][Knocker:2]]
|
||||
@name knocker = door knocker;knocker;goblin
|
||||
# Knocker:2 ends here
|
||||
|
||||
|
||||
|
||||
# The knocker shouldn’t be stealable:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Knocker][Knocker:3]]
|
||||
@lock knocker = get:false()
|
||||
#
|
||||
@set knocker/get_err_msg = "It appears firmly attached to the door."
|
||||
# Knocker:3 ends here
|
||||
|
||||
|
||||
|
||||
# Since we can remove the ring, let’s create it:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Knocker][Knocker:4]]
|
||||
@create ring = typeclasses.things.Returnable
|
||||
# Knocker:4 ends here
|
||||
|
||||
|
||||
|
||||
# And give it an alias:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Knocker][Knocker:5]]
|
||||
@name ring = brass ring;ring
|
||||
# Knocker:5 ends here
|
||||
|
||||
|
||||
|
||||
# And a description:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Knocker][Knocker:6]]
|
||||
@desc ring = "A brass ring that should be in the door knocker's mouth.
|
||||
How else are you going to knock on a door?"
|
||||
# Knocker:6 ends here
|
||||
|
||||
|
||||
|
||||
# Although we can interact with it, let’s not make it obvious that it is an object:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Knocker][Knocker:7]]
|
||||
@lock ring = view:tag(hidden_ring, mp)
|
||||
# Knocker:7 ends here
|
||||
|
||||
|
||||
|
||||
# And put the ring in the knocker’s mouth:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Knocker][Knocker:8]]
|
||||
@give ring to knocker
|
||||
# Knocker:8 ends here
|
||||
|
||||
|
||||
|
||||
# The description is dynamic from the Python code, so we don’t need this statement:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Knocker][Knocker:9]]
|
||||
@desc knocker = The brass face looks at you and winks.
|
||||
# Knocker:9 ends here
|
||||
|
||||
|
||||
|
||||
# In order for us to /knock/ on the door, we have to give a =knock= command to the /room/.
|
||||
|
||||
|
||||
# [[file:../../../projects/mud.org::*Knocker][Knocker:10]]
|
||||
@update here = typeclasses.rooms_weather.KnockableOutsideRoom
|
||||
# Knocker:10 ends here
|
||||
|
||||
|
||||
|
||||
# The python object has all the knowledge about knocking and whatnot, but we should have the descriptions here. First, what the knocker reads:
|
||||
|
||||
|
||||
# [[file:../../../projects/mud.org::*Knocker][Knocker:11]]
|
||||
@set here/knock_msg = "You grab the ring and knock firmly on the door."
|
||||
# Knocker:11 ends here
|
||||
|
||||
|
||||
|
||||
# Then, what the other’s in the room read:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Knocker][Knocker:12]]
|
||||
@set here/knock_other_msg = "grabs the ring and knocks firmly on the door."
|
||||
# Knocker:12 ends here
|
||||
|
||||
|
||||
|
||||
# And an error message if the ring is not with the goblin:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Knocker][Knocker:13]]
|
||||
@set here/knock_err_msg = "This door knocker is defective, as it
|
||||
doesn't have a ring to...er, do the knockin'."
|
||||
# Knocker:13 ends here
|
||||
|
||||
# [[file:../../../projects/mud.org::*Cozy Tea House][Cozy Tea House:1]]
|
||||
@dig house = red door;door;house;inside,outside;leave
|
||||
# Cozy Tea House:1 ends here
|
||||
|
||||
|
||||
# The door description should match the artwork on the website:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Red Door][Red Door:1]]
|
||||
@desc red door = A painted red door where the round top of the door
|
||||
fits snugly in the bark of the tree. Along with a large brass
|
||||
doorknob, the door sports the most curious door knocker in the shape
|
||||
of a goblin's face.
|
||||
# Red Door:1 ends here
|
||||
|
||||
|
||||
|
||||
# This exit should be special. First, it is locked unless a character has the =open_red_door= tag.
|
||||
|
||||
# [[file:../../../projects/mud.org::*Red Door][Red Door:2]]
|
||||
@lock door = traverse:tag(open_red_door, mp)
|
||||
# Red Door:2 ends here
|
||||
|
||||
|
||||
# Needs a message why one can’t walk through:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Red Door][Red Door:3]]
|
||||
@set door/err_traverse = "The door seems locked."
|
||||
# Red Door:3 ends here
|
||||
|
||||
|
||||
|
||||
# If you do figure out how to get through the door:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Red Door][Red Door:4]]
|
||||
@set door/traverse_msg = "You stoop as you step through the doorway..."
|
||||
# Red Door:4 ends here
|
||||
|
||||
|
||||
|
||||
# Fix the inside of the “House”:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Inside][Inside:1]]
|
||||
@teleport red door
|
||||
# Inside:1 ends here
|
||||
|
||||
|
||||
# Add the Python /special-ness/ for [[file:~/src/moss-n-puddles/typeclasses/rooms.py::class DabblersRoom(Room):][this room]]:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Inside][Inside:2]]
|
||||
@update here = typeclasses.rooms.DabblersRoom
|
||||
# Inside:2 ends here
|
||||
|
||||
|
||||
# Give it a title:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Inside][Inside:3]]
|
||||
@name here = Dabbler's House;mp03
|
||||
# Inside:3 ends here
|
||||
|
||||
|
||||
# Might as well stay a while:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Inside][Inside:4]]
|
||||
@sethome here
|
||||
# Inside:4 ends here
|
||||
|
||||
|
||||
|
||||
# And the best description ever:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Inside][Inside:5]]
|
||||
@desc here = An enormous stone hearth overshadows this round room with
|
||||
dark paneling. A subtle smell of tea and incense. Large, overstuffed
|
||||
chairs sit invitingly by the fireplace. Oddly angled shelves with
|
||||
books and knickknackery adorn the walls while a trolley supports a
|
||||
large kettle, cups and scones.
|
||||
# Inside:5 ends here
|
||||
|
||||
|
||||
|
||||
# Since we want the description to include the state of the fire, we need some /parts/ to assemble. Still not sure how this should be done.
|
||||
|
||||
|
||||
# [[file:../../../projects/mud.org::*Inside][Inside:6]]
|
||||
@set here/initial_desc = "You found a cozy, cornerless room."
|
||||
|
||||
# Ravenous State
|
||||
@set here/fire_out = "The room is dim, but you see large, overstuffed chairs placed
|
||||
by a dark fireplace in a large stone hearth. Perhaps you could light a fire?"
|
||||
|
||||
# Hungry State
|
||||
@set here/fire_dim = "Large, overstuffed chairs sit invitingly close to the
|
||||
dimly glowing embers in the fireplace of a stone hearth."
|
||||
|
||||
# Fed State
|
||||
@set here/fire_on = "Large, overstuffed chairs sit invitingly by a fire casting
|
||||
shadows that dance on the dark paneling."
|
||||
|
||||
# Full State
|
||||
@set here/fire_full = "Large, overstuffed chairs slightly shield you
|
||||
from the bright light of the roaring fire in the fireplace of a stone hearth."
|
||||
|
||||
# And a final description:
|
||||
@set here/final_desc = "Oddly angled shelves with books and
|
||||
knickknackery adorn the walls around a tapestry. The subtle smell of
|
||||
wood smoke, incense and tea leads you to a trolley supporting a large
|
||||
teapot, cups and freshly baked scones."
|
||||
# Inside:6 ends here
|
||||
|
||||
|
||||
|
||||
# Granted, none of the dynamic description will work until we create the [[Fire]].
|
||||
|
||||
# Let’s come up with a lot of descriptions:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Inside][Inside:7]]
|
||||
@detail tapestry = The muted colors of the tapestry either show its
|
||||
age or its location over the sometimes smokey hearth. It shows a
|
||||
gallant stag surrounded by woodland creatures. A racoon holds aloft a
|
||||
gold box while a wolf has a gnarled staff. A raven perched on the
|
||||
stag's antlers grips a blue ball in its beak.
|
||||
# Inside:7 ends here
|
||||
|
||||
|
||||
|
||||
# We should describe all the objects in the tapestry, eh?
|
||||
|
||||
# [[file:../../../projects/mud.org::*Inside][Inside:8]]
|
||||
@detail raven = The raven winks at you, and says, “Nevermore.” Really?
|
||||
It probably didn't. Your eyes must be playing trickster.
|
||||
# Inside:8 ends here
|
||||
|
||||
|
||||
|
||||
# And the other animals:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Inside][Inside:9]]
|
||||
@detail wolf = The gnarled staff the wolf holds looks a lot like the staff the gnome, Dabbler, has.
|
||||
#
|
||||
@detail stag = A majestic looking deer with gold fur and antlers that look more like tree branches.
|
||||
#
|
||||
@detail raccoon = The box he's holding seems to be a distraction, for he's pocketing a gold coin with his other paw.
|
||||
# Inside:9 ends here
|
||||
|
||||
|
||||
|
||||
# Will this staff get confused at some point?
|
||||
|
||||
# [[file:../../../projects/mud.org::*Inside][Inside:10]]
|
||||
@detail staff = A gnarled staff made of oak has a dark petina from age. Three small leaves has sprouted from the side.
|
||||
# Inside:10 ends here
|
||||
|
||||
|
||||
|
||||
# Touch up the exit:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Inside][Inside:11]]
|
||||
@desc leave = A wood door with a large brass knob leads to the outside.
|
||||
#
|
||||
@set leave/traverse_msg = "You open the door and step outside..."
|
||||
# Inside:11 ends here
|
||||
|
||||
|
||||
# And a fire in the fireplace is a type of /pet/, since we can feed it:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Fireplace][Fireplace:1]]
|
||||
@create/drop fireplace : typeclasses.pets.Fire
|
||||
# Fireplace:1 ends here
|
||||
|
||||
|
||||
# How about some aliases:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Fireplace][Fireplace:2]]
|
||||
@name fireplace = fireplace;fire;embers
|
||||
# Fireplace:2 ends here
|
||||
|
||||
|
||||
# And a description that will be overridden:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Fireplace][Fireplace:3]]
|
||||
@desc fireplace = A stone fireplace with a carved wooden mantel supporting
|
||||
small pictures, some books and a black statue.
|
||||
# Fireplace:3 ends here
|
||||
|
||||
|
||||
# Since we mentioned some details, we better mention them:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Fireplace][Fireplace:4]]
|
||||
@detail pictures = Two small framed pictures perch above the fireplace
|
||||
mantle. One is of a satyr playing a saxophone, and the other is of a
|
||||
fish with a big smile.
|
||||
# Fireplace:4 ends here
|
||||
|
||||
|
||||
|
||||
# This reference in this detail is obviously, only for me:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Fireplace][Fireplace:5]]
|
||||
@detail statue = A small, black statue of a salamander curled around a
|
||||
book, engraved with a title, "Seeing Stones".
|
||||
# Fireplace:5 ends here
|
||||
|
||||
|
||||
|
||||
# I imagine a giant picture over the fireplace … need to do something interesting with it.
|
||||
|
||||
# [[file:../../../projects/mud.org::*Fireplace][Fireplace:6]]
|
||||
@detail picture = Above the fireplace is a large, somewhat abstract
|
||||
painting stretching its arm-like branches with shadowing that looks
|
||||
like a yawn.
|
||||
# Fireplace:6 ends here
|
||||
|
||||
|
||||
# What sort of non-books do we want to look at?
|
||||
|
||||
# In the meantime, let’s just have some descriptions:
|
||||
|
||||
|
||||
# [[file:../../../projects/mud.org::*Knickknacks][Knickknacks:1]]
|
||||
@detail knickknacks;things;knick-knacks;doodads;stuff;crap = An odd
|
||||
assortment of knickknacks and doodads that decorate the minimal
|
||||
space between the askewed books on the skewampus shelves.
|
||||
# Knickknacks:1 ends here
|
||||
|
||||
|
||||
|
||||
# We mentioned shelves of books:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Books][Books:1]]
|
||||
@detail shelves;bookshelf;bookshelves = Shelves at various angles
|
||||
embellish the walls of this small, cozy room. Leatherbound books
|
||||
weigh each shelf, while some stacks of books support other shelves.
|
||||
Dabbler has decorated some shelves with odd trinkets.
|
||||
# Books:1 ends here
|
||||
|
||||
|
||||
|
||||
# This should be an object of “books”, but looking should pull up a random list of books.
|
||||
|
||||
# [[file:../../../projects/mud.org::*Books][Books:2]]
|
||||
@create/drop books:typeclasses.readables.Books
|
||||
# Books:2 ends here
|
||||
|
||||
|
||||
# I start with the name, =books=, but when we look in the room, I want to see /collection/:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Books][Books:3]]
|
||||
@name books = collection of books;books
|
||||
# Books:3 ends here
|
||||
|
||||
|
||||
|
||||
# With a good description:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Books][Books:4]]
|
||||
@desc books = Books of different sizes and colors. So many books.
|
||||
Perhaps you want to simply |blook|n at a |bbook|n at random?
|
||||
# Books:4 ends here
|
||||
|
||||
|
||||
# We mentioned a /trolley/ with tea, cups and scones:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Tea Service][Tea Service:1]]
|
||||
@detail trolley = A tea trolley, complete with a small collection of
|
||||
teacups, a magical teapot, as well as an assortment of scones and pastries.
|
||||
# Tea Service:1 ends here
|
||||
|
||||
|
||||
|
||||
# The “room” gives the teacups, and the “teapot” fills the cups, so we just need descriptions:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Tea Service][Tea Service:2]]
|
||||
@detail teacups = An odd, yet interesting assortment of teacups. Take one.
|
||||
#
|
||||
@detail teacup = Each cup is unique. Take one to look further.
|
||||
# Tea Service:2 ends here
|
||||
|
||||
|
||||
|
||||
# A [[file:~/src/moss-n-puddles/typeclasses/drinkables.py::class Teapot(Object):][teapot]] will contain a type of tea … either given or randomly chosen.
|
||||
# A teapot will “fill” a teacup forever, until it is “remade”.
|
||||
|
||||
|
||||
# [[file:../../../projects/mud.org::*Tea Service][Tea Service:3]]
|
||||
@create/drop teapot;pot;tea pot:typeclasses.drinkables.Teapot
|
||||
#
|
||||
@desc teapot = An adorable brown teapot, waiting for you to |bmake|n some tea.
|
||||
# Tea Service:3 ends here
|
||||
|
||||
|
||||
# And of course, you can’t steal the tea pot:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Tea Service][Tea Service:4]]
|
||||
@lock teapot = get:false()
|
||||
#
|
||||
@set teapot/get_err_msg = "You don't need to carry it around to make tea."
|
||||
# Tea Service:4 ends here
|
||||
|
||||
|
||||
# And [[file:~/src/moss-n-puddles/typeclasses/sittables.py::class Sittables(Sittable):][the chairs]] is a /plural/ location to sit, allowing anyone to sit down.
|
||||
|
||||
|
||||
# [[file:../../../projects/mud.org::*Chairs][Chairs:1]]
|
||||
@create/drop chairs:typeclasses.sittables.Sittables
|
||||
# Chairs:1 ends here
|
||||
|
||||
|
||||
# Add aliases afterwards:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Chairs][Chairs:2]]
|
||||
@name chairs = few overstuffed chairs;overstuffed chairs;chairs;chair
|
||||
# Chairs:2 ends here
|
||||
|
||||
|
||||
# And the description:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Chairs][Chairs:3]]
|
||||
@desc chairs = A few, dark leather, overstuffed chairs, each with a soft, colorful blanket and pillow. An invitation for a cozy nap.
|
||||
# Chairs:3 ends here
|
||||
|
||||
|
||||
|
||||
# Can’t steal ‘em:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Chairs][Chairs:4]]
|
||||
@lock chairs = get:false()
|
||||
#
|
||||
@set chairs/get_err_msg = "It's way too heavy for you to lift."
|
||||
# Chairs:4 ends here
|
||||
|
||||
|
||||
|
||||
# And textual descriptions the object can use:
|
||||
|
||||
# [[file:../../../projects/mud.org::*Chairs][Chairs:5]]
|
||||
@set chairs/adjective = "in"
|
||||
#
|
||||
@set chairs/article = "the"
|
||||
#
|
||||
@set chairs/singular = "an overstuffed chair"
|
||||
#
|
||||
@set chairs/extra = "This feels [|very|quite] [nice|cozy|comfortable].|n"
|
||||
# Chairs:5 ends here
|
||||
Loading…
Reference in a new issue