#!/usr/bin/env python from re import match from evennia import CmdSet from evennia.utils import delay, logger from evennia.commands.default.muxcommand import MuxCommand from .command import Command from utils.word_list import routput class CmdFly(Command): """Cast the 'fly' spell. Make sure you set the following properties, for instance: @set self/disappear_msg = "The wizard disappears in a puff of smoke." @set self/reappear_msg = "A plume of <> smoke appears... ;; When the smoke clears, a wizard <>." @set self/appear_delay = 3 The last setting is the number of seconds between message segments (those are separated by double semicolons). """ key = "^fly" locks = "call:all()" def func(self): self.caller.do_fly(self.args.strip()) class CmdSetWand(CmdSet): """ All wizard spells are tied to a 'wand' that might be flavored. """ key = "Wand" def at_cmdset_creation(self): super().at_cmdset_creation() self.add(CmdFly) class CmdGM(MuxCommand): """ The gm command allows anything to be emoted into a room. """ key = "gm" aliases = ["#"] locks = "cmd:perm(gm) or perm(Admin)" def func(self): send_to = [] for switch in self.switches: o = self.caller.search(switch, global_search=True) if o: send_to = send_to + [o] if not send_to: send_to = [self.caller.location] for o in send_to: if o.is_typeclass('typeclasses.rooms.Room'): o.msg_contents(self.args) elif o.is_typeclass('typeclasses.characters.Character'): o.msg(self.args) logger.info(f"switches = {self.switches} lhs={self.lhs} rhs={self.rhs} / args={self.args}") class CmdGMTrigger(Command): """The trigger command kicks off a series of named events. Usage: trigger trigger-name trigger :game trigger-name trigger/character trigger-name trigger/character:game trigger-name Where 'game' defaults to the value previously set: @set npc/currentgame = "session1" Triggers are typically set on the NPC (which would be in the room with the PCs) or the room. Using the command: @set npc/triggers:session1 = {"darkness": {"desc": "Make the room go black", "timer": 1, "events": [ "The room gets dark", "And then pitch-black.", ("You can't help it, but scream!", "You hear a scream!")]}} The 'set' command, as a complicated data structure, should be set in a batchcommand. """ key = "trigger" aliases = ["trig"] locks = "cmd:perm(gm) or perm(Admin)" def parse(self): m = match(r" *(/[^: ]+)?(:[^ ]+)? *(.*)", self.args) if m: self.name = m.group(3) if m.group(2): self.game = m.group(2)[1:] else: self.game = None if m.group(1): self.switches = m.group(1)[1:].split(',') else: self.switches = [] else: self.caller.msg("Usage trigger/dest:game trigger") return False def func(self): npc = self.caller self.send_to = [] for switch in self.switches: o = npc.search(switch) if o: self.send_to = self.send_to + [o] else: return game = self.game or npc.db.currentgame if not game: npc.msg("Specify the game, or set a default with |g@set self/currentgame = ") return triggers = dict(npc.attributes.get(key='triggers', category=game)) if not self.name: npc.msg("What event do you want to trigger?") for name,details in triggers.items(): npc.msg(f" - {name} : {details['desc']}") return trigger = triggers[self.name] if trigger: npc.msg(f"Triggering: |w{trigger['desc']}") self.trigger(trigger['events'], trigger.get('timer', 5), self.send_to) else: npc.msg(f"Didn't find '{self.name}' to trigger.") def trigger(self, events, time_delay, dests=[]): """ Given a list of events, send each events at an interval. If an event is a tuple instead of a string, the first element goes to 'dests' and the second goes to the room (based on the caller's location). """ for idx, event in enumerate(events): if isinstance(event, str): delay(time_delay * idx, self.caller.location.msg_contents, "\n" + routput(event)) else: char = event[0] room = event[1] if room: delay(time_delay * idx, self.caller.location.msg_contents, "\n" + routput(room), exclude=dests) if char: for dest in dests: delay(time_delay * idx, dest.msg, "\n" + routput(char))