We can knock on a door.

And a number of bugs squashed.
This commit is contained in:
Howard Abrams 2025-02-11 21:09:23 -08:00
parent fabb5a0d00
commit 0850301c65
9 changed files with 100 additions and 26 deletions

View file

@ -10,7 +10,7 @@ class CmdTake(Command):
Added to the default_cmdsets. Added to the default_cmdsets.
""" """
key = "take" key = "take"
aliases = ["get", "remove"] aliases = ["remove"]
# only allow this command if command.obj is carried by caller. # only allow this command if command.obj is carried by caller.
# locks = "cmd:holds()" # locks = "cmd:holds()"
@ -19,5 +19,23 @@ class CmdTake(Command):
Implements the take command. Since this command is designed Implements the take command. Since this command is designed
to work on the object, we operate only on self.obj. to work on the object, we operate only on self.obj.
""" """
logger.log_info(f"Dealing with {self.caller.key}") # logger.log_info(f"Dealing with {self.caller.key}")
self.caller.do_take(self.args) self.caller.do_take(self.args)
class CmdKnock(Command):
"""
The ability to knock on something, like a door.
While it would be great if it could be attached to a door or some
other exit, we need to attach this to the room.
"""
key = "knock"
def func(self):
logger.log_info(f"Seems like {self.caller.key} wants to knock on me.")
self.obj.do_knock(self.caller)
class CmdSetKnock(CmdSet):
def at_cmdset_creation(self):
self.add(CmdKnock)

View file

@ -11,10 +11,10 @@ creation commands.
from evennia.objects.objects import DefaultCharacter from evennia.objects.objects import DefaultCharacter
from utils.word_list import Token, routput from utils.word_list import Token, routput
from .objects import ObjectParent from .objects import Object
class Character(ObjectParent, DefaultCharacter): class Character(Object, DefaultCharacter):
""" """
The Character just re-implements some of the Object's methods and hooks The Character just re-implements some of the Object's methods and hooks
to represent a Character entity in-game. to represent a Character entity in-game.

View file

@ -10,7 +10,7 @@ for allowing Characters to traverse the exit to its destination.
from evennia.objects.objects import DefaultExit from evennia.objects.objects import DefaultExit
from .objects import ObjectParent from .objects import ObjectParent
from commands.take import CmdSetKnock
class Exit(ObjectParent, DefaultExit): class Exit(ObjectParent, DefaultExit):
""" """
@ -30,3 +30,12 @@ class Exit(ObjectParent, DefaultExit):
return super().at_traverse(traveler, destination) return super().at_traverse(traveler, destination)
else: else:
return False return False
class KnockableExit(Exit):
def at_object_creation(self):
self.cmdset.add_default(CmdSetKnock)
def do_knock(self, knocker):
knocker.msg("You knock.")
self.location.msg_contents(f"{knocker.name} knocks on {self.key}.",
exclude=knocker)

View file

@ -4,7 +4,7 @@ from typeclasses.objects import Object
from typeclasses.rooms import DabblersRoom from typeclasses.rooms import DabblersRoom
from evennia import Command, CmdSet from evennia import Command, CmdSet
from evennia.prototypes.spawner import spawn from evennia.prototypes.spawner import spawn
from utils.word_list import routput, character_has, Token from utils.word_list import routput, Token
import random import random

View file

