We can make potions now!

This includes herbs, mushrooms and water sources that can be placed in
the cauldron to create effects.
This commit is contained in:
Howard Abrams 2025-07-21 18:11:09 -07:00
parent dca4048acf
commit 43b6245c77
7 changed files with 961 additions and 224 deletions

View file

@ -25,6 +25,30 @@ class CmdSetMakeConsumable(CmdSet):
self.add(CmdMakeConsumable)
class CmdFill(Command):
"""
Fill a bottle with water.
"""
key = "fill"
def func(self):
item = self.caller.search(self.args.strip())
if item:
if item.has_method("do_fill"):
item.do_fill(self.caller, {
"title": self.obj.db.fill_name,
"desc": self.obj.db.fill_desc,
})
else:
self.caller.msg("You can't fill that.")
class CmdSetFillable(CmdSet):
def at_cmdset_creation(self):
self.add(CmdFill)
class CmdMakeTea(Command):
"""
make [tea-type]
@ -42,7 +66,7 @@ class CmdMakeTea(Command):
"""
Make a pot of tea. Optional accept the type of tea.
"""
self.obj.do_make_tea(self.caller, self.words())
self.obj.do_make_tea(self.caller, self.args.strip())
class CmdFillTeacup(Command):

View file

@ -1,13 +1,17 @@
#!/usr/bin/env python
from random import choice
from collections import defaultdict
from random import choice, randint, random
from evennia.commands.default.muxcommand import MuxCommand
from evennia import CmdSet
from evennia.utils import logger
from evennia.commands.default.muxcommand import MuxCommand
from evennia.prototypes.spawner import spawn
from evennia.utils import delay, iter_to_str, logger
from commands.command import Command
from typeclasses.objects import Object
from typeclasses.scripts import Script
from typeclasses.drinkables import Container
class CmdEmpty(Command):
@ -17,6 +21,11 @@ class CmdEmpty(Command):
Usage:
empty [ cauldron ]
Empty the cauldron before you start working on making a potion.
This destroys either the ingredients or the potion that it contains.
Next, you can start |gadd|ning the potion's components.
"""
key = "empty"
@ -26,17 +35,36 @@ class CmdEmpty(Command):
class CmdAdd(Command):
"""
Add an item_str from your inventory to the cauldron.
Add an item from your inventory to the cauldron.
Usage:
add item_str [ to cauldron ]
add <item> [ to cauldron ]
The item can be a single item you picked up on your travels, like
a bunch of tickleweed, or can be the contents of a container, like
a bottle or teacup.
Keep in mind that potions may require |wenough|n of an item.
For instance, a bottle can contain more liquid than a teacup.
(You can get an empty bottle from the shelf.)
Once all ingredients have been added, you can |gcreate|n a potion.
"""
priority = 2
key = "add"
aliases = "give"
def func(self):
self.obj.do_add(self.caller)
maker = self.caller
item_str = self.args.strip().split(" to ")
if len(item_str) == 0:
maker.msg(f"What do you want to add to the {self.obj.name}?")
return
item = maker.search(item_str[0], location=maker)
if item:
self.obj.do_add(self.caller, item)
class CmdCreate(Command):
@ -45,30 +73,43 @@ class CmdCreate(Command):
Usage:
create
create [ potion ]
After you have |gadd|ned all the ingredients for a potion, cast
this. If you have the correct components, the cauldron will
contain a potion ready for you to |gbottle|n.
"""
key = "create"
aliases = ["make", "mix", "cook"]
aliases = ["make", "brew", "cook"]
def func(self):
self.obj.do_create(self.caller)
class CmdBottle(Command):
"""
Bottle the contents of the cauldron.
"""Bottle the contents of the cauldron.
Usage:
bottle
bottle [ potion ]
After you have |gcreate|nd a potion, use this command to put it
into a vial you can consume later (or give to a friend).
If you |gdrop|n the vial, you can always get another potion from
the cauldron (at least, until some one calls |gempty|n).
"""
key = "bottle"
aliases = ["fill", "get vial"]
def func(self):
self.obj.do_bottle(self.caller)
class CmdSetCauldron(CmdSet):
"""
The commands available to people next to a cauldron.
"""
def at_cmdset_creation(self):
self.add(CmdEmpty)
self.add(CmdAdd)
@ -86,63 +127,197 @@ class Cauldron(Object):
- bottle
"""
def at_object_creation(self):
"""
Associate the commands with this instance.
"""
self.cmdset.add_default(CmdSetCauldron)
def do_empty(self, maker):
def return_appearance(self, looker):
"""
Return the full description and contents of this object.
Along with a description of this object, we want to return the
ingredients and items in this object. For that, we duplicate a
lot of already implemented code.
"""
full_desc = self.db.desc
num_items = len(self.contents)
if num_items == 0:
return full_desc + "|/It is empty, and ready for you to |gadd|n ingredients."
# Had to copy the following code from the objects.objects'
# get_display_things so that I could reformat it:
grouped_things = defaultdict(list)
for thing in self.contents:
grouped_things[thing.get_display_name(looker)].append(thing)
thing_names = []
for thingname, thinglist in sorted(grouped_things.items()):
nthings = len(thinglist)
thing = thinglist[0]
singular, plural = thing.get_numbered_name(nthings, looker, key=thingname)
thing_names.append(singular if nthings == 1 else plural)
thing_names = iter_to_str(thing_names)
return full_desc + \
f"|/It contains {thing_names}." if thing_names else ""
def do_empty(self, maker=None):
"""
Delete the contents of the cauldron.
Also randomly return a funny emptying message.
"""
if self.contents == []:
maker.msg(f"The {self.name} is already empty.")
return
msg = choice([
f"The imp <<climbs ^ flies >> down from its perch, <<sniffs ^ tastes ^ samples >> the brew, then <<downs ^ swallows ^ drinks >> it, emptying the cauldron. Lethargically, it << hoists itself ^ climbs back >> to its branch.",
"The imp produces a long metal straw and slurps up the brew from the cauldron.",
"The imp pushes down a level, flushing the contents of cauldron.",
"The imp << stokes the ^ breathes >> fire, quickly boiling the brew until it evaporates. It licks clean the remaining sludge, emptyig the cauldron."
"The imp pushes down a lever, flushing the contents of cauldron.",
"The imp << stokes the ^ breathes >> fire, quickly boiling the brew until it evaporates. It licks clean the remaining sludge, emptying the cauldron."
])
maker.announce_action(msg)
self.db.contents = []
def do_add(self, maker):
item_str = self.args.strip()
if item_str == "":
maker.msg("What do you want to add to the cauldron?")
return
item = maker.search(item_str, location=maker)
if item:
maker.announce_action(f"$You() $conj(add) {item.name} to {self.name}.")
self.attributes.add("contents",
self.db.contents + [item_str])
if maker:
maker.announce_action(msg)
for item in self.contents:
item.delete()
def do_create(self, create):
def do_add_liquid(self, maker, obj):
"""
Like do_add, but doesn't delete the container.
Instead this creates a new "object" based on the contents of
the container. Makes it safe to delete.
"""
name, amount, desc = obj.do_empty()
if name:
for cup in range(int(amount / 4)):
liquid = spawn({
"typeclass": "typeclasses.objects.Object",
"key": f"cup of {name}"
})[0]
liquid.location = self
maker.announce_action(f"$You() $conj(pour) the {name} from $pron(your) {obj.name} into the {self.name}.")
else:
maker.msg(f"The {obj.name} is empty. You can |gfill|n it first.")
def do_add(self, maker, item):
"""
Moves an item to the cauldron.
If the item is a container, we call do_add_liquid to add its contents.
We limit this to Herbs and other consumables.
"""
if self.has_potion():
maker.msg("The cauldron already contains a potion. You need to |gempty|n it first.")
return
if item.has_method("do_empty"):
self.do_add_liquid(maker, item)
elif item.is_typeclass("typeclasses.consumables.Consumable") or \
item.is_typeclass("typeclasses.consumables.Herb"):
item.move_to(self, quiet=True)
maker.announce_action(f"$You() $conj(add) {item.name} to {self.name}.")
else:
maker.msg("Adding that to a cauldron for brewing potions doesn't make sense.")
def do_create(self, maker):
"""
Does this make a viable concoction?
"""
good = choice([
f"The imp <<climbs ^ flies >> down from its perch, <<sniffs ^ tastes ^ samples >> the brew. Before returning to its roost, it << gives you a tiny thumbs up ^ nods ^ smiles >>.",
"The imp <<climbs ^ flies ^ jumps >> down from its perch, <<sniffs ^ tastes ^ samples >> the brew. Before returning to its roost, it << gives $you() a tiny thumbs up ^ nods ^ smiles ^ nods >>.",
])
bad = choice([
f"The imp <<climbs ^ flies >> down from its perch, <<sniffs ^ tastes ^ samples >> the brew. Before returning to its roost, it << shakes its head ^ grimaces ^ retches a bit >>.",
"The imp <<climbs ^ flies ^ jumps >> down from its perch, <<sniffs ^ tastes ^ samples >> the brew. Before returning to its roost, it << shakes its head ^ grimaces ^ retches a bit >>.",
"As soon as $you() $conj(grab) a wooden spoon to stir, the <<brew ^ concoction>> in the cauldron farts a black cloud. This must not be right."
])
maker.announce_action(good)
if self.contents == []:
maker.msg(f"The {self.name} is empty. First, |gadd|n ingredients.")
return
seq, brew_func = self.can_create_laughter()
if seq:
maker.announce_action(good)
for idx, msg in enumerate(seq):
delay(idx * 3 + 2, maker.announce_action, msg)
self.do_empty()
brew_func()
else:
maker.announce_action(bad)
def has_potion(self):
"""
Return reference to the potion in the cauldron.
None otherwise.
"""
if len(self.contents) == 1 and self.has(Potion):
return self.contents[0]
def do_bottle(self, maker):
"""
If the contents are viable, let's make a vial.
If the contents are viable, let's create a vial.
"""
title = "potion"
bottle = spawn({
potion = self.has_potion()
if not potion:
maker.msg("The cauldron doesn't have a potion to bottle. Perhaps, you need to |gcreate|n one first?")
return
vial = spawn({
"typeclass": "typeclasses.alchemy.Vial",
"key": title,
"aliases": ["bottle", "vial"],
"desc": details.get("desc")
"key": potion.name,
"aliases": ["potion", "vial"],
"desc": potion.db.desc
})[0]
bottle.db.amount = 1
bottle.location = maker
maker.announce_action(f"After stirring and crafting $pron(your) stew, $you() $conj(fill) a vial with $pron(your) concoction.")
vial.db.amount = 1
vial.db.spell = potion.db.spell
vial.db.empty_name = "empty vial"
vial.db.empty_desc = "Small crystal vial. May have contained a potion."
vial.location = maker
maker.announce_action(f"$You() $conj(fill) a small vial with $pron(your) << stew ^ elixir ^ potion ^ concoction >>.")
# ----------------------------------------------------------------------
# Potions:
def can_create_laughter(self):
"""
Return true if the cauldron can make a laughter potion.
"""
mushrooms = self.search("gigglecap mushroom", location=self, quiet=True)
weeds = self.search("tickleweed", location=self, quiet=True)
water = self.search("fizzy water", location=self, quiet=True)
if len(mushrooms) > 0 and len(weeds) > 0 and len(water) > 1:
return ([
"$You() $conj(stir) the cauldron with a wooden spoon, watching the liquid change to a deep purple, releasing a fragrant aroma.",
"The imp climbs down from its perch and mutters, \"Risus ignis, laetitiae flamma, in corde nostro, gaudium humourous.\"",
"Sparks of vibrant octarine pop over the elixir, making it ready to |gbottle|n."
], self.create_laughter)
else:
return (None, None)
def create_laughter(self):
"""
Spawn a Potion with the spell function for the cauldron's contents.
"""
potion = spawn({
"typeclass": "typeclasses.alchemy.Potion",
"key": "laughing potion",
"desc": "A purple elixir guaranteed to elicit a chuckle or two."
})[0]
potion.location = self
potion.db.spell = LaughterSpell
class Vial(Object):
class Vial(Container):
"""
A vial with a single quaff, but cast a spell.
"""
fill_amount = 1
def at_object_creation(self):
"""
Set up the database.
@ -154,3 +329,68 @@ class Vial(Object):
"""
Called when owner calls the 'drink' command.
"""
if not self.do_empty():
drinker.msg("The vial is empty.")
else:
drinker.announce_action("$You() $conj(<< down ^ quaff ^ imbibe >>) a small vial.")
drinker.scripts.add(self.db.spell, autostart=True)
class Potion(Object):
"""
A marker-type object for a potion in the cauldron.
"""
pass
# ----------------------------------------------------------------------
# Scripts that emulate the effects of Potions
# ----------------------------------------------------------------------
class LaughterSpell(Script):
"""
This class defines the script itself
"""
def at_script_creation(self):
self.key = "laughter-spell"
self.desc = "Adds various timed events to a character."
self.interval = 20 # seconds
self.repeats = 15 # repeat only a certain number of times
self.start_delay = True # wait self.interval until first call
def at_repeat(self):
"""
This gets called every self.interval seconds. We make
a random check here so as to only return 33% of the time.
"""
if random() < 0.66:
# no message this time
return
self.send_random_message()
def send_random_message(self):
rand = randint(1, 10)
if rand == 1:
msg = "$You() $conj(erupt) into laughter, a deep, rolling sound that fills the room and makes everyone turn to see whats so funny."
elif rand == 2:
msg = "$You() $conj(let) out a series of high-pitched giggles, each one bubbling up like a fizzy drink, light and infectious."
elif rand == 3:
msg = "$You() $conj(burst) into cackling laughter, the sharp, gleeful sound that echo off the walls."
elif rand == 4:
msg = "$You() $conj(find) yourself wheezing with laughter, gasping for air as the hilarity overwhelms you, tears streaming down your cheeks."
elif rand == 5:
msg = "$You() $conj(break) into a fit of snorting giggles; you try to surpress them to no avail."
elif rand == 6:
msg = "$You() $conj(let) out a tinkling laugh, a melodic sound that dances through the air, bringing a sense of whimsy to the moment."
elif rand == 7:
msg = "$You() $conj(roar) with laughter, a booming sound that resonates with joy."
elif rand == 8:
msg = "$You() $conj(chuckle) softly, a warm and genuine sound that reflects your delight."
elif rand == 9:
msg = "$You() $conj(giggle) uncontrollably, making it hard for $pron(you) to catch $pron(your) breath."
else:
msg = "$You() $conj(let) a stifled chuckle, unsure what became so humorous."
self.obj.announce_action(msg)

