diff --git a/commands/misc.py b/commands/misc.py index 7fa026c..4e47df3 100755 --- a/commands/misc.py +++ b/commands/misc.py @@ -305,6 +305,33 @@ class CmdSetFrog(CmdSet): self.add(CmdFrog) +class CmdAntic(Command): + """Have your familiar do some antic. + + Usage: + + antic + + Or: + + antic's + + Will announce your familiar's antics to the room. + + You can target another character by preceding the character's + description with a |w/|n, as in |w/elf|n or |w/blonde elf|n. + """ + key = "antic" + + def func(self): + self.obj.at_do(self.caller, self.args.strip()) + + +class CmdSetAntic(CmdSet): + def at_cmdset_creation(self): + self.add(CmdAntic) + + class CmdRoll(MuxCommand): """ Roll the dice in your inventory. diff --git a/commands/say.py b/commands/say.py index d4ceac7..eaaa8e9 100755 --- a/commands/say.py +++ b/commands/say.py @@ -4,6 +4,7 @@ from random import random from re import match, split, sub, MULTILINE from evennia.contrib.rpg.rpsystem import send_emote +from evennia.utils import logger from evennia.utils.verb_conjugation.pronouns import PRONOUN_MAPPING from commands.command import Command diff --git a/typeclasses/npcs.py b/typeclasses/npcs.py index 36df4eb..7129d1d 100755 --- a/typeclasses/npcs.py +++ b/typeclasses/npcs.py @@ -88,39 +88,10 @@ class Familiar(NPC): """ Issue a 'send_emote' into the room with a antic. """ - def name_and_adjs(name): - """ - Split a long name into its parts. - """ - return list(filter(lambda s: s != "", split(r"[, ]+", name))) - - def new_name(parts): - """ - Take a long name, like: fat, black cat - And return _part_ of the name, like: - - - fat, black cat - - black cat - - cat - """ - num_adjs = len(parts)-1 - lst_adjs = parts[randint(0, num_adjs):num_adjs] - - noun = parts[-1] - adjs = ', '.join(lst_adjs) - return f"{adjs} {noun}" if len(adjs) > 0 else noun - - parts = name_and_adjs(self.db._sdesc or self.name) - # The familiar's name: - if not alias or alias == parts[-1]: - name = new_name(parts) - else: - name = alias - if antics.startswith("'"): - owner.announce_action(f"$Your() {name}{antics}") + owner.announce_action(f"$Your() {self.get_name(alias)}{antics}") else: - owner.announce_action(f"$Your() {name} {antics}") + owner.announce_action(f"$Your() {self.get_name(alias)} {antics}") class Cat(Familiar): @@ -145,7 +116,7 @@ class Frog(Familiar): A puppetable 'frog' that acts based on that 'command'. """ def at_object_creation(self): - "Called when a octopus is first created." + "Called when this frog is first created." self.cmdset.add(CmdSetFrog, persistent=True) diff --git a/typeclasses/objects.py b/typeclasses/objects.py index 0af38ae..f3178ef 100755 --- a/typeclasses/objects.py +++ b/typeclasses/objects.py @@ -10,6 +10,7 @@ with a location in the game world (like Characters, Rooms, Exits). """ from re import split, match, sub, IGNORECASE +from random import randint from django.conf import settings @@ -47,6 +48,36 @@ class ObjectParent: """True if this object has a method of a particular name.""" return hasattr(self, method_name) and callable(getattr(self, method_name)) + def get_name(self, alias=None): + def name_and_adjs(name): + """ + Split a long name into its parts. + """ + return list(filter(lambda s: s != "", split(r"[, ]+", name))) + + def new_name(parts): + """ + Take a long name, like: fat, black cat + And return _part_ of the name, like: + + - fat, black cat + - black cat + - cat + """ + num_adjs = len(parts)-1 + lst_adjs = parts[randint(0, num_adjs):num_adjs] + + noun = parts[-1] + adjs = ', '.join(lst_adjs) + return f"{adjs} {noun}" if len(adjs) > 0 else noun + + parts = name_and_adjs(self.db._sdesc or self.name) + # The familiar's name: + if not alias or alias == parts[-1]: + return new_name(parts) + else: + return alias + def has(self, item): """ Return true if object has an item. diff --git a/typeclasses/pets.py b/typeclasses/pets.py index 0ffcdf4..9e792b1 100755 --- a/typeclasses/pets.py +++ b/typeclasses/pets.py @@ -20,9 +20,11 @@ from evennia.utils import logger from evennia.utils.gametime import schedule from evennia.utils.search import search_object -from typeclasses.objects import Object +from typeclasses.objects import Object, Listener from typeclasses.characters import Character +from typeclasses.npcs import Familiar from commands.pets import CmdPetSet +from commands.misc import CmdSetAntic from utils.scoring import Scores from utils.word_list import squish, choices @@ -467,10 +469,23 @@ class Friendly(Pet): petter.announce_action(f"$You() $conj(pet) {self.name}.") -class WeeBeastie(Friendly): +# The key attribute is the Listener mixin: +class WeeBeastie(Friendly, Familiar, Listener): """ The stoat that lives in Dabbler's house, is a finicky eater. """ + def at_object_creation(self): + "Called when this pet is first created." + self.cmdset.add(CmdSetAntic, persistent=True) + + def other_sayto(self, speaker, message): + "Override to return a string in response to message." + owner = self.search("Dabbler") + if owner: + owner.announce_action(f"$Your() {name} purrs.") + else: + self.execute_cmd(f"emote /me purrs.") + def feed(self, feeder, item=None): """ Feeding the beast. If item is None, we choose something