@ -3,6 +3,9 @@
import random import random
from .rooms import Room from .rooms import Room
from commands.take import CmdSetKnock
from .scripts import Script, KnockScript
from evennia import ( from evennia import (
TICKER_HANDLER, TICKER_HANDLER,
CmdSet, CmdSet,
@ -14,10 +17,9 @@ from evennia import (
search_object, search_object,
syscmdkeys, syscmdkeys,
utils, utils,
create_script,
) )
print("Loading the weather...")
# ------------------------------------------------------------- # -------------------------------------------------------------
# #
# Weather room - room with a ticker # Weather room - room with a ticker
@ -153,3 +155,27 @@ class TimeWeatherRoom(Room):
if self.db.previous_weather != msg: if self.db.previous_weather != msg:
self.db.previous_weather = msg self.db.previous_weather = msg
self.msg_contents(f"|w{msg}|n\n") self.msg_contents(f"|w{msg}|n\n")
class KnockableOutsideRoom(TimeWeatherRoom):
def at_object_creation(self):
super().at_object_creation()
self.cmdset.add_default(CmdSetKnock)
def do_knock(self, knocker):
door = self.search("knocker")
if door.has("ring"):
knock_script = create_script(key="knocking",
typeclass=KnockScript,
interval=10, # seconds <=0 means off
start_delay=True, # wait interval before first call
autostart=True,
attributes=[("knocker", knocker)])
knock_script.db.waker = door
knock_script.db.knocker = knocker
knocker.msg("You grab the ring and knock firmly on the door.")
self.msg_contents(f"{knocker.name} grabs the ring and knocks firmly on the door.",
exclude=knocker)
else:
knocker.msg("This door knocker is defective, as it doesn't have a ring to...er, do the knockin'.")

View file

@ -13,6 +13,8 @@ just overloads its hooks to have it perform its function.
""" """
from evennia.scripts.scripts import DefaultScript from evennia.scripts.scripts import DefaultScript
from evennia.utils import logger
from utils.support import god_msg
class Script(DefaultScript): class Script(DefaultScript):
@ -99,5 +101,18 @@ class Script(DefaultScript):
at_server_start() at_server_start()
""" """
pass pass
class KnockScript(Script):
"""
A script to wake the dead.
"""
def at_start(self):
knocker = self.attributes.get("knocker")
if knocker:
god_msg(f"{knocker.key} stands at the door, and knocks.")
def at_repeat(self):
if self.db.waker:
self.db.waker.knocked_timed_out()
self.stop()

View file

@ -71,12 +71,12 @@ class Sittables(Sittable):
def sit_msg(self): def sit_msg(self):
adjective = self.db.adjective or "on" adjective = self.db.adjective or "on"
article = self.db.article or "the" article = self.db.article or "the"
default = f"{article} {self.db.name}" name = aliases[-1] # Last alias is singular
default = f"{article} {name}"
singular = self.db.singular or default singular = self.db.singular or default
extra = self.db.extra or "" extra = self.db.extra or ""
aliases = self.aliases.all() aliases = self.aliases.all()
name = aliases[1] # Second alias is singular
return routput(f"You sit {adjective} {singular}. {extra}") return routput(f"You sit {adjective} {singular}. {extra}")

View file

@ -51,14 +51,14 @@ class Knocker(Object):
[r"knocker|goblin", [ [r"knocker|goblin", [
"[Sorry.|What was that?|Did you say something?] I'm hard of hearing on account of the brass ears.", "[Sorry.|What was that?|Did you say something?] I'm hard of hearing on account of the brass ears.",
"Yes, I suppose I'm this amazing puzzle you get to in Chapter Three. Wait, does that mean I'm just an NPC?", "Yes, I suppose I'm this amazing puzzle you get to in Chapter Three. Wait, does that mean I'm just an NPC?",
"Who me? I thought you were talking to the goblin in the bushes." "Who me? I thought you were talking to the goblin in the bushes.",
"Why yes, I am hard of hearing.", "Why yes, I am hard of hearing.",
]], ]],
["password", [ ["password", [
"Of course this door is protected by a super complicated encrypted password.", "Of course this door is protected by a super complicated encrypted password.",
"If I tell you, it wouldn't be a secret now.", "If I tell you, it wouldn't be a secret now.",
"The password? You just have to guess.", "The password? You just have to guess.",
"Well, I suppose I could give you a hint." "Well, I suppose I could give you a |bhint|n.",
]], ]],
["hint", [ ["hint", [
"A hint does sound fair. [Should I|I should] come up with a |briddle|n[|, huh]?" "A hint does sound fair. [Should I|I should] come up with a |briddle|n[|, huh]?"
@ -83,7 +83,7 @@ class Knocker(Object):
things out, wait, where was I? things out, wait, where was I?
""" """
]], ]],
["hello|greet", [ [r"\bhello|\bgreet|\bhey\b", [
"How's it going?", "How's it going?",
"How's it?", "How's it?",
"'Sup.", "'Sup.",
@ -107,14 +107,14 @@ class Knocker(Object):
So, you see, if you speak the |bpassword|n, wait, I've said too much. So, you see, if you speak the |bpassword|n, wait, I've said too much.
""" """
]], ]],
["\byes|yeah|yah\b", [ [r"\byes|yeah|yah\b", [
"Really? You agree?", "Really? You agree?",
"Excellent", "Excellent",
]], ]],
["\bno|nope\b", [ [r"\bno|nope\b", [
"Well, it's true. Just ask the [raven|trees|gnome].", "Well, it's true. Just ask the [raven|trees|gnome].",
]], ]],
["\?$", [ [r"\?$", [
"What about [me|it|'im]?", "What about [me|it|'im]?",
"I dunno...", "I dunno...",
]], ]],
@ -163,7 +163,8 @@ class Knocker(Object):
# Let's see if a keyword gives a good response: # Let's see if a keyword gives a good response:
for idx, [regex, responses] in enumerate(self.all_responses): for idx, [regex, responses] in enumerate(self.all_responses):
if re.match(r".*" + regex + r".*", message): full_regex = r".*" + regex + r".*"
if re.match(full_regex, message):
# The first match is the password, so we set a tag on # The first match is the password, so we set a tag on
# the character, so that they can go through the door: # the character, so that they can go through the door:
if idx == 0: if idx == 0:
@ -248,3 +249,9 @@ class Knocker(Object):
else: else:
self.at_say("Umph") self.at_say("Umph")
return True return True
def knocked_timed_out(self):
if self.has("brass ring"):
self.at_say(choice(self.muffled_responses))
else:
self.at_say("Doesn't appear that anyone is home.")

View file

@ -20,12 +20,11 @@ def character_has(holder, item):
elif i == item: elif i == item:
return i return i
def god_msg(msg, sender=None, location=None):
dabbler = Character.objects.search_object("#1")[0]
dabbler.msg(f"{msg} {'from ' + sender if sender else ''} {'at ' + location if location else ''}")
def debug(msg, sender=None, location=None): def debug(msg, sender=None, location=None):
dabbler = Character.objects.search_object("Dabbler")[0] god_msg(f"DEBUG: {msg}", sender, location)
full_msg = "DEBUG:"
if sender: # py from typeclasses.characters import Character; god = Character.objects.search_object("#1")[0]
full_msg += f" (from {sender})"
if location:
full_msg += f" (at {location})"
full_msg += f" {msg}"
dabbler.msg(full_msg)