View file

@ -60,6 +60,34 @@ class Consumable(Object):
self.delete()
class Herb(Object):
"""
Essentially a marker for something that can go in a cauldron.
"""
pass
class Edible(Consumable):
"""
Like a Consumable, but this packs a punch.
When eaten, it kicks off a temporary script that acts like a
spell.
"""
def do_eat(self, eater):
"""
Consume (eat) AND destroy this object.
We assume one dose is sufficient.
"""
msg = self.db.eat_msg or f"You take a bite of {self.name}."
eater.msg(routput(msg))
self.delete()
if self.db.spell:
eater.scripts.add(self.db.spell, autostart=True)
elif self.db.spell_msgs:
eater.delay_sequence(self.db.spell_msgs)
class Producer(Object):
"""
An object that produces a Consumable object.
@ -123,6 +151,11 @@ class Producer(Object):
if self.db.make_finish_msgs:
consumable.db.finish_msgs = self.db.make_finish_msgs
if self.db.make_spell:
consumable.db.spell = self.db.make_spell
if self.db.make_spell_msgs:
consumable.db.spell_msgs = self.db.make_spell_msgs
consumable.location = picker
picker.announce_action(f"$You() {self.db.make_verb or '$conj(get)'} {self.db.make_name}{self.db.make_note or ''}.")

View file

@ -4,84 +4,264 @@ from evennia.prototypes.spawner import spawn
from evennia.utils import logger
from typeclasses.objects import Object
from commands.consumables import CmdSetTeapot
from commands.consumables import CmdSetTeapot, CmdSetFillable
from utils.word_list import routput, choices
import re
import random
TEA_TYPES = {
'black': 'a rich, bold and <<malty ^ fragrant ^ almost spicy>> black tea',
'green': 'a green tea with <<grassy ^ floral ^ vanilla ^ vegetal>> notes',
'oolong': 'a complex and <<earthy ^ floral>> oolong',
'matcha': 'a frothy and aromatic matcha of the most vibrant green',
'white': 'a subtle tea with notes of <<rose ^ berries ^ chamomile flowers>>',
'pu-erh': 'an earthy, almost mushroom flavored, pu-erh tea',
'puerh': 'an earthy, almost mushroom flavored, pu-erh tea',
'barley': 'a nutty herbal infusion of barley with just a hint of smokiness',
'chaga': 'an earthy, mushroomy chaga infusion',
'hibiscus': 'a dark red, tart herbal infusion of roselle flowers',
'chai': 'a spicy chai tea, tempered with milk and sweetness',
'herbal': 'an herbal infusion of <<chamomile ^ mint ^ chicory root ^ lavender>>',
'earl': 'a flowery Earl Grey tea',
'chamomile': 'a relaxing, yet subtle infusion of chamomile flowers that makes you want to go to sleep',
'mint': 'a blend of peppermint and spearmint to create the ultimate minty herbal infusion',
'chrysanthemum': 'a lovely, floral infusion of chrysanthemum flowers',
'dandelion': 'a roasted herbal infusion of dandelions that tastes a bit like coffee',
'rooibos': 'an almost <<sweet and ^ >> <<woody ^ nutty ^ vanilla-y>> rooibos herbal infusion',
# Why limit to teas ... sure, this tea pot could make coffee ...
}
FILL_TEA_MSGS = [
'You fill your <<teacup ^ cup>> with {1}.',
'You pour <<some ^ >> {0} tea into your <<teacup ^ cup>>.',
]
def choose_drink(drink_list, name=None, rando=True):
"""
Return an entry from 'drink_list'.
DRINK_TEA_MSGS = [
'You take a sip of {0} tea.',
'You take a sip of {0} tea <<in ^ from>> your <<teacup ^ cup>>.',
'You <<sip ^ sample ^ drink>> from your <<teacup ^ cup>>.',
'You savor {1} in your <<teacup ^ cup>>.',
]
The 'name' must match an entry with a similar 'title' key.
The drink_list should be a list of dicts.
"""
if name and name != "":
rx = rf".*{name}.*"
# logger.info(f"Working on {rx}")
details = [c for c in drink_list
if re.match(rx, c.get("title"), re.IGNORECASE) or
name in c.get("aliases", [])]
if len(details) > 0:
return details[0]
EMPTY_TEA_MSGS = [
'Your <<teacup ^ cup>> is empty. Perhaps you can |gmake|n some |gtea|n?',
"Your cup certainly doesn't runneth over, as it be quite empty.",
'Alas, you find your cup devoid of any sort of watery infusion.',
'You notice your cup is empty.',
'It appears that you need to refill your tea cup.'
if rando:
return random.choice(drink_list)
return None
TEAS = [
{"title": "black",
"desc": "a rich, bold and <<malty ^ fragrant ^ almost spicy>> black tea",
},
{"title": "green",
"desc": "a green tea with <<grassy ^ floral ^ vanilla ^ vegetal>> notes",
},
{"title": "oolong",
"desc": "a complex and <<earthy ^ floral>> oolong",
},
{"title": "rooibos",
"desc": "an almost <<sweet and ^ >> <<woody ^ nutty ^ vanilla-y>> rooibos herbal infusion",
},
{"title": "dandelion",
"desc": "a roasted herbal infusion of dandelions that tastes a bit like coffee",
},
{"title": "mint",
"desc": "a blend of peppermint and spearmint to create the ultimate minty herbal infusion",
},
{"title": "chamomile",
"desc": "a relaxing, yet subtle infusion of chamomile flowers that makes you want to go to sleep",
},
{"title": "earl",
"desc": "a flowery Earl Grey tea",
},
{"title": "herbal",
"desc": "an herbal infusion of <<chamomile ^ mint ^ chicory root ^ lavender>>",
},
{"title": "chai",
"desc": "a spicy chai tea, tempered with milk and sweetness",
},
{"title": "hibiscus",
"desc": "a dark red, tart herbal infusion of roselle flowers",
},
{"title": "matcha",
"desc": "a frothy and aromatic matcha of the most vibrant green"
},
{"title": "white",
"desc": "a subtle tea with notes of <<rose ^ berries ^ chamomile flowers>>",
},
{"title": "pu-erh",
"desc": "an earthy, almost mushroom flavored, pu-erh tea",
},
{"title": "puerh",
"desc": "an earthy, almost mushroom flavored, pu-erh tea",
},
{"title": "barley",
"desc": "a nutty herbal infusion of barley with just a hint of smokiness",
},
{"title": "chaga",
"desc": "an earthy, mushroomy chaga infusion",},
{
"title": "",
"desc": "",
},
]
class TeaCup(Object):
class Container(Object):
"""
All re-fillable cups, glasses and bottles inherit from this object.
Database settings:
type: "tea"
details:
"""
# Defaults
sip_amount = 1
fill_amount = 1
details = {"title": "unknown liquid",
"desc": "Not sure what this is."}
empty_msgs = ["It is empty."]
drink_msgs = [
'You take a <<sip ^ sample ^ swig ^ drink>> << of {0}^ >> << ^ from your {2} >>.',
'You <<sip ^ sample ^ swig ^ drink>> some of your {0} << ^ from your {2} >>.',
]
fill_msgs = ["$You() $conj(fill) $pron(your) {2} with {0}."]
def at_object_creation(self):
"""
called at creation
"""
self.db.amount = 0
def do_drink(self, drinker):
"""
Drink command results, gives a message to drinker.
And lowers the amount by the 'sip_amount'.
When empty, resets the container description to its
'empty_desc' setting.
"""
amount = self.db.amount or 0
details = self.db.details or self.details or {}
sip_amount = self.db.sip_amount or self.sip_amount or 1
if amount == 0:
drinker.msg(choices(self.empty_msgs, details["title"],
details["desc"], self.name))
else:
self.db.amount = amount - sip_amount
drinker.msg(choices(self.drink_msgs, details["title"],
details["desc"], self.name))
if self.db.amount == 0:
self.db.desc = self.db.empty_desc
def do_empty(self):
"""
Return the title of the contents and empty the container.
If already empty, return None.
"""
if self.db.amount == 0:
return None
details = self.db.details or self.details or {}
results = (details["title"], self.db.amount, self.db.desc)
self.db.amount = 0
if self.db.empty_name:
self.key = self.db.empty_name
if self.db.empty_desc:
self.db.desc = self.db.empty_desc
return results
def do_fill(self, filler, details):
"""
Fill this container with 'details'.
The containers description will match the contents.
"""
if self.db.amount > 0:
already_full = True
else:
already_full = False
# Render and restore the description:
desc = routput(details['desc'])
details['desc'] = desc
self.db.details = details
self.db.amount = self.db.fill_amount or self.fill_amount or 1
if already_full:
msg = f"$You() $conj(empty) $pron(your) {self.name} and then $pron(you) $conj(fill) it with {desc}"
else:
msg = choices((self.db.fill_msgs or self.fill_msgs),
details["title"], desc, self.name)
# Save the current description as the "empty" description,
# for re-using later.
if not self.db.empty_desc:
self.db.empty_desc = self.db.desc
self.db.desc = f"Contains {desc}"
filler.announce_action(msg)
def at_pre_drop(self, dropper):
"""
Let's keep this world tidy.
"""
dropper.announce_action(f"$You() $conj(drop) the {self.name}, shattering it.")
self.delete()
class Bottle(Container):
"""
Generic large container that can be filled.
"""
fill_amount = 8
empty_msgs = [
'Your {2} is empty. Perhaps you can |gfill|n it?',
'It appears that you need to fill your {2}.'
]
def at_object_creation(self):
"""
called at creation
"""
self.db.amount = 0
class Water(Object):
"""
Object that contains water or other fillable liquid.
You must set the following:
@set this/fill_name = "water"
@set this/fill_desc = "fizzy water with bubbles trapped from waterfall."
"""
def at_object_creation(self):
"""
called at creation
"""
self.cmdset.add_default(CmdSetFillable, persistent=True)
class TeaCup(Container):
fill_amount = 4
sip_amount = 1
def do_drink(self, drinker):
amount = self.db.amount or 0
tea_type = self.db.tea_type or "tea"
tea_details = self.db.tea_details
drink_msgs = [
'You take a sip of {0} tea.',
'You take a sip of {0} tea <<in ^ from>> your <<teacup ^ cup>>.',
'You <<sip ^ sample ^ drink>> from your <<teacup ^ cup>>.',
'You savor {1} in your <<teacup ^ cup>>.',
]
if amount > 0:
self.db.amount = self.db.amount - self.sip_amount
drinker.msg(choices(DRINK_TEA_MSGS, tea_type, tea_details))
else:
drinker.msg(choices(EMPTY_TEA_MSGS, tea_type, tea_details))
empty_msgs = [
'Your <<teacup ^ cup>> is empty. Perhaps you can |gmake|n some |gtea|n?',
"Your cup certainly doesn't runneth over, as it be quite empty.",
'Alas, you find your cup devoid of any sort of watery infusion.',
'You notice your cup is empty.',
'It appears that you need to refill your tea cup.'
]
def do_fill(self, drinker, tea_type, tea_details):
self.db.tea_type = tea_type
self.db.tea_details = tea_details
self.db.amount = self.fill_amount
drinker.msg(choices(FILL_TEA_MSGS, tea_type, tea_details))
fill_msgs = [
'You fill your <<teacup ^ cup>> with {1}.',
'You pour <<some ^ >> {0} tea into your <<teacup ^ cup>>.',
]
def at_pre_drop(self, dropper):
if dropper.location.key == "Dabbler's House":
dropper.msg("You place the teacup on the trolley with the others.")
if dropper.location.key in ("Cozy House", "Cramped Kitchen"):
dropper.announce_action("$You() $conj(wash) and $conj(replace) the teacup in the cabinet with the others.")
self.delete()
else:
return True
class Teapot(Object):
def at_object_creation(self):
"""
@ -96,30 +276,25 @@ class Teapot(Object):
If 'args', try to make a particular type of tea, otherwise,
pick one at random.
"""
tea_choice = []
if not words.empty():
tea_choice = [tea for tea in TEA_TYPES.keys() if words.contains(tea)]
if len(tea_choice) > 0:
self.db.tea_type = tea_choice[0]
else:
self.db.tea_type = random.choice(list(TEA_TYPES.keys()))
desc = routput(TEA_TYPES[self.db.tea_type])
tea_choice = choose_drink(TEAS, words)
desc = routput(tea_choice['desc'])
self.db.tea_choice = tea_choice
self.db.desc = f"A large, brown teapot full of {desc}."
drinker.announce_action(f"$You() $conj(make) a teapot of {desc}.")
def do_fill(self, drinker):
teatype = self.db.tea_type
teatype = self.db.tea_choice
if not teatype:
drinker.msg("You need to |gmake tea|n first.")
return
teacup = drinker.has("teacup")
if teacup:
teacup.do_fill(drinker, teatype, TEA_TYPES[teatype])
else:
if not teacup:
drinker.msg("You need to |gget teacup|n first.")
return
teacup.do_fill(drinker, self.db.tea_choice)
COCKTAILS = [
@ -295,7 +470,7 @@ COCKTAILS = [
"Your liver is thanking you."
]
},
]
]
DRINK_COCKTAIL_MSGS = [
# 0 -> drink title or name
@ -323,16 +498,7 @@ class Cocktail(Object):
Create for 'owner', a drink that matches 'name'.
If name doesn't match, get a random one.
"""
if name:
rx = r".*" + name + r".*"
details = [c for c in COCKTAILS
if re.match(rx, c.get("title"), re.IGNORECASE) or
name in c.get("aliases", [])]
if len(details) > 0:
details = details[0]
else:
details = random.choice(COCKTAILS)
details = choose_drink(COCKTAILS, name, rando=False)
if not details or details == []:
shaker.msg(f"No match for '{name}'.")
return
@ -383,8 +549,8 @@ class Cocktail(Object):
if dropper.location.key == 'Wyldwood Bar':
dropper.msg(routput(f"<< A ^ The >> mushroom << man ^ person >> << bounces ^ shimmies over ^ appears >> and takes the {self.name} << from you ^ >>."))
self.delete()
elif dropper.location.key == "Dabbler's House":
dropper.msg(routput(f"The {self.db.cocktail_type} << falls ^ drops >> to the << floor ^ ground >> and shatters! A dust ball from under the chair forms into a little impish-looking fellow, who cleans it all before disappearing."))
elif dropper.location.key in ("Cozy House", "Cramped Kitchen"):
dropper.msg(routput(f"The {self.db.cocktail_type} << falls ^ drops >> to the << floor ^ ground >> and shatters! A dust ball from under a chair forms into a little impish-looking fellow, who disappears with glass."))
self.delete()
else:
return True

View file

@ -1,20 +1,49 @@
Covered in herbs, mushrooms and moss, this land invites me to produce potions. To work such craft, one must have the proper equipment, which I imported from Twilight Spire outside Mistwood. Most experiments have been successful, and I record them here.
|BEver Laughter|n
|BElixir Risorium|n
While saccharine, this potion induces a state of euphoria finding everything, including one's own thoughts, hilarious.
Enjoyable, and easy to make.
|wIngredients|n
- 2 Gigglecap mushrooms
- 4 Brambleberries
- 1 bottle of bubblefizz water
- 1 Gigglecap mushrooms
- 1 Bunch of tickleweed
- 2 cups of fizzy water
Step 1, |gcrush|n the brambleberries into a paste
I have found Gigglecaps growing on well drained, rocky soil and even on rocks. Tickleweed loves the frothy, bubbly water that comes from the meadow's waterfall. This place too is where I collect the fizzy water.
|wProcedure|n
Step 1, |gempty|n the cauldron
Step 2. |gadd|n all ingredients to the caldron
Step 3. |gmix|n under a low heat
Step 3. |gcreate|n the potion using a low heat and the magic incantation
Step 4. |gbottle|n the concoction into a vial
...interestingly, the rest of the book is blank...
I have taught |mImpetus|n the incantation for the spell, which makes brewing potions much easier and quicker. Just remember to stir the potion with the wooden spoon.
|BSomnium Illusorium|n
This fascinating potion can create a dream-like state while awake, including visions of sight and sound. One must be careful with this, as it could disrupt one perception of reality.
|wIngredients|n
- 1 handful of Moonberries
- 1 Dreamshade mushroom
- 1 small sack of Pixie Dust
- 1 cup of fresh, still water
The moonberries grow under conifers, and I find I often have to travel to one of the islands on the Lavender Sea to collect these. Dreamshades (Lunara Mycelium) feed on floating dreams, and often congregate where dreamers sleep.
I have found Gigglecaps growing on well drained, rocky soil and even on rocks. Tickleweed loves the frothy, bubbly water that comes from the meadow's waterfall. This place too is where I collect the fizzy water.
Ive noticed Pixies often dance in the marshlands to the East, but are often invisible except in the evenings. Ive attempted to discuss a trade for pixie dust, but often luck out as they often pay more attention to their choreography than any trinkets I could produce.
|wProcedure|n
Step 1, |gempty|n the cauldron
Step 2. |gadd|n all ingredients to the caldron
Step 3. |gcreate|n the potion by stirring the potion clockwise for exactly seven rotations
Step 4. |gbottle|n the concoction into a vial
|bNote: This is still a work in progress... What do you think of this idea? You would gather herbs and whatnot, put them in the cauldron and then make potions! Seems intriguing...|n

215
world/update4.ev Normal file
View file

@ -0,0 +1,215 @@
# Laughing Potion
# Need a script….
# Colorful gigglecaps prefer well drained locations to grow, like on the top of boulders.
# [[file:../../../projects/mud.org::*Laughing Potion][Laughing Potion:1]]
@teleport/quiet mp02
#
@create/drop patch of mushrooms;mushrooms;mushroom: typeclasses.consumables.Producer
#
@desc mushrooms = A vibrant patch of mushrooms bursts forth like a painter's palette, each cap shimmering with iridescent hues of violet, emerald, and gold. Their delicate stems sway gently in the enchanted breeze...wait, you feel no breeze. They seem to be undulating with unheard laughter.
#
@set mushrooms/make_name = "gigglecap mushroom"
#
@set mushrooms/make_verb = "$conj(harvest) a"
#
@set mushrooms/make_class = "typeclasses.consumables.Edible"
#
@set mushrooms/make_desc = "A whimsical fungi emits a soft, melodic laughter when touched."
#
@set mushrooms/make_amount = 1
#
@set mushrooms/make_spell_msgs = "10 ;; $You() $conj(<< giggle ^ chuckle ^ chortle >>) out loud."
# Laughing Potion:1 ends here
# This purple grass, often called tickleweed since it vibrates as if laughing, can be found in fields and meadows throughout the area.
# [[file:../../../projects/mud.org::*Laughing Potion][Laughing Potion:2]]
@teleport/quiet mp05
#
@create/drop patch of tickleweed;tickleweed: typeclasses.consumables.Producer
#
@desc tickleweed = Patches of this vivid grass vibrates as if giggling.
#
@set tickleweed/make_name = "bunch of tickleweed"
#
@set tickleweed/make_verb = "$conj(harvest) a"
#
@set tickleweed/make_class = "typeclasses.consumables.Herb"
#
@set tickleweed/make_desc = "This grass vibrates as if giggling."
#
@set tickleweed/make_amount = 1
# Laughing Potion:2 ends here
# And some fizzy water;
# [[file:../../../projects/mud.org::*Laughing Potion][Laughing Potion:3]]
@teleport/quiet mp05
#
@create/drop stream;water: typeclasses.drinkables.Water
#
@desc stream = A slow-moving stream meanders like a snake in the grassy field. The water, fizzy with bubbles from the waterfall torrent, creates an efforvesent aroma. Little green |Yfrogs|n cling to grass stems hanging over the sparkling water.
#
@lock stream = get:false()
#
@set stream/get_err_msg = "Seriously? You can't get that. Perhaps a bottle, or at least a cup, could hold the fizzy water."
#
@set stream/fill_name = "fizzy water"
#
@set stream/fill_desc = "sparkling water from waterfall turbulence."
#
@set stream/fill_msgs = ["$You() $conj(<< get ^ kneel >>) down, and $conj(fill) $pron(your) {2} with sparkling efforvesence.", "$You() $conj(<< get ^ kneel >>) down, and $conj(put) $pron(your) {2} in the cool water, filling it."]
# Laughing Potion:3 ends here
# Trippy Potion
# After ingesting this potion, they may see hallucinations and nightmares. It would be nice if these dreams could incorporate the room state.
# Ive noticed Pixies often dance in the marshlands to the East, but are often invisible except in the evenings. Ive attempted to discuss a trade for pixie dust, but often luck out as they often pay more attention to their choreography than any trinkets I could produce.
# [[file:../../../projects/mud.org::*Trippy Potion][Trippy Potion:1]]
@teleport/quiet mp08
#
@create/drop patch of glitter;pixie dust;dust: typeclasses.consumables.Producer
#
@desc pixie dust = As you look at reeds and marsh grass, you notice the shiny glitter is actually dander from pixies... pixie dust. With a little effort, you could gather a small sack of it.
#
@set pixie dust/make_name = "sack of pixie dust"
#
@set pixie dust/make_verb = "$conj(collect) and $conj(fill) a"
#
@set pixie dust/make_class = "typeclasses.objects.Object"
#
@set pixie dust/make_desc = "Small bag of the good, shiny stuff."
#
@set pixie dust/make_amount = 1
# Trippy Potion:1 ends here
# Fresh spring water should be in the Grotto, right?
# [[file:../../../projects/mud.org::*Trippy Potion][Trippy Potion:2]]
@teleport/quiet mp04
#
@create/drop stream;water: typeclasses.drinkables.Water
#
@lock stream = get:false()
#
@set stream/get_err_msg = "Seriously? You can't get that. Perhaps a bottle, or at least a cup, could hold the fresh water."
#
@desc stream = A small stream, almost hidden behind the ferns and brambleberry bushes, drops down a lush hill, creating a lush, relaxing feeling. The water looks fresh and pure.
#
@set stream/fill_name = "still water"
#
@set stream/fill_desc = "fresh spring water."
#
@set stream/fill_msgs = ["$You() $conj(<< get ^ kneel >>) down, and $conj(fill) $pron(your) {2} with the << spring ^ fresh ^ refreshing >> water.", "$You() $conj(<< get ^ kneel >>) down, and $conj(put) $pron(your) {2} in the cool water, filling it."]
# Trippy Potion:2 ends here
# Dreamshade mushrooms feed on floating dreams, and often congregate where dreamers sleep.
# [[file:../../../projects/mud.org::*Trippy Potion][Trippy Potion:3]]
@teleport/quiet mp07
#
@create/drop cluster of mushrooms;mushroom: typeclasses.consumables.Producer
#
@desc mushrooms = Slender blue tendrils of a fungus encircle the base of the mattress.
#
@set mushrooms/make_name = "sack of mushrooms"
#
@set mushrooms/make_verb = "$conj(collect) and $conj(fill) a"
#
@set mushrooms/make_class = "typeclasses.consumables.Edible"
#
@set mushrooms/make_desc = "Small collection of slender, blue mushrooms."
#
@set mushrooms/make_amount = 1
#
@set mushrooms/make_spell_msgs = "10 ;; $You() $conj(nod) off, as $pron(your) head bobbles and bounces. ;; 5 ;; $You() $conj(awaken) with a start."
# Trippy Potion:3 ends here
# The moonberries grow under conifers, and I find I often have to travel to one of the islands on the Lavender Sea to collect these.
# [[file:../../../projects/mud.org::*Trippy Potion][Trippy Potion:4]]
@teleport/quiet gr02
#
@create/drop moonberries;moonberry;berry: typeclasses.consumables.Producer
#
@desc moonberries = Growing a slender vines that wrap around the trunks of the pine trees. Laden with small, blue berries, each reflecting a white cresent shape.
#
@set moonberries/make_name = "handful of moonberries"
#
@set moonberries/make_verb = "$conj(collect) a"
#
@set moonberries/make_class = "typeclasses.objects.Edible"
#
@set moonberries/make_desc = "Blue berries with a white cresent shape."
#
@set moonberries/make_amount = 1
#
@set moonberries/make_eat_msg = "Slightly bitter. Not very good."
#
@set mushrooms/make_spell_msgs = "10 ;; $You() $conj(nod) off, as $pron(your) head bobbles and bounces. ;; 5 ;; $You() $conj(awaken) with a start."
# Trippy Potion:4 ends here
# Other
# Well get ready by allowing one to collect water from _all_ the places, like the salty sea:
# [[file:../../../projects/mud.org::*Other][Other:1]]
@teleport/quiet mp06
#
@create/drop lavender sea;sea;water;bay: typeclasses.drinkables.Water
#
@desc sea = A gently waving sea. Too bad the shore doesn't respond with a greeting of its own.
#
@lock sea = get:false()
#
@set sea/get_err_msg = "You can only hold the sea in your heart. Perhaps a bottle, or at least a cup, could hold the salty water."
#
@set sea/fill_name = "salt water"
#
@set sea/fill_desc = "salty water with a purple hue."
#
@set sea/fill_msgs = ["$You() $conj(reach) down from the dock, and $conj(fill) $pron(your) {2} with the << salty ^ lavender ^ fragrant >> water."]
# Other:1 ends here
# And the muddy marsh:
# [[file:../../../projects/mud.org::*Other][Other:2]]
@teleport/quiet mp08
#
@create/drop river;stream;water: typeclasses.drinkables.Water
#
@lock river = get:false()
#
@set river/get_err_msg = "Slippery things, those rivers. Seems you would need a bottle, or at least a cup to hold the muddy water."
@desc stream = A muddy, almost stagnant river. Smells like a fecund stew of moist dirt and decomposing swamp herbage.
#
@set stream/fill_name = "muddy water"
#
@set stream/fill_desc = "muddy water from the marsh."
#
@set stream/fill_msgs = ["$You() $conj(<< get ^ kneel >>) down, and $conj(fill) $pron(your) {2} with the muddy water."]
# Other:2 ends here

