Muttering and or, Singing NPCs
NPCs can, after a delay, state or do a few things from a file.
This commit is contained in:
parent
a5d88da4a8
commit
c7825731f2
1 changed files with 124 additions and 2 deletions
|
|
@ -12,12 +12,16 @@ just overloads its hooks to have it perform its function.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
from itertools import cycle
|
||||||
|
from pathlib import Path
|
||||||
|
from random import choice
|
||||||
|
|
||||||
from evennia.scripts.scripts import DefaultScript
|
from evennia.scripts.scripts import DefaultScript
|
||||||
from evennia.prototypes.spawner import spawn
|
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):
|
class Script(DefaultScript):
|
||||||
"""
|
"""
|
||||||
|
|
@ -159,6 +163,7 @@ class Spell(Script):
|
||||||
target.attributes.clear(category="effect")
|
target.attributes.clear(category="effect")
|
||||||
self.delete()
|
self.delete()
|
||||||
|
|
||||||
|
|
||||||
class DonkeyHeadSpell(Spell):
|
class DonkeyHeadSpell(Spell):
|
||||||
def at_start(self, **kwargs):
|
def at_start(self, **kwargs):
|
||||||
target = self.attributes.get("target")
|
target = self.attributes.get("target")
|
||||||
|
|
@ -174,3 +179,120 @@ class DonkeyHeadSpell(Spell):
|
||||||
|
|
||||||
def at_repeat(self, **kwargs):
|
def at_repeat(self, **kwargs):
|
||||||
self.stop()
|
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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue