132 lines
4.3 KiB
Python
Executable file
132 lines
4.3 KiB
Python
Executable file
#!/usr/bin/env python
|
|
|
|
from random import randint
|
|
from re import split
|
|
|
|
from typeclasses.objects import Object
|
|
from commands.misc import CmdSetCat, CmdSetOctopus
|
|
from utils.word_list import routput
|
|
|
|
|
|
class NPC(Object):
|
|
"""
|
|
An NPC is an NPC because it can react to what it _hears_.
|
|
To do this, implement 'at_heard_say', a function that
|
|
returns a string for a response.
|
|
"""
|
|
def at_heard_say(self, message, from_obj,
|
|
is_say=True, is_whisper=False):
|
|
"Override to return a string in response to message."
|
|
pass
|
|
|
|
def msg(self, text=None, from_obj=None, **kwargs):
|
|
"Custom msg() method reacting to say."
|
|
# make sure to not repeat what we ourselves said or we'll
|
|
# create a loop
|
|
if from_obj != self:
|
|
is_say = False
|
|
is_whisper = False
|
|
try:
|
|
say_text, is_say = text[0], text[1]['type'] == 'say'
|
|
is_whisper = text[1]['type'] == 'whisper'
|
|
except Exception:
|
|
pass
|
|
|
|
try:
|
|
# message will be on the form `<Person> says, "say_text"`
|
|
# we want to get only say_text without the quotes and any spaces
|
|
message = text.split('says, ')[1].strip(' "')
|
|
shout, response = self.at_heard_say(message, from_obj,
|
|
is_say, is_whisper)
|
|
if response != None:
|
|
self.at_say(response, just_owner=(shout == "shout"))
|
|
except Exception:
|
|
pass
|
|
|
|
# this is needed if anyone ever puppets this NPC - without it
|
|
# you would never get any feedback from the server (not even
|
|
# the results of look)
|
|
super().msg(text=text, from_obj=from_obj, **kwargs)
|
|
|
|
|
|
class CarriableNPC(NPC):
|
|
"""
|
|
A carriable NPC is like any other NPC, except that since it can
|
|
be carried and isn't locked down, it can't hear conversation in a
|
|
room.
|
|
"""
|
|
def at_say(self, message, msg_self=None, msg_location=None,
|
|
receivers=None, msg_receivers=None, just_owner=True,
|
|
**kwargs):
|
|
"Does the best it can to speak out loud."
|
|
owner = self.location
|
|
|
|
if self.location.is_typeclass("typeclasses.rooms.Room"):
|
|
super().at_say(message, msg_self=msg_self,
|
|
msg_location=msg_location,
|
|
receivers=receivers,
|
|
msg_receivers=msg_receivers)
|
|
elif just_owner:
|
|
owner.msg(f"The {self.name} says, \"{message}\"")
|
|
else:
|
|
owner.msg(
|
|
f"The {self.name}, you are carrying, says, \"{message}\"")
|
|
owner.location.msg(
|
|
f"The {self.name}, carried by {self.location.name}, says, \"{message}\"", exclude=owner)
|
|
|
|
|
|
class Familiar(NPC):
|
|
"""
|
|
Parent class for all familiars.
|
|
|
|
These are pets that can be controlled by their owner to do antics.
|
|
"""
|
|
def at_do(self, owner, antics):
|
|
"""
|
|
Issue a 'send_emote' into the room with a antic.
|
|
"""
|
|
def new_name(name):
|
|
"""
|
|
Take a long name, like: fat, black cat
|
|
And return _part_ of the name, like:
|
|
|
|
- fat, black cat
|
|
- black cat
|
|
- cat
|
|
"""
|
|
|
|
parts = list(filter(lambda s: s != "", split(r"[, ]+", name)))
|
|
|
|
num_adjs = len(parts)-1
|
|
lst_adjs = parts[randint(0, num_adjs):num_adjs]
|
|
|
|
noun = parts[-1]
|
|
adjs = ', '.join(lst_adjs)
|
|
return f"{adjs} {noun}" if len(adjs) > 0 else noun
|
|
|
|
# The familiar's name:
|
|
name = self.db._sdesc or self.name
|
|
|
|
if antics.startswith("'"):
|
|
owner.announce_action(f"$Your() {new_name(name)}{antics}")
|
|
else:
|
|
owner.announce_action(f"$Your() {new_name(name)} {antics}")
|
|
|
|
|
|
class Cat(Familiar):
|
|
"""
|
|
A puppetable 'cat' that acts based on that 'command'.
|
|
"""
|
|
def at_object_creation(self):
|
|
"Called when a cat is first created."
|
|
self.cmdset.add(CmdSetCat, persistent=True)
|
|
|
|
|
|
class Octopus(Familiar):
|
|
"""
|
|
A puppetable 'octopus' that acts based on that 'command'.
|
|
"""
|
|
def at_object_creation(self):
|
|
"Called when a octopus is first created."
|
|
self.cmdset.add(CmdSetOctopus, persistent=True)
|