View file

@ -629,132 +629,121 @@ py timed_script = evennia.create_script(key="Create Sticks",
# And lets hide it until we are ready:
# [[file:../../../projects/mud.org::*Beast][Beast:2]]
@set beast/hidden_tag = "hidden_beast"
#
@lock beast = view:tag(hidden_beast)
# Beast:2 ends here
# And a general description that will be /expanded/ with its current reaction.
# [[file:../../../projects/mud.org::*Beast][Beast:3]]
# [[file:../../../projects/mud.org::*Beast][Beast:2]]
@desc beast = A big, hairy beast with long claws and teeth.
# Beast:3 ends here
# Beast:2 ends here
# Cant get this:
# [[file:../../../projects/mud.org::*Beast][Beast:4]]
# [[file:../../../projects/mud.org::*Beast][Beast:3]]
@lock beast = get:false()
#
@set beast/get_err_msg = "You can't pick that up, as that beast is far larger than you."
# Beast:4 ends here
# Beast:3 ends here
# And set its sleepy time at 8pm …
# [[file:../../../projects/mud.org::*Beast][Beast:5]]
# [[file:../../../projects/mud.org::*Beast][Beast:4]]
@set beast/sleep_hour = 21
# Beast:5 ends here
# Beast:4 ends here
# It will wake at 8am …
# [[file:../../../projects/mud.org::*Beast][Beast:6]]
# [[file:../../../projects/mud.org::*Beast][Beast:5]]
@set beast/wake_hour = 8
# Beast:6 ends here
# Beast:5 ends here
# Lets set some behavior levels. For instance, the beast is sad when he doesnt see its friends:
# [[file:../../../projects/mud.org::*Beast][Beast:7]]
# [[file:../../../projects/mud.org::*Beast][Beast:6]]
@set beast/loneliness_amount = -2
# Beast:7 ends here
# Beast:6 ends here
# It seem to warm up the to new characters hanging around the area, but not as much as those that would interact with it:
# [[file:../../../projects/mud.org::*Beast][Beast:8]]
# [[file:../../../projects/mud.org::*Beast][Beast:7]]
@set beast/shyness_amount = 3
# Beast:8 ends here
# Beast:7 ends here
# How active should this pet be? Seems like at the moment, it shouldnt be too obnoxious. This setting is a percentage, so 12 is /12%/, which returns a message only 12% of the /ticks/ (where a tick is about a minute).
# [[file:../../../projects/mud.org::*Beast][Beast:9]]
# [[file:../../../projects/mud.org::*Beast][Beast:8]]
@set beast/active_amount = 10
# Beast:9 ends here
# Beast:8 ends here
# It isnt that scared of new people, as it will ignore them when someone it knows is around.
# [[file:../../../projects/mud.org::*Beast][Beast:10]]
# [[file:../../../projects/mud.org::*Beast][Beast:9]]
@set beast/new_character_reaction = 'ignores'
# Beast:10 ends here
# Beast:9 ends here
# Seems we should make descriptions for all the states that happen when you look at them. These are appended to the standard description.
# [[file:../../../projects/mud.org::*Beast][Beast:11]]
# [[file:../../../projects/mud.org::*Beast][Beast:10]]
@set beast/scared_msg = "It seems <<skiddish ^ afraid ^ skiddish and afraid>> as it tries to hide behind a tall clump of grass. Yeah, it doesn't do a good job of hiding."
# Beast:11 ends here
# Beast:10 ends here
# Concerned level:
# [[file:../../../projects/mud.org::*Beast][Beast:12]]
# [[file:../../../projects/mud.org::*Beast][Beast:11]]
@set beast/concerned_msg = "Its large, yellow eyes stare at you from a safe distance."
# Beast:12 ends here
# Beast:11 ends here
# Interested level:
# [[file:../../../projects/mud.org::*Beast][Beast:13]]
# [[file:../../../projects/mud.org::*Beast][Beast:12]]
@set beast/interested_msg = "It seems <<curious ^ interested>> in what you are doing <<here ^ >>. ;; Its << ^ large, ^ big,>> yellow eyes watch your every move."
# Beast:13 ends here
# Beast:12 ends here
# Friendly level:
# [[file:../../../projects/mud.org::*Beast][Beast:14]]
# [[file:../../../projects/mud.org::*Beast][Beast:13]]
@set beast/friendly_msg = "It sits next to you, as its big, friendly eyes gaze as you. ;; It <<leaps over ^ runs up ^ bounces up ^ >> to you, wagging its tail-less behind. ;; It lays down next to you."
# Beast:14 ends here
# Beast:13 ends here
# When the beast is sleeping, we can some times spam the room with the snores:
# [[file:../../../projects/mud.org::*Beast][Beast:15]]
# [[file:../../../projects/mud.org::*Beast][Beast:14]]
@set beast/sleeping_actions = "The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> lets loose a <<big, ^ huge, ^ large, ^ tremendous, ^ >> snore. ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> growls in its sleep. ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> twitches its <<leg ^ legs ^ paw ^ nose>>. ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> <<shifts ^ rolls>> on its <<big, ^ huge, ^ large, ^ tremendous, ^ >> mattress."
# Beast:15 ends here
# Beast:14 ends here
@ -763,9 +752,9 @@ py timed_script = evennia.create_script(key="Create Sticks",
# The scared level doesnt last long, so lets just leave one message:
# [[file:../../../projects/mud.org::*Beast][Beast:16]]
# [[file:../../../projects/mud.org::*Beast][Beast:15]]
@set beast/scared_actions = "A shadow hovers at the edge of the meadow.."
# Beast:16 ends here
# Beast:15 ends here
@ -773,43 +762,43 @@ py timed_script = evennia.create_script(key="Create Sticks",
# Concerned actions:
# [[file:../../../projects/mud.org::*Beast][Beast:17]]
# [[file:../../../projects/mud.org::*Beast][Beast:16]]
@set beast/concerned_actions = "The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> <<is ^ seems>> concerned by your presence in the <<meadow ^ field>>. ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> seems concerned. Maybe it's hungry. ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> seems concerned and keeps its distance."
# Beast:17 ends here
# Beast:16 ends here
# Interested actions:
# [[file:../../../projects/mud.org::*Beast][Beast:18]]
# [[file:../../../projects/mud.org::*Beast][Beast:17]]
@set beast/interested_actions = "The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> seems <<curious ^ interested>> in $you(). ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> seems curious about $you(). ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> stands on its hind legs. ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> <<stares at ^ watches ^ follows>> $you() with its <<large, ^ big, ^ >> yellow eyes."
# Beast:18 ends here
# Beast:17 ends here
# Friendly actions:
# [[file:../../../projects/mud.org::*Beast][Beast:19]]
# [[file:../../../projects/mud.org::*Beast][Beast:18]]
@set beast/friendly_actions = "The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> <<thunders ^ stomps ^ tramps ^ clomps ^ rumbles ^ rolls>> <<across the field ^ across the meadow ^ over>> wagging its backend<<, ^ as it seems>> happy to see $you(). ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> <<thunders ^ stomps ^ tramps ^ clomps ^ rumbles ^ rolls>> <<across the field ^ across the meadow ^ over>> hoping to play with $you(). ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> flops over in front of $you() wriggling <<its back ^ >> on the ground. ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> <<thunders ^ stomps ^ tramps ^ clomps ^ rumbles ^ rolls>> <<across the field ^ across the meadow ^ over>> next to $you(). ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> chases butterflies around the <<field ^ meadow ^ grass ^ flowers>>."
# Beast:19 ends here
# Beast:18 ends here
# The ecstatic states are just a bit more than friendly.
# [[file:../../../projects/mud.org::*Beast][Beast:20]]
# [[file:../../../projects/mud.org::*Beast][Beast:19]]
@set beast/ecstatic_actions = "The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> <<thunders ^ stomps ^ tramps ^ clomps ^ rumbles ^ rolls>> <<across the field ^ across the meadow ^ over>> to give $you() a sloppy <<kiss ^ lick>>. ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> <<thunders ^ stomps ^ tramps ^ clomps ^ rumbles ^ rolls>> <<across the field ^ across the meadow ^ over>> wagging its backend as it seems <<very ^ >> excited to see $you(). ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> <<thunders ^ stomps ^ tramps ^ clomps ^ rumbles ^ rolls>> <<across the field ^ across the meadow ^ over>> hoping to play with $you(). ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> flops over in front of $you() happily wriggling on the ground. ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> excitedly <<thunders ^ stomps ^ tramps ^ clomps ^ rumbles ^ rolls>> <<across the field ^ across the meadow ^ over>> next to you. ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> <<happily ^ joyfully>> leaps into air. ;; The <<big, ^ huge, ^ large, ^ tremendous, ^ >> <<hairy ^ slobbery ^ horned ^ clawed ^ >> <<brute ^ beast ^ monster>> chases butterflies around the <<field ^ meadow ^ grass ^ flowers>>."
# Beast:20 ends here
# Beast:19 ends here
# And the responses to being /pet/:
# [[file:../../../projects/mud.org::*Beast][Beast:21]]
# [[file:../../../projects/mud.org::*Beast][Beast:20]]
@set beast/pet_scared_response = "$You() can't get near the wild beast to pet it. It seems scared."
#
@set beast/pet_concerned_response = "$You can't get near the big, hairy beast to pet it. It seems concerned."
@ -819,7 +808,7 @@ py timed_script = evennia.create_script(key="Create Sticks",
@set beast/pet_friendly_response = "The << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> << flops ^ rolls >> over << in the grass ^>> as $you() $conj(give) it belly rubs. ;; The << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> << flops ^ rolls >> over << in the grass ^>> as $you() $conj(rub) its belly. ;; $You() $conj(pet) the << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> . ;; $You() $conj(scratch) the << nose ^ ears >> of the << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>>. ;; The << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> leans forward as $you() $conj(scratch) its nose."
#
@set beast/pet_ecstatic_response = "While << excited ^ ecstatic ^ squirmy >>, the << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> << lays ^ gets >> down so $you() can << pet ^ scratch >> << the top of its head ^ the back of its neck ^ its nose ^ the sides of its face >>. It closes its eyes and purrs. ;; << The squirmy little devil. ^ >> $conj(You) << can ^ >> << barely ^ hardly >> scratch the << nose ^ ears ^ neck ^ top of the head >> of the << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> as it << squirms around ^ wriggles it backend >>. It << can hardly ^ can't >> contain its excitement. ;; The << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> wriggles around before << flopping ^ rolling >> over << in the grass ^>> as $you() $conj(give) it belly rubs. ;; The << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> wriggles and squirms excitedly before it << flops ^ rolls >> over << in the grass ^>> as $you() $conj(rub) its belly."
# Beast:21 ends here
# Beast:20 ends here
# Mellow Marsh
# The river from the [[Field]] flows into a marsh:
@ -984,6 +973,10 @@ py timed_script = evennia.create_script(key="Create Sticks",
# [[file:../../../projects/mud.org::*Purple Heron][Purple Heron:1]]
@create/drop purple heron: typeclasses.npcs.Eliza
#
@lock purple heron = get:false()
#
@set purple heron/get_err_msg = "You try to get it, but it just flies out of reach."
# Purple Heron:1 ends here
@ -1438,7 +1431,7 @@ py bt = self.search('old lady'); bt.db.pose = 'playing with a deck of cards'
# And describe this.
# [[file:../../../projects/mud.org::*The Dock][The Dock:6]]
@desc here = The dock you stand on juts into a bay of water the color of lavender flowers. Mesmerizing and calming from the way the sound of the waves lap along the shore.
@desc here = The dock you stand on juts into a sea the color of lavender flowers. Mesmerizing and calming from the way the sound of the waves lap along the shore.
Someone has set a nice chair for viewing.
# The Dock:6 ends here
@ -1448,7 +1441,7 @@ Someone has set a nice chair for viewing.
# [[file:../../../projects/mud.org::*The Dock][The Dock:7]]
@detail water;waves = Despite the inclement weather, the waves ripple softly against the shore. Seems nice for fishing.
@detail waves = Despite the inclement weather, the waves ripple softly against the shore. Seems nice for fishing.
#
@detail lavender;flowers;flower = The water is the |wcolor|n of lavender, not actually lavender. Hrm. Could it possibly be |wlavender tea|n?
#
@ -1678,85 +1671,75 @@ Someone has set a nice chair for viewing.
# The bush shouldnt be stealable:
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:3]]
@lock bush = get:true()
#
@set bush/get_err_msg = "It appears firmly attached to the ground. Perhaps you want to |gpick|n a berry?"
# Berry Bush:3 ends here
# We have to have the bush describe what it /makes/:
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:4]]
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:3]]
@set bush/make_name = "berry"
# Berry Bush:4 ends here
# Berry Bush:3 ends here
# Including some plural aliases:
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:5]]
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:4]]
@set bush/make_aliases = ["berries", "brambleberry", "brambleberries"]
# Berry Bush:5 ends here
# Berry Bush:4 ends here
# And a verb when they /get/ the consumable:
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:6]]
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:5]]
@set bush/make_verb = "$conj(pick) a"
# Berry Bush:6 ends here
# Berry Bush:5 ends here
# And the bush needs to know the /description/ of the Consumable, so that it can attach that:
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:8]]
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:7]]
@set bush/make_desc = "Bright red with flecks of orange, about grape-sized"
# Berry Bush:8 ends here
# Berry Bush:7 ends here
# How many berries are there when you pick them?
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:9]]
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:8]]
@set bush/make_amount = 1
# Berry Bush:9 ends here
# Berry Bush:8 ends here
# How many berries do you eat at a time:
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:10]]
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:9]]
@set bush/make_eat_amount = 1
# Berry Bush:10 ends here
# Berry Bush:9 ends here
# We can either have a single /eat/ message:
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:11]]
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:10]]
@set bush/make_eat_msg = "Sweet and slightly tart. <<Delicious ^ Tangy ^ Mmmm>>."
# Berry Bush:11 ends here
# Berry Bush:10 ends here
# Or many messages that can be randomly selected:
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:12]]
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:11]]
@set bush/make_eat_msgs = [ "Sweet and slightly tart.", "<<Delicious ^ Tangy ^ Mmmm>>.", "Ooo...quite sour.", "A bit ripe, but still good.", "So sweet with a hint of <<orange ^ maple>>." ]
# Berry Bush:12 ends here
# Berry Bush:11 ends here
# Let the user know when they consumed them all.
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:13]]
# [[file:../../../projects/mud.org::*Berry Bush][Berry Bush:12]]
@set bush/make_finish_msg =
#"Those were <<delicious ^ great>>."
# Berry Bush:13 ends here
# Berry Bush:12 ends here
# Knocker
# The knocker has the ability to make the door “open” using [[https://www.evennia.com/docs/latest/api/evennia.objects.objects.html][on_traverse]] hooks?
@ -2555,7 +2538,7 @@ py here.search("cabinet").do_bake()
# [[file:../../../projects/mud.org::*Inside the Secret Room][Inside the Secret Room:1]]
@teleport mp12
#
@desc here = A curious little room containing a stool next to a table covered with alchemical equipment--a testament to the arcane arts--cluttered yet meticulously organized.
@desc here = A curious little room containing a stool next to a table covered with alchemical equipment--a testament to the arcane arts--cluttered yet meticulously organized. Oh, and a few empty bottles.
# Inside the Secret Room:1 ends here
@ -2660,7 +2643,7 @@ py here.search("cabinet").do_bake()
# The books title and the fact that it cant be removed from the room:
# The books title and description:
# [[file:../../../projects/mud.org::*Book][Book:2]]
@ -2688,16 +2671,16 @@ py here.search("cabinet").do_bake()
# Book:4 ends here
# Cauldron
# The cauldron should have a special =look= so you know what ingredients have been added, and the follow commands:
# The cauldron should have a special =look= so a character knows what ingredients they added, and the follow commands:
# - =empty= … an imp should drink the contents and then shakes its head, but only if there are ingredients already in it.
# - =add= (or =give=) an item from the inventory.
# - =create=, =cook= or =mix=
# - =bottle= to create a vial
# - =empty= … the imp will empty the contents
# - =add= (or =give=) an item from the inventory.
# - =create=, =cook= or =mix=
# - =bottle= to create a vial
# What about these commands?
# - =crush= for use in
# - =crush= for use in mortal and pestle
# [[file:../../../projects/mud.org::*Cauldron][Cauldron:1]]
@ -2710,16 +2693,63 @@ py here.search("cabinet").do_bake()
# [[file:../../../projects/mud.org::*Cauldron][Cauldron:2]]
@desc cauldron = A small, cast-iron cauldron sits on a portable stand, its interior stained from countless brews. The cauldron is surrounded by a ring of salt, a protective barrier against unwanted energies. A small fire burns beneath it, ready to heat concoctions.
@desc cauldron = A small, cast-iron cauldron sits on an iron stand, its interior stained from countless brews. Someone surrounded the cauldron with a ring of salt, a protective barrier against unwanted energies. A small fire burns beneath it, ready to heat concoctions.
# Cauldron:2 ends here
# Table
# Lock it down:
# [[file:../../../projects/mud.org::*Cauldron][Cauldron:3]]
@lock cauldron = get:false()
# Cauldron:3 ends here
# Table and Shelf
# Until we decide if we want to do something with the table:
# [[file:../../../projects/mud.org::*Table][Table:1]]
# [[file:../../../projects/mud.org::*Table and Shelf][Table and Shelf:1]]
@detail table = Made from a polish black wood, etched with intricate runes that shimmer faintly in the candlelight.
# Table:1 ends here
# Table and Shelf:1 ends here
# The table is a producer of /bottles/.
# [[file:../../../projects/mud.org::*Table and Shelf][Table and Shelf:2]]
@create/drop shelf of empty bottles;shelf;bottles;bottle: typeclasses.consumables.Producer
# Table and Shelf:2 ends here
# With a description:
# [[file:../../../projects/mud.org::*Table and Shelf][Table and Shelf:3]]
@desc shelf = Cluttered with some empty brown |Ybottles|n. Perhaps you can fill these with liquid ingredients and bring them back here.
# Table and Shelf:3 ends here
# We have to have the bush describe what it /makes/:
# [[file:../../../projects/mud.org::*Table and Shelf][Table and Shelf:4]]
@set shelf/make_name = "bottle"
#
@set shelf/make_verb = "$conj(pick up) a"
# Table and Shelf:4 ends here
# This one is optional as it defaults to Consumable:
# [[file:../../../projects/mud.org::*Table and Shelf][Table and Shelf:5]]
@set shelf/make_class = "typeclasses.drinkables.Bottle"
#
@set shelf/make_desc = "A brown glass bottle. Currently empty."
#
@set shelf/make_amount = 1
# Table and Shelf:5 ends here
# Imp
# Every secret alchemical lab should have an Imp familiar.
@ -3006,7 +3036,7 @@ py bt = self.search('head'); bt.db.pose = 'sitting next to a small campfire'
# [[file:../../../projects/mud.org::*Mares Head][Mares Head:7]]
@set mares head/arrive = "5 ;; emote nods its skull in greeting. ;; 30 ;; emote stares at you with its empty sockets. ;; emote reaches into the fire, and pulls out a branch ;; 2 ;; emote brushes off the soot, and bends it into a pleasing curve... ;; gift pipe to {0}"
@set mares head/arrive = "5 ;; emote nods its skull in greeting. ;; 30 ;; emote stares at you with its empty sockets. ;; emote reaches into the fire, pulls out a branch, and brushes off the soot. ;; gift pipe to {0}"
# Mares Head:7 ends here
# Bugs