diff --git a/typeclasses/scripts.py b/typeclasses/scripts.py index c56d787..9b768b0 100644 --- a/typeclasses/scripts.py +++ b/typeclasses/scripts.py @@ -12,12 +12,16 @@ just overloads its hooks to have it perform its function. """ from enum import Enum +from itertools import cycle +from pathlib import Path +from random import choice from evennia.scripts.scripts import DefaultScript from evennia.prototypes.spawner import spawn -from evennia.utils import logger +from evennia.utils import logger, delay + +from typeclasses.characters import Character -from .characters import Character class Script(DefaultScript): """ @@ -159,6 +163,7 @@ class Spell(Script): target.attributes.clear(category="effect") self.delete() + class DonkeyHeadSpell(Spell): def at_start(self, **kwargs): target = self.attributes.get("target") @@ -174,3 +179,120 @@ class DonkeyHeadSpell(Spell): def at_repeat(self, **kwargs): self.stop() + + +class Muttering(Script): + """ + Script to have an objects 'emote' phrases in sequence. + + First add settings to the 'npc', for instance: + + @set npc/muttering_interval = 120 # for 2 minutes + @set npc/muttering_gap = 5 # for 5 seconds per sequence + @set npc/muttering_formats = [ + "sings to |oself as if no one is listening, \"{0}\"", + "continues to sing to |oself, \"{0}\"", + "croons to |oself, \"{0}\"", + "finishes |p verse, \"{0}\"|/", + ] + @set npc/muttering_file = "song-lyrics.txt" + + Then start the script by running the following: + + @script npc = typeclasses.scripts.Muttering + """ + def at_script_creation(self): + self.key = "muttering" + self.desc = "NPCs that Mutter" + self.interval = self.obj.db.muttering_interval or 300 # seconds + self.start_delay = False + self.persistent = True + self.reload() + + def reload(self): + self.db.mutter_delay_gap = self.obj.db.muttering_gap or 7 + self.db.mutter_sequence_index = 0 + mutter_file = self.obj.db.muttering_file + if mutter_file: + logger.info(f"Reading muttering file, {mutter_file}") + self.db.mutters = self.load_mutter(mutter_file) + + def at_repeat(self, **kwargs): + """ + If we have passengers, we need to sail... + """ + self.mutter_sequence() + + def mutter_sequence(self): + # if not hasattr(self, 'mutter_sequence_index'): + # self.db.mutter_sequence_index = 0 + + if self.db.mutter_sequence_index < len(self.db.mutters): + sequences = self.db.mutters[self.db.mutter_sequence_index] + self.db.mutter_sequence_index += 1 + else: + sequences = self.db.mutters[0] + self.db.mutter_sequence_index = 1 + + formats = self.refresh_mutter_formats() + zip_list = zip(sequences, cycle(formats)) \ + if len(sequences) > len(formats) \ + else zip(sequences, formats[:len(sequences)]) + + for idx, tup in enumerate(zip_list): + logger.info(f"delay({idx} * {self.db.mutter_delay_gap}, self.mutter, {tup[0]}, {tup[1]})") + delay(idx * self.db.mutter_delay_gap, + self.mutter, tup[0], tup[1]) + + def mutter(self, phrase, msg_format): + """ + Mutter something aloud to the room the NPC resides. + + Why wait for input from other characters when the NPC can + pretend to be real. + """ + thing = self.obj + room = thing.location + name = choice([ + thing.key, + thing.db._sdesc or thing.name, + thing.key.split(" ")[-1] + ]) + + if thing.db.article: + prefix = f"{thing.db.article} {name} {msg_format}" + else: + prefix = f"{name} {msg_format}" + + if phrase: + room.msg_contents( + prefix.format(phrase), + from_obj=self.obj) + + def refresh_mutter_formats(self): + return self.obj.db.muttering_formats or [ + "mutters as if no one is listening, \"{0}\"", + "grumbles to |oself, \"{0}\"", + "continues to mutter to |oself, \"{0}\"", + "murmurs to |oself, \"{0}\"", + "mutters to |oself, \"{0}\"|/", + ] + + def load_mutter(self, data_file): + """ + Return 'data_file' and return a list of lists. + + Where a blank line in the data file separates the list of + lines from others. + """ + path = Path(__file__).with_name(data_file) + mutters = [] + with open(path) as file: + curr_mutter = [] + for line in file: + if line.strip() == "": + mutters = mutters + [curr_mutter] + curr_mutter = [] + else: + curr_mutter.append(line.strip()) + return mutters