From 245a1bb389a7c222379591da4f0cd508abc9f3b9 Mon Sep 17 00:00:00 2001 From: Howard Abrams Date: Wed, 5 Mar 2025 21:54:41 -0800 Subject: [PATCH] Refactored code Cleaned up flake8 warnings --- commands/{drinkables.py => consumables.py} | 78 +++++++++++++++--- commands/feedables.py | 6 +- commands/misc.py | 22 ++++++ commands/take.py | 23 +----- typeclasses/consumables.py | 83 ++++++++----------- typeclasses/drinkables.py | 10 +-- typeclasses/exits.py | 14 +--- typeclasses/fishing.py | 3 + typeclasses/pets.py | 30 +++---- typeclasses/readables.py | 18 ++++- typeclasses/rooms.py | 54 +------------ typeclasses/rooms_weather.py | 60 +++----------- typeclasses/scripts.py | 8 +- typeclasses/sittables.py | 19 ++--- typeclasses/things.py | 92 +++++++++++++--------- 15 files changed, 249 insertions(+), 271 deletions(-) rename commands/{drinkables.py => consumables.py} (60%) diff --git a/commands/drinkables.py b/commands/consumables.py similarity index 60% rename from commands/drinkables.py rename to commands/consumables.py index 22f9fe0..3291a37 100755 --- a/commands/drinkables.py +++ b/commands/consumables.py @@ -1,8 +1,40 @@ #!/usr/bin/env python from evennia import Command, CmdSet +from re import match + + +class CmdMakeConsumable(Command): + """ + Generate a new thing and give it to the caller. + """ + key = "pick" + # aliases = "pick" + + def func(self): + self.obj.do_make(self.caller, self.args) + + +class CmdSetMakeConsumable(CmdSet): + def at_cmdset_creation(self): + self.add(CmdMakeConsumable) + + +class CmdEat(Command): + """ + Eat something + """ + key = "eat" + aliases = "bite" + + def func(self): + self.obj.do_eat(self.caller) + + +class CmdSetEat(CmdSet): + def at_cmdset_creation(self): + self.add(CmdEat) -import random class CmdDrinkTea(Command): """ @@ -16,15 +48,19 @@ class CmdDrinkTea(Command): def func(self): self.obj.do_drink(self.caller) + class CmdMakeTea(Command): """ make [tea-type] - Make a pot of magical tea. If you do not specify a particular type of tea (or if it doesn't know what type of tea you suggest), the pot will choose something special for the occasion. + Make a pot of magical tea. If you do not specify a particular type + of tea (or if it doesn't know what type of tea you suggest), the + pot will choose something special for the occasion. + """ + priority = 3 key = "make" - aliases = ["make tea"] - locks = "cmd:all()" + aliases = "brew" def func(self): """ @@ -32,6 +68,7 @@ class CmdMakeTea(Command): """ self.obj.do_make_tea(self.caller, self.args.strip()) + class CmdFillTeacup(Command): """ Fill the teacup with whatever tea is in the teapot. @@ -40,16 +77,30 @@ class CmdFillTeacup(Command): """ key = "fill" aliases = "pour" + locks = "holds(teacup)" def func(self): self.obj.do_fill(self.caller) + +class CmdSetTeacup(CmdSet): + def at_cmdset_creation(self): + self.add(CmdDrinkTea) + + +class CmdSetTeapot(CmdSet): + def at_cmdset_creation(self): + self.add(CmdMakeTea) + self.add(CmdFillTeacup) + + class CmdGetTeacup(Command): """ Get a teacup from the trolley. Each cup is special, but not necessarily unique. """ + auto_help = False key = "get teacup" aliases = ["get cup", "pickup cup", "pickup teacup", "take cup", "take teacup"] locks = "cmd:all()" @@ -61,15 +112,20 @@ class CmdGetTeacup(Command): """ self.obj.produce_teacup(self.caller) -class CmdSetTeacup(CmdSet): - def at_cmdset_creation(self): - self.add(CmdDrinkTea) -class CmdSetTeapot(CmdSet): - def at_cmdset_creation(self): - self.add(CmdMakeTea) - self.add(CmdFillTeacup) +class CmdMakeScone(Command): + """ + Generate a new thing and give it to the caller. + """ + auto_help = False + key = "get scone" + aliases = "grab scone" + + def func(self): + self.obj.do_make(self.caller, self.args) + class CmdSetTrolley(CmdSet): def at_cmdset_creation(self): self.add(CmdGetTeacup) + self.add(CmdMakeScone) diff --git a/commands/feedables.py b/commands/feedables.py index 1db3c4d..989384d 100755 --- a/commands/feedables.py +++ b/commands/feedables.py @@ -5,10 +5,11 @@ from evennia import CmdSet class CmdFeed(Command): """ - Feed or give. + Feed or give something to an object that can eat. + Typically this is used to feed wood to a fire, or + berries to a beast. """ key = "feed" - aliases = ["give"] def func(self): args = self.args.strip() @@ -16,6 +17,7 @@ class CmdFeed(Command): self.caller.msg("Feed what?") return + print(self.obj.key) self.obj.feed(self.caller, self.args) class CmdFeedSet(CmdSet): diff --git a/commands/misc.py b/commands/misc.py index 51a7fbe..86f24f8 100755 --- a/commands/misc.py +++ b/commands/misc.py @@ -2,6 +2,27 @@ from .command import Command from evennia import CmdSet +from evennia.utils import logger + + +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) class CmdJump(Command): @@ -25,6 +46,7 @@ class CmdThrow(Command): Jump or play in or around puddles. """ key = "throw" + locks = "holds(stick)" def func(self): self.obj.do_throw(self.caller) diff --git a/commands/take.py b/commands/take.py index 93bcbd1..ce9bd61 100755 --- a/commands/take.py +++ b/commands/take.py @@ -1,8 +1,7 @@ #!/usr/bin/env python from commands.command import Command -from evennia import CmdSet -from evennia.utils import logger + class CmdTake(Command): """ @@ -10,7 +9,7 @@ class CmdTake(Command): Added to the default_cmdsets. """ key = "take" - aliases = ["remove"] + aliases = ["steal"] # only allow this command if command.obj is carried by caller. # locks = "cmd:holds()" @@ -21,21 +20,3 @@ class CmdTake(Command): """ # logger.log_info(f"Dealing with {self.caller.key}") 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) diff --git a/typeclasses/consumables.py b/typeclasses/consumables.py index 319bc6b..0127f50 100755 --- a/typeclasses/consumables.py +++ b/typeclasses/consumables.py @@ -1,31 +1,19 @@ #!/usr/bin/env python -from evennia import Command, CmdSet +from evennia import Command, CmdSet, TICKER_HANDLER from evennia.prototypes.spawner import spawn +from commands.consumables import ( + CmdSetEat, CmdSetTrolley, CmdSetMakeConsumable +) from typeclasses.objects import Object from utils.word_list import routput from datetime import date +from re import match import random -class CmdEat(Command): - """ - Eat something - """ - key = "eat" - aliases = "bite" - - def func(self): - self.obj.do_eat(self.caller) - - -class CmdSetEat(CmdSet): - def at_cmdset_creation(self): - self.add(CmdEat) - - class Consumable(Object): """ Create with a command: @@ -71,22 +59,6 @@ class Consumable(Object): self.delete() -class CmdMakeConsumable(Command): - """ - Generate a new thing and give it to the caller. - """ - key = "pick" - # aliases = "pick" - - def func(self): - self.obj.do_make(self.caller, self.args) - - -class CmdSetMakeConsumable(CmdSet): - def at_cmdset_creation(self): - self.add(CmdMakeConsumable) - - class Producer(Object): """ An object that produces a Consumable object. @@ -142,21 +114,13 @@ class Producer(Object): # ---------------------------------------------------------------------- -class CmdMakeScone(Command): - """ - Generate a new thing and give it to the caller. - """ - key = "get scone" - # aliases = "take scone" - - def func(self): - self.obj.do_make(self.caller, self.args) - - -class CmdSetMakeScone(CmdSet): - def at_cmdset_creation(self): - self.add(CmdMakeScone) - +TEACUP_DESCS = [ + "A rustic, clay teacup carefully crafted on a wheel. Beautiful [dark red|olive green|navy blue] glaze.", + "A fine example of Royal Albert teacup, sporting a design of violet azaleas. Perfect for a black tea.", + "A Wings of Grace style teacup with blue butterflies. Perfect for some Earl Grey.", + "A dark brown Yixing clay teacup. Perfect for an Oolong tea.", + "A light jade green handle-less teacup. A good choice for a green tea.", +] class Trolley(Producer): """ @@ -204,8 +168,27 @@ class Trolley(Producer): }, ] + teacup_prototype = { + "typeclass": "typeclasses.drinkables.TeaCup", + "key": "teacup", + "desc": "A nice teacup.", + } + def at_object_creation(self): - self.cmdset.add_default(CmdSetMakeScone) + self.cmdset.add_default(CmdSetTrolley) + TICKER_HANDLER.add(interval=60 * 60 * 24, + callback=self.do_bake) + + def produce_teacup(self, caller): + if caller.has("teacup"): + caller.msg("You already have a teacup.") + else: + cuptype = self.teacup_prototype + cuptype['desc'] = routput(random.choice(TEACUP_DESCS)) + + cup = spawn(cuptype)[0] + cup.location = caller + caller.msg("You pick up a teacup.") def do_bake(self): """ @@ -233,3 +216,5 @@ class Trolley(Producer): self.db.make_eat_msgs = msgs self.db.make_finish_msg = "That was [delicious|great|really good]." + + self.location.msg_contents(routput("[New|Aromatic|Fresh|Freshly baked] scones [magically|suddenly|mystically|enchantingly|] appear [on a plate|on plates|] on the trolley.")) diff --git a/typeclasses/drinkables.py b/typeclasses/drinkables.py index 3203895..9037bb1 100755 --- a/typeclasses/drinkables.py +++ b/typeclasses/drinkables.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from typeclasses.objects import Object -from commands.drinkables import CmdSetTeapot, CmdSetTeacup +from commands.consumables import CmdSetTeapot, CmdSetTeacup from utils.word_list import routput, Token import random @@ -28,14 +28,6 @@ TEA_TYPES = { # Why limit to teas ... sure, this tea pot could make coffee ... } -TEACUP_DESCS = [ - "A rustic, clay teacup carefully crafted on a wheel. Beautiful [dark red|olive green|navy blue] glaze.", - "A fine example of Royal Albert teacup, sporting a design of violet azaleas. Perfect for a black tea.", - "A Wings of Grace style teacup with blue butterflies. Perfect for some Earl Grey.", - "A dark brown Yixing clay teacup. Perfect for an Oolong tea.", - "A light jade green handle-less teacup. A good choice for a green tea.", -] - FILL_MSGS = [ "You fill your [teacup|cup] with {1}.", "You pour [some|] {0} tea into your [teacup|cup].", diff --git a/typeclasses/exits.py b/typeclasses/exits.py index 4c3c5d2..a8fae8f 100644 --- a/typeclasses/exits.py +++ b/typeclasses/exits.py @@ -10,7 +10,8 @@ for allowing Characters to traverse the exit to its destination. from evennia.objects.objects import DefaultExit from .objects import ObjectParent -from commands.take import CmdSetKnock +from commands.misc import CmdSetKnock + class Exit(ObjectParent, DefaultExit): """ @@ -26,16 +27,7 @@ class Exit(ObjectParent, DefaultExit): pre_check = traveler.at_pre_move(destination) if pre_check: if self.db.traverse_msg: - traveler.msg(f"\n{self.db.traverse_msg}\n\n") + traveler.msg(f"\n{self.db.traverse_msg}\n") return super().at_traverse(traveler, destination) else: 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) diff --git a/typeclasses/fishing.py b/typeclasses/fishing.py index 539306d..1d37da2 100755 --- a/typeclasses/fishing.py +++ b/typeclasses/fishing.py @@ -33,6 +33,7 @@ class CmdThrowFish(Command): A helper can escort the fish to the nearest body of water if you aren't adjacent to one. """ key = "throw" + locks = "holds(fish)" def func(self): self.obj.do_delete(self.caller) @@ -48,6 +49,7 @@ class CmdCast(Command): Cast the pole. """ key = "cast" + locks = "holds(pole)" def func(self): self.obj.do_cast(self.caller) @@ -58,6 +60,7 @@ class CmdReel(Command): Reel the pole. """ key = "reel" + locks = "holds(pole)" def func(self): self.obj.do_reel(self.caller) diff --git a/typeclasses/pets.py b/typeclasses/pets.py index 80bd447..432584f 100755 --- a/typeclasses/pets.py +++ b/typeclasses/pets.py @@ -8,20 +8,12 @@ Each level of pet requires more aspects for interaction. """ from typeclasses.objects import Object +from typeclasses.characters import Character # from typeclasses.lightables import LightSource -from commands.feedables import CmdFeed, CmdFeedSet +from commands.feedables import CmdFeedSet from utils.word_list import squish -from evennia import ( - TICKER_HANDLER, - CmdSet, - Command, - create_object, - default_cmds, - search_object, - syscmdkeys, - utils, -) +from evennia import TICKER_HANDLER from enum import Enum from time import time @@ -41,8 +33,8 @@ class Pet(Object): This is a base class for Pets. """ fullname = None - pers_pronoun = "it" # or he/she/they - poss_pronoun = "its" # or his/her/them + pers_pronoun = "it" # or he/she/they + poss_pronoun = "its" # or his/her/them # Feed about once a day: hungry_rate = -.7 @@ -83,7 +75,6 @@ class Pet(Object): Called when object is first created. We set up a ticker to update hunger levels regularly. """ - super().at_object_creation() self.db.hunger_level = Hunger.FULL.value self.cmdset.add_default(CmdFeedSet) @@ -93,6 +84,7 @@ class Pet(Object): # so as to not have all weather rooms update at the same time. self.db.interval = random.randint(70, 90) TICKER_HANDLER.add(interval=self.db.interval, callback=self.update_hunger) + super().at_object_creation() def update_hunger(self, *args, **kwargs): """ @@ -105,7 +97,9 @@ class Pet(Object): curr = self.hunger() amount = kwargs.get('amount', self.hungry_rate) - # self.location.msg_contents(f"Feeding a pet: {amount} {isinstance(amount, str)}-> {self.db.hunger_level} / {self.hungry_rate}") + # self.location.msg_contents(f"Feeding a pet: {amount} + # {isinstance(amount, str)}-> {self.db.hunger_level} / + # {self.hungry_rate}") self.db.hunger_level = self.db.hunger_level + amount if self.db.hunger_level < 0: @@ -119,7 +113,7 @@ class Pet(Object): self.location.msg_contents("|w%s|n\n" % self.hunger_appearance()) try: self.location.check_light_state() - except AttributeError as e: + except AttributeError: pass def return_appearance(self, looker, **kwargs): @@ -134,6 +128,7 @@ class Pet(Object): """ return f"{self.db.desc} {self.hunger_appearance()}" + # ------------------------------------------------------------ # Fireplace, both a pet that is hungry and consumes food, # but also emits light when it isn't starving. @@ -189,6 +184,7 @@ class Fire(Pet): 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) + exclude=feeder) self.update_hunger(feeder=feeder, amount=300) + diff --git a/typeclasses/readables.py b/typeclasses/readables.py index 1db1ede..46701da 100755 --- a/typeclasses/readables.py +++ b/typeclasses/readables.py @@ -71,23 +71,26 @@ class CmdLookBook(Command): """ Respond with a new book to look at. """ - priority = 3 + auto_help = False key = "look book" aliases = "l book" def func(self): self.obj.do_look(self.caller) + class CmdTakeBook(Command): """ Generate a new book to store it with the reader. """ + auto_help = False key = "get book" aliases = "take book" def func(self): self.obj.do_take(self.caller) + class CmdReadBook(Command): """ Return the inside contents of the book. @@ -96,16 +99,17 @@ class CmdReadBook(Command): def func(self): self.obj.do_read(self.caller) + class CmdBurnBook(Command): """ Destroy the instance of the book """ key = "burn" - aliases = "throw" def func(self): self.obj.do_burn(self.caller) + class CmdDropBook(Command): """ Drop the instance of the book @@ -116,10 +120,12 @@ class CmdDropBook(Command): def func(self): self.obj.do_burn(self.caller, drop=True) + class CmdSetRead(CmdSet): def at_cmdset_creation(self): self.add(CmdReadBook) + class CmdSetBook(CmdSet): priority = 2 @@ -128,11 +134,13 @@ class CmdSetBook(CmdSet): self.add(CmdBurnBook) self.add(CmdDropBook) + class CmdSetShelf(CmdSet): def at_cmdset_creation(self): self.add(CmdLookBook) self.add(CmdTakeBook) + # ---------------------------------------------------------------------- class Readable(Object): @@ -180,12 +188,14 @@ class Letter(Readable): class Book(Readable): def do_read(self, reader): super().do_read(reader) - reader.location.msg_contents(routput(f"{reader.name} reads a book. You notice the title, |b{0}|n.".format(self.db.title)), exclude=reader) + reader.location.msg_contents(routput(f"{reader.name} reads a book. You notice the title, |b{self.db.title}|n."), + exclude=reader) def do_burn(self, reader, drop=False): if isinstance(reader.location, DabblersRoom): if drop: - reader.msg("You drop the book, and it flaps its pages, and flies back to a section on the shelf. Gotta keep the room organized.") + reader.msg("""You drop the book, and it flaps its pages, and flies back to a section on the shelf. + Gotta keep the room organized.""") else: reader.msg("You throw the book in the fireplace. It immediately yelps, flaps its pages, and flies back to a section on the shelf.") self.location.msg_contents(routput(f"{reader.name} throws a book in the fireplace! It immediately yelps, flaps it pages, and flies back to a shelf."), exclude=reader) diff --git a/typeclasses/rooms.py b/typeclasses/rooms.py index ccd4093..30c4557 100644 --- a/typeclasses/rooms.py +++ b/typeclasses/rooms.py @@ -5,39 +5,16 @@ Rooms are simple containers that has no location of their own. """ -from evennia.objects.objects import DefaultRoom +from evennia import utils from evennia.contrib.grid.extended_room import ExtendedRoom -from evennia.prototypes.spawner import spawn -# from .objects import LightSource -from .drinkables import TEACUP_DESCS -from .pets import Hunger -from commands.drinkables import CmdSetTrolley -from utils.word_list import routput, Token - -import random - -# the system error-handling module is defined in the settings. We load the -# given setting here using utils.object_from_module. This way we can use -# it regardless of if we change settings later. from django.conf import settings -from evennia import ( - TICKER_HANDLER, - CmdSet, - Command, - DefaultExit, - DefaultRoom, - create_object, - default_cmds, - search_object, - syscmdkeys, - utils, -) - +# from .objects import LightSource +from .pets import Hunger +from .objects import ObjectParent _SEARCH_AT_RESULT = utils.object_from_module(settings.SEARCH_AT_RESULT) -from .objects import ObjectParent class Room(ObjectParent, ExtendedRoom): @@ -55,29 +32,6 @@ class Room(ObjectParent, ExtendedRoom): class DabblersRoom(Room): - teacup_prototype = { - "typeclass": "typeclasses.drinkables.TeaCup", - "key": "teacup", - "desc": "A nice teacup.", - } - - def at_object_creation(self): - """ - called at creation - """ - self.cmdset.add_default(CmdSetTrolley, persistent=True) - - def produce_teacup(self, caller): - if caller.has("teacup"): - caller.msg("You already have a teacup.") - else: - cuptype = self.teacup_prototype - cuptype['desc'] = routput(random.choice(TEACUP_DESCS)) - - cup = spawn(cuptype)[0] - cup.location = caller - caller.msg("You pick up a teacup.") - def get_display_desc(self, looker): fire = self.search("fire") full_desc = self.db.initial_desc diff --git a/typeclasses/rooms_weather.py b/typeclasses/rooms_weather.py index 01e3227..529a784 100755 --- a/typeclasses/rooms_weather.py +++ b/typeclasses/rooms_weather.py @@ -3,22 +3,8 @@ import random from .rooms import Room -from commands.take import CmdSetKnock -from .scripts import Script, KnockScript +from evennia import TICKER_HANDLER -from evennia import ( - TICKER_HANDLER, - CmdSet, - Command, - DefaultExit, - DefaultRoom, - create_object, - default_cmds, - search_object, - syscmdkeys, - utils, - create_script, -) # ------------------------------------------------------------- # @@ -27,12 +13,12 @@ from evennia import ( # ------------------------------------------------------------- # Need the time of day ... -from datetime import datetime, date, time, timedelta +from datetime import datetime from pytz import timezone TIMEBASE_WEATHER_MSGS = [ # Night - [ # Clear + [ # Clear "The clouds part and you can see stars glitter against the black velvet night.", "You hear distant howls as the moon appears.", # Cloudy @@ -90,6 +76,7 @@ TIMEBASE_WEATHER_MSGS = [ ], ] + def watches(now=None): """ Would be nice to get the sunrise/sunset of my area. @@ -101,18 +88,20 @@ def watches(now=None): now = datetime.now(local_tz) if now.hour < 4 or now.hour > 22: - return 0 # Night + return 0 # Night if now.hour < 10: - return 1 # Morning + return 1 # Morning if now.hour < 13: - return 2 # Noon + return 2 # Noon if now.hour < 18: - return 3 # Afternoon - return 4 # Evening + return 3 # Afternoon + return 4 # Evening + def choose_weather_message(): return random.choice(TIMEBASE_WEATHER_MSGS[watches()]) + class TimeWeatherRoom(Room): """ This sets up an outdoor room typeclass. At irregular intervals, @@ -138,8 +127,6 @@ class TimeWeatherRoom(Room): TICKER_HANDLER.add( interval=self.db.interval, callback=self.update_weather ) - # this is parsed by the 'tutorial' command on TutorialRooms. - self.db.tutorial_info = "This room has a Script running that has it echo a weather-related message at irregular intervals." def update_weather(self, *args, **kwargs): """ @@ -155,28 +142,3 @@ class TimeWeatherRoom(Room): if self.db.previous_weather != msg: self.db.previous_weather = msg 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 - # This is the _character_ that does the knocking, not the door knocker: - 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'.") diff --git a/typeclasses/scripts.py b/typeclasses/scripts.py index c9b8148..fc6ea0c 100644 --- a/typeclasses/scripts.py +++ b/typeclasses/scripts.py @@ -103,6 +103,7 @@ class Script(DefaultScript): """ pass + class KnockScript(Script): """ A script to wake the dead. @@ -110,12 +111,13 @@ class KnockScript(Script): def at_start(self): knocker = self.attributes.get("knocker") if knocker: - room = knocker.global_search("mp03") + room = knocker.global_search(self.attributes.get("room")) if room: room.msg_contents("Someone is knocking on the door...") god_msg(f"With your seer stone, you see the knocker is {knocker.key}.") def at_repeat(self): - if self.db.waker: - self.db.waker.knocked_timed_out() + waker = self.attributes.get("waker") + if waker: + waker.knocked_timed_out() self.stop() diff --git a/typeclasses/sittables.py b/typeclasses/sittables.py index 19633f7..be6886c 100755 --- a/typeclasses/sittables.py +++ b/typeclasses/sittables.py @@ -4,6 +4,7 @@ from typeclasses.objects import Object from commands.sittables import CmdSetSit from utils.word_list import routput + class Sittable(Object): multiple = False @@ -32,14 +33,14 @@ class Sittable(Object): article = self.db.article or "the" current = self.db.sitter - if current: - if current == sitter: - sitter.msg(f"You are already sitting {adjective} {article} {self.key}.") - return - elif not self.multiple: - sitter.msg(f"You can't sit {adjective} {article} {self.key} " - f"- {current.key} is already sitting there!") - return + if sitter.db.is_sitting: + sitter.msg(f"You are already sitting {adjective} {article} {self.key}.") + return + + if self.db.sitter and not self.multiple: + sitter.msg(f"You can't sit {adjective} {article} {self.key} " + f"- {current.key} is already sitting there!") + return self.db.sitter = sitter sitter.db.is_sitting = self @@ -47,7 +48,6 @@ class Sittable(Object): self.location.msg_contents(f"{sitter.name} sits {adjective} {article} {self.key}.", exclude=sitter) - def do_stand(self, stander): """ Called when trying to stand from this object. @@ -65,6 +65,7 @@ class Sittable(Object): del stander.db.is_sitting stander.msg(self.stand_msg()) + class Sittables(Sittable): multiple = True diff --git a/typeclasses/things.py b/typeclasses/things.py index 823b05a..0843e71 100755 --- a/typeclasses/things.py +++ b/typeclasses/things.py @@ -1,20 +1,11 @@ #!/usr/bin/env python -""" -Knocker - -The Object is the class for gatekeepers between rooms. - -Use the ObjectParent class to implement common features for *all* entities -with a location in the game world (like Characters, Rooms, Exits). - -""" - +from evennia import create_script from evennia.utils import logger +from .scripts import KnockScript from .objects import Object -from .characters import Character -from commands.misc import CmdSetPuddle, CmdSetStick +from commands.misc import CmdSetPuddle, CmdSetStick, CmdSetKnock from utils.word_list import routput from random import choice, random @@ -26,18 +17,19 @@ class Stick(Object): self.cmdset.add_default(CmdSetStick) def do_throw(self, thrower): - player.db.thrown_times = (player.db.thrown_times or 0) + 1 - if player.db.jumped_times == 1: - player.msg("The stick flies through the air, and just as you thought, it comes back to you!") + thrower.db.thrown_times = (thrower.db.thrown_times or 0) + 1 + if thrower.db.jumped_times == 1: + thrower.msg("The stick flies through the air, and just as you thought, it comes back to you!") else: - player.msg(routput(choice([ - "Yer a wizard, {thrower.name.capitalize()}!", - "Did you see that? It clipped the leaf on that tree before returning.", - "This is a fun game.", - "Maybe we should get a pet beastie in here who would love to play.", + thrower.msg(routput(choice([ + f"Yer a wizard, {thrower.name.capitalize()}!", + "[Did you see that?|] It clipped the leaf on that tree before returning.", + "This is a [fun|pleasant|nice] [past-time|game].", + "Maybe we should get a pet [or beast|beastie] in here who would love to play.", ]))) - self.location.msg_contents(f"{player.name} jumps in the puddle.", - exclude=player) + self.location.msg_contents(f"{thrower.name} throws a stick.", + exclude=thrower) + class Puddle(Object): def at_object_creation(self): @@ -67,11 +59,14 @@ class Puddle(Object): self.location.msg_contents(f"{player.name} jumps in the puddle.", exclude=player) + class Knocker(Object): """ + Knocker + + The Object is the class for gatekeepers between rooms. Special object that listens to what is said in the room, and attempts to a _real_ NPC. - """ muffled_responses = [ "Mmmuufffmm", @@ -191,6 +186,37 @@ class Knocker(Object): "I'll say, [we have had|that is] a spell of weather.", ] + def at_object_creation(self): + super().at_object_creation() + self.cmdset.add(CmdSetKnock) + + def do_knock(self, knocker): + if self.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, + # This is the _character_ + # that does the knocking, not + # the door knocker: + attributes=[("knocker", knocker), + # Waker is the door knocker + ("waker", self), + ("room", self.db.room_to_msg) + ]) + 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'.") + + 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.") + def at_heard_say(self, message, from_obj): """ A simple listener and response. This makes it easy to change for @@ -228,28 +254,28 @@ class Knocker(Object): # time, so we store in the database a setting to keep # track and alternate the responses: elif self.db.hard: - self.db.hard = False; + self.db.hard = False if from_obj.tags.get(key="open_red_door", category="mp"): return routput(choice(self.after_unlocked_responses)) else: return routput(choice(self.unknown_responses)) else: - self.db.hard = True; + self.db.hard = True return routput(choice(self.cant_hear_responses)) def get_display_desc(self, looker, **kwargs): # Use this for random information instead of self.db.desc response = "In a shape of a bald goblin, the brass door knocker in the center of the red door" if self.has("brass ring"): - response += " holds a ring in its mouth. " - response += "[You think it|You are sure it|You could've sworn it|It] [just|] winked at you." + response += " holds a ring in its mouth. " + response += "[You think it|You are sure it|You could've sworn it|It] [just|] winked at you." else: - response += " [smiles|looks] at you expectantly. " + response += " [smiles|looks] at you expectantly. " return routput(response) def at_desc(self, looker): - return "what" # self.get_display_desc(looker) + return "what" # self.get_display_desc(looker) def get_display_things(self, looker): return "" @@ -275,7 +301,7 @@ class Knocker(Object): # First get the response (if any) response = self.at_heard_say(say_text, from_obj) # If there is a response - if response != None: + if response is not None: self.at_say(response) # this is needed if anyone ever puppets this NPC - without it you would never @@ -288,9 +314,3 @@ class Knocker(Object): else: self.at_say("Umph") 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.")