#!/usr/bin/env python from re import match from evennia import CmdSet, create_script from evennia.utils import delay, logger from evennia.commands.default.muxcommand import MuxCommand from evennia.contrib.rpg.rpsystem import send_emote from .command import Command from typeclasses.scripts import DonkeyHeadSpell 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) class CmdSpell(Command): key = "spell" aliases = ['cast'] locks = "cmd:perm(gm) or perm(Admin)" def parse(self): self.spell = None self.target = None m = match(r"([^ ]+)( +on +(.+))?", self.args.strip()) if m: self.spell = m.group(1) self.target = m.group(3) def func(self): caster = self.caller if not self.spell: caster.msg('Usage: cast [on ]') return char = None if self.target: char = caster.search(self.target) if not char: return if self.spell == 'donkey' and char: create_script(key="donkey_head", typeclass=DonkeyHeadSpell, interval=130, start_delay=True, attributes=[("target", char)]) caster.msg(f"You cast |wHead of Donkey|n on {char}") else: caster.msg(f"You fail to cast {self.spell}") 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))