#!/usr/bin/env python from re import split, match, IGNORECASE from evennia.utils import logger from typeclasses.characters import Character from utils.word_list import routput class Puppet(Character): """ Special character that if not puppetable, stays put. Perhaps responding or logging information to the GM. """ def at_post_puppet(self, **kwargs): """ Called just after puppeting has been completed and all Account<->Object links have been established. Args: **kwargs (dict): Arbitrary, optional arguments for users overriding the call (unused by default). Notes: You can use `self.account` and `self.sessions.get()` to get account and sessions at this point; the last entry in the list from `self.sessions.get()` is the latest Session puppeting this Object. """ self.msg(f"\nYou are puppeting |c{self.key}|n.") self.msg((self.at_look(self.location), {"type": "look"}), options=None) def at_pre_unpuppet(self, **kwargs): """ Reset our pose. """ super().at_pre_unpuppet() self.execute_cmd("pose reset") def at_post_unpuppet(self, account=None, session=None, **kwargs): """ Make the character object remain in the room. Args: account (DefaultAccount): The account object that just disconnected from this object. session (Session): Session controlling the connection that just disconnected. Keyword Args: reason (str): If given, adds a reason for the unpuppet. This is set when the user is auto-unpuppeted due to being link-dead. **kwargs: Arbitrary, optional arguments for users overriding the call (unused by default). """ self.msg(f"\nNo longer puppeting |c{self.key}|n.\n") def get_display_desc(self, _, **kwargs): """ Return one of two appearances based on if it is being puppeted or not. Set either or both: @set me/desc_puppeted = "A clown bouncing up and down from a box." @set me/desc_uppuppeted = "A colorful box with a closed lid." If either is not specified, it uses the standard description. """ if self.tags.get(key='puppeted', category='account'): return self.db.desc_puppeted if self.db.desc_puppeted else self.db.desc else: return self.db.desc_unpuppeted if self.db.desc_unpuppeted else self.db.desc # ---------------------------------------------------------------------- # TRIGGERS def get_character_label(self, character): return character.get_display_name(self).split(' ')[-1] def trigger_sequence(self, seq, character, *other_stuff): self.delay_sequence(seq, 1, character.key, character.get_display_name(self), self.get_character_label(character), *other_stuff) def get_attribute_trigger(self, label, character): """ Return the attribute where 'key' is the label, and the category can by either the 'character' or its display name. """ name = self.get_character_label(character) return (self.attributes.get(key=label, category=character.key) or self.attributes.get(key=label, category=name) or self.attributes.get(key=label)) def move_triggers(self, label, character): """ Return a list of triggers matching 'label' and 'character'. """ seq = self.get_attribute_trigger(label, character) if seq: self.trigger_sequence(seq, character) def other_arrive(self, character): """ Execute a command when a character arrives in the same location. """ self.move_triggers('arrive', character) def other_leave(self, character): """ Execute a command when a character arrives in the same location. """ self.move_triggers('leave', character) def say_triggers(self, label, character, speech): trigs = self.get_attribute_trigger(label, character) if trigs: for _, trigger in enumerate(dict(trigs)): seq = trigs[trigger] if match(trigger, speech, IGNORECASE): self.trigger_sequence(seq, character) def other_say(self, speaker, speech): self.say_triggers('say', speaker, speech) def other_sayto(self, speaker, speech): self.say_triggers('sayto', speaker, speech) def other_given(self, giver, obj): target = giver.get_display_name(self).split(' ')[-1] self.execute_cmd(f"emote /Me says to /{target}, \"Thanks for the {obj.name}.\"")