Updated contrib to use the Google style docstrings are per #709. Also

remove long deprecated code-block usage in menusystem - use callback functions
instead.
This commit is contained in:
Griatch 2015-05-17 12:43:12 +02:00
parent 64c6d06d0f
commit 3e9263e207
10 changed files with 352 additions and 172 deletions

View file

@ -104,7 +104,9 @@ class TradeTimeout(DefaultScript):
This times out the trade request, in case player B did not reply in time.
"""
def at_script_creation(self):
"called when script is first created"
"""
Called when script is first created
"""
self.key = "trade_request_timeout"
self.desc = "times out trade requests"
self.interval = TRADE_TIMEOUT
@ -113,13 +115,17 @@ class TradeTimeout(DefaultScript):
self.persistent = False
def at_repeat(self):
"called once"
"""
called once
"""
if self.ndb.tradeevent:
self.obj.ndb.tradeevent.finish(force=True)
self.obj.msg("Trade request timed out.")
def is_valid(self):
"Only valid if the trade has not yet started"
"""
Only valid if the trade has not yet started
"""
return self.obj.ndb.tradeevent and not self.obj.ndb.tradeevent.trade_started
@ -130,12 +136,19 @@ class TradeHandler(object):
"""
def __init__(self, partA, partB):
"""
Initializes the trade. This is called when part A tries to initiate
a trade with part B. The trade will not start until part B repeats
this command (B will then call the self.join() command)
Initializes the trade. This is called when part A tries to
initiate a trade with part B. The trade will not start until
part B repeats this command (B will then call the self.join()
command)
Args:
partA (object): The party trying to start barter.
partB (object): The party asked to barter.
Notes:
We also store the back-reference from the respective party
to this object.
We also store the back-reference from the respective party to
this object.
"""
# parties
self.partA = partA
@ -152,9 +165,14 @@ class TradeHandler(object):
def msg(self, party, string):
"""
Relay a message to the other party. This allows
the calling command to not have to worry about
which party they are in the handler.
Relay a message to the other party. This allows the calling
command to not have to worry about which party they are in the
handler.
Args:
party (object): One of partA or B. The method will figure
out which is which.
string (str): Text to send.
"""
if self.partA == party:
self.partB.msg(string)
@ -165,7 +183,16 @@ class TradeHandler(object):
self.party.msg(string)
def get_other(self, party):
"Returns the other party of the trade"
"""
Returns the other party of the trade
Args:
partyX (object): One of the parties of the negotiation
Returns:
partyY (object): The other party, not partyX.
"""
if self.partA == party:
return self.partB
if self.partB == party:
@ -175,6 +202,10 @@ class TradeHandler(object):
def join(self, partB):
"""
This is used once B decides to join the trade
Args:
partB (object): The party accepting the barter.
"""
print "join:", self.partB, partB, self.partB == partB, type(self.partB), type(partB)
if self.partB == partB:
@ -186,7 +217,11 @@ class TradeHandler(object):
def unjoin(self, partB):
"""
This is used if B decides not to join the trade
This is used if B decides not to join the trade.
Args:
partB (object): The party leaving the barter.
"""
if self.partB == partB:
self.finish()
@ -198,6 +233,11 @@ class TradeHandler(object):
Change the current standing offer. We leave it up to the
command to do the actual checks that the offer consists
of real, valid, objects.
Args:
party (object): Who is making the offer
args (objects or str): Offerings.
"""
if self.trade_started:
# reset accept statements whenever an offer changes
@ -212,15 +252,25 @@ class TradeHandler(object):
def list(self):
"""
Returns two lists of objects on offer, separated by partA/B.
List current offers.
Returns:
offers (tuple): A tuple with two lists, (A_offers, B_offers).
"""
return self.partA_offers, self.partB_offers
def search(self, offername):
"""
Returns an object on offer, based on a search criterion.
If the search criterion is an integer, treat it as an
index to return in the list of offered items
Search current offers.
Args:
offername (str or int): Object to search for, or its index in
the list of offered items.
Returns:
offer (object): An object on offer, based on the search criterion.
"""
all_offers = self.partA_offers + self.partB_offers
if isinstance(offername, int):
@ -242,7 +292,18 @@ class TradeHandler(object):
"""
Accept the current offer.
Returns True if this closes the deal, False otherwise
Args:
party (object): The party accepting the deal.
Returns:
result (object): `True` if this closes the deal, `False`
otherwise
Notes:
This will only close the deal if both parties have
accepted independently. This is done by calling the
`finish()` method.
"""
if self.trade_started:
if party == self.partA:
@ -255,9 +316,20 @@ class TradeHandler(object):
def decline(self, party):
"""
Remove an previously accepted status (changing ones mind)
Decline the offer (or change one's mind).
Args:
party (object): Party declining the deal.
Returns:
did_decline (bool): `True` if there was really an
`accepted` status to change, `False` otherwise.
Notes:
If previously having used the `accept` command, this
function will only work as long as the other party has not
yet accepted.
returns True if there was really a status to change, False otherwise.
"""
if self.trade_started:
if party == self.partA:
@ -276,6 +348,12 @@ class TradeHandler(object):
def finish(self, force=False):
"""
Conclude trade - move all offers and clean up
Args:
force (bool, optional): Force cleanup regardless of if the
trade was accepted or not (if not, no goods will change
hands but trading will stop anyway)
"""
fin = False
if self.trade_started and self.partA_accepted and self.partB_accepted:
@ -303,8 +381,8 @@ class TradeHandler(object):
class CmdTradeBase(Command):
"""
Base command for Trade commands to inherit from. Implements
the custom parsing.
Base command for Trade commands to inherit from. Implements the
custom parsing.
"""
def parse(self):
"""

View file

@ -2,9 +2,9 @@
Contribution - Griatch 2011
[Note - with the advent of MULTISESSION_MODE=2, this is not really
as necessary anymore - the ooclook and @charcreate commands in that
mode replaces this module with better functionality.]
[Note - with the advent of MULTISESSION_MODE=2, this is not really as
necessary anymore - the ooclook and @charcreate commands in that mode
replaces this module with better functionality.]
This is a simple character creation commandset. A suggestion is to
test this together with menu_login, which doesn't create a Character
@ -18,11 +18,11 @@ while puppeting a Character already before.
Installation:
Read the instructions in contrib/examples/cmdset.py in
order to create a new default cmdset module for Evennia to use (copy
the template up one level, and change the settings file's relevant
variables to point to the cmdsets inside). If you already have such
a module you should of course use that.
Read the instructions in contrib/examples/cmdset.py in order to create
a new default cmdset module for Evennia to use (copy the template up
one level, and change the settings file's relevant variables to point
to the cmdsets inside). If you already have such a module you should
of course use that.
Next import this module in your custom cmdset module and add the
following line to the end of OOCCmdSet's at_cmdset_creation():

View file

@ -4,8 +4,8 @@ Dice - rolls dice for roleplaying, in-game gambling or GM:ing
Evennia contribution - Griatch 2012
This module implements a full-fledged dice-roller and a 'dice' command to
go with it. It uses standard RPG 'd'-syntax (e.g. 2d6 to roll two
This module implements a full-fledged dice-roller and a 'dice' command
to go with it. It uses standard RPG 'd'-syntax (e.g. 2d6 to roll two
six-sided die) and also supports modifiers such as 3d6 + 5.
One can also specify a standard Python operator in order to specify
@ -39,31 +39,53 @@ def roll_dice(dicenum, dicetype, modifier=None, conditional=None, return_tuple=F
"""
This is a standard dice roller.
Input:
dicenum - number of dice to roll (the result to be added)
dicetype - number of sides of the dice to be rolled
modifier - tuple (operator, value), where operator is a character string
with one of +,-,/ or *. The entire result of the dice rolls will
be modified by this value.
conditional - tuple (conditional, value), where conditional is a character
string with one of ==,<,>,>=,<= or !=.
return_tuple - return result as a tuple containing all relevant info
return_tuple - (default False) - return a tuple with all individual roll
results
All input numbers are converted to integers.
Args:
dicenum (int): Number of dice to roll (the result to be added).
dicetype (int): Number of sides of the dice to be rolled.
modifier (tuple): A tuple `(operator, value)`, where operator is
one of `"+"`, `"-"`, `"/"` or `"*"`. The result of the dice
roll(s) will be modified by this value.
conditional (tuple): A tuple `(conditional, value)`, where
conditional is one of `"=="`,`"<"`,`">"`,`">="`,`"<=`" or "`!=`".
This allows the roller to directly return a result depending
on if the conditional was passed or not.
return_tuple (bool): Return a tuple with all individual roll
results or not.
Returns:
normally returns the result
if return_tuple=True, returns a tuple (result, outcome, diff, rolls)
In this tuple, outcome and diff will be None if conditional is
not set. rolls is itself a tuple holding all the individual
rolls in the case of multiple die-rolls.
roll_result (int): The result of the roll + modifiers. This is the
default return.
condition_result (bool): A True/False value returned if `conditional`
is set but not `return_tuple`. This effectively hides the result
of the roll.
full_result (tuple): If, return_tuple` is `True`, instead
return a tuple `(result, outcome, diff, rolls)`. Here,
`result` is the normal result of the roll + modifiers.
`outcome` and `diff` are the boolean result of the roll and
absolute difference to the `conditional` input; they will
be will be `None` if `conditional` is not set. `rolls` is
itself a tuple holding all the individual rolls in the case of
multiple die-rolls.
Raises:
TypeError if non-supported modifiers or conditionals are given.
Notes:
All input numbers are converted to integers.
Examples:
print roll_dice(2, 6) # 2d6
<<< 7
print roll_dice(1, 100, ('+', 5) # 1d100 + 5
<<< 34
print roll_dice(1, 20, conditional=('<', 10) # let'say we roll 3
<<< True
print roll_dice(3, 10, return_tuple=True)
<<< (11, None, None, (2, 5, 4))
print roll_dice(2, 20, ('-', 2), conditional=('>=', 10), return_tuple=True)
<<< (8, False, 2, (4, 6)) # roll was 4 + 6 - 2 = 8
"""
dicelimit = 0 # This is the maximum number of dice that can be used in a single roll.
dicenum = int(dicenum)
dicetype = int(dicetype)
@ -90,7 +112,10 @@ def roll_dice(dicenum, dicetype, modifier=None, conditional=None, return_tuple=F
if return_tuple:
return (result, outcome, diff, rolls)
else:
return result
if conditional:
return outcome
else:
return result
RE_PARTS = re.compile(r"(d|\+|-|/|\*|<|>|<=|>=|!=|==)")
RE_MOD = re.compile(r"(\+|-|/|\*)")

View file

@ -158,8 +158,16 @@ class ExtendedRoom(DefaultRoom):
def replace_timeslots(self, raw_desc, curr_time):
"""
Filter so that only time markers `<timeslot>...</timeslot>` of the
correct timeslot remains in the description.
Filter so that only time markers `<timeslot>...</timeslot>` of
the correct timeslot remains in the description.
Args:
raw_desc (str): The unmodified description.
curr_time (str): A timeslot identifier.
Returns:
description (str): A possibly moified description.
"""
if raw_desc:
regextuple = REGEXMAP[curr_time]
@ -171,14 +179,24 @@ class ExtendedRoom(DefaultRoom):
def return_detail(self, key):
"""
This will attempt to match a "detail" to look for in the room. A detail
is a way to offer more things to look at in a room without having to
add new objects. For this to work, we require a custom `look` command that
allows for `look <detail>` - the look command should defer to this
method on the current location (if it exists) before giving up on
finding the target.
This will attempt to match a "detail" to look for in the room.
Details are not season-sensitive, but are parsed for timeslot markers.
Args:
key (str): A detail identifier.
Returns:
detail (str or None): A detail mathing the given key.
Notes:
A detail is a way to offer more things to look at in a room
without having to add new objects. For this to work, we
require a custom `look` command that allows for `look
<detail>` - the look command should defer to this method on
the current location (if it exists) before giving up on
finding the target.
Details are not season-sensitive, but are parsed for timeslot
markers.
"""
try:
detail = self.db.details.get(key.lower(), None)
@ -192,7 +210,17 @@ class ExtendedRoom(DefaultRoom):
return None
def return_appearance(self, looker):
"This is called when e.g. the look command wants to retrieve the description of this object."
"""
This is called when e.g. the look command wants to retrieve
the description of this object.
Args:
looker (Object): The object looking at us.
Returns:
description (str): Our description.
"""
raw_desc = self.db.raw_desc or ""
update = False

View file

@ -8,8 +8,8 @@ insert custom markers in their text to indicate gender-aware
messaging. It relies on a modified msg() and is meant as an
inspiration and starting point to how to do stuff like this.
When in use, all messages being sent to the character will make use
of the character's gender, for example the echo
When in use, all messages being sent to the character will make use of
the character's gender, for example the echo
```
char.msg("%s falls on {p face with a thud." % char.key)

View file

@ -19,8 +19,10 @@ CMDSET_UNLOGGEDIN = "contrib.menu_login.UnloggedInCmdSet"
That's it. Reload the server and try to log in to see it.
The initial login "graphic" is taken from strings in the module given
by settings.CONNECTION_SCREEN_MODULE.
You will want to change the login "graphic", which defaults to give
information about commands which are not used in this version of the
login. You can change the screen used by editing
`mygame/server/conf/connection_screens.py`.
"""

View file

@ -11,14 +11,29 @@ in one or more columns.
The menu system consists of a MenuTree object populated by MenuNode
objects. Nodes are linked together with automatically created commands
so the player may select and traverse the menu. Each node can display
text and show options, but also execute arbitrary code to act on the
text and show options, but also execute a callback to act on the
system and the calling object when they are selected.
There is also a simple Yes/No function supplied. This will create a
one-off Yes/No question and executes a given code depending on which
choice was made.
There is also a simple Yes/No function as well as a one-level choice
function supplied. This will create a one-off Yes/No question or a
one-level choice. These helpers will execute a given callback
depending on which choice was made.
To test, add this to the default cmdset
To start a menu, define the nodes of the menu and then add the
following to a command `func` you can call:
```python
menu = MenuTree(self.caller, nodes=(...))
menu.start()
```
This will switch you into menu-mode. See `contrib/menu_login.py` for an
example of usage.
For a simple demonstration, add `CmdMenuTest` from this module to the default cmdset.
"""
from types import MethodType
@ -49,8 +64,6 @@ class CmdMenuNode(Command):
menutree = None
callback = None
# deprecated
code = None
def func(self):
"Execute a selection"
@ -60,12 +73,6 @@ class CmdMenuNode(Command):
self.callback()
except Exception, e:
self.caller.msg("%s\n{rThere was an error with this selection.{n" % e)
elif self.code:
evennia.logger.log_depmsg("menusystem.code is deprecated. Use menusystem.func.")
try:
exec(self.code)
except Exception, e:
self.caller.msg("%s\n{rThere was an error with this selection.{n" % e)
else:
self.caller.msg("{rThis option is not available.{n")
@ -173,8 +180,19 @@ class MenuTree(object):
enter and where to exit the menu tree. If nodes is given, it
should be a list of valid node objects to add to the tree.
exec_end - if not None, will execute the given command string
directly after the menu system has been exited.
caller (Object): The caller triggering the menu
nodes (tuple, optional): A tuple of `MenuNode` objects. This need
not be in any particular order.
startnode (str, optional): The key of the first `MenuNode` to jump
to when starting the menu. Defaults to "START".
endnode (str, optional): The key of the end node. When
instructed to go to this node (by any means), the menu
will be gracefully exited. Defaults to "END".
exec_end (str, optional): If not `None`, this command name will be executed
directly after the menu system has been exited. It is
normally useful for making sure the user realizes their UI
mode has changed.
"""
self.tree = {}
self.startnode = startnode
@ -187,7 +205,8 @@ class MenuTree(object):
def start(self):
"""
Initialize the menu
Initialize the menu and go to the starting node.
"""
self.goto(self.startnode)
@ -195,6 +214,9 @@ class MenuTree(object):
"""
Add a menu node object to the tree. Each node itself keeps
track of which nodes it is connected to.
Args:
menunode (MenuNode): The node to add.
"""
self.tree[menunode.key] = menunode
@ -202,6 +224,10 @@ class MenuTree(object):
"""
Go to a key in the tree. This sets up the cmdsets on the
caller so that they match the choices in that node.
Args:
key (str): The node-key to go to.
"""
if key == self.endnode:
# if we was given the END node key, we clean up immediately.
@ -210,7 +236,7 @@ class MenuTree(object):
if self.exec_end is not None:
self.caller.execute_cmd(self.exec_end)
return
# not exiting, look for a valid code.
# not exiting, look for a valid node
node = self.tree.get(key, None)
# make caller available on node
node.caller = self.caller
@ -222,13 +248,6 @@ class MenuTree(object):
except Exception:
logger.log_trace()
self.caller.msg("{rNode callback could not be executed for node %s. Continuing anyway.{n" % key)
if node.code:
# Execute eventual code active on this node. self.caller is available at this point.
evennia.logger.log_depmsg("menusystem.code is deprecated. Use menusystem.callback.")
try:
exec(node.code)
except Exception:
self.caller.msg("{rCode could not be executed for node %s. Continuing anyway.{n" % key)
# initialize - this creates new cmdset
node.init(self)
# clean old menu cmdset and replace with the new one
@ -252,42 +271,48 @@ class MenuNode(object):
"""
def __init__(self, key, text="", links=None, linktexts=None,
keywords=None, cols=1, helptext=None,
selectcmds=None, callback=None, code="", nodefaultcmds=False, separator=""):
selectcmds=None, callback=None, nodefaultcmds=False, separator=""):
"""
key - the unique identifier of this node.
text - is the text that will be displayed at top when viewing this
node.
links - a list of keys for unique menunodes this is connected to.
The actual keys will not printed - keywords will be used
(or a number)
linktexts - an optional list of texts to describe the links. Must
match link list if defined. Entries can be None to not
generate any extra text for a particular link.
keywords - an optional list of unique keys for choosing links. Must
match links list. If not given, index numbers will be used.
Also individual list entries can be None and will be replaed
by indices. If CMD_NOMATCH or CMD_NOENTRY, no text will be
generated to indicate the option exists.
cols - how many columns to use for displaying options.
helptext - if defined, this is shown when using the help command
instead of the normal help index.
selectcmds- a list of custom cmdclasses for handling each option.
Must match links list, but some entries may be set to None
to use default menu cmds. The given command's key will be
used for the menu list entry unless it's CMD_NOMATCH or
CMD_NOENTRY, in which case no text will be generated. These
commands have access to self.menutree and so can be used to
select nodes.
code - functional code. Deprecated. This will be executed just before this
node is loaded (i.e. as soon after it's been selected from
another node). self.caller is available to call from this
code block, as well as the evennia flat API.
callback - function callback. This will be called as callback(currentnode) just
before this node is loaded (i.e. as soon as possible as it's
been selected from another node). currentnode.caller is available.
nodefaultcmds - if true, don't offer the default help and look commands
in the node
separator - this string will be put on the line between menu nodes.
Initialize the node.
Args:
key (str): The unique identifier of this node.
text (str, optional): The text that will be displayed at
top when viewing this node.
Kwargs:
links (list): A liist of keys for unique menunodes this is connected to.
The actual keys will not printed - keywords will be
used (or a number)
linktexts (list)- A list of texts to describe the links. Must
match order of `links` list if defined. Entries can be
None to not generate any extra text for a particular
link.
keywords (list): A list of unique keys for choosing links. Must
match links list. If not given, index numbers will be
used. Also individual list entries can be None and
will be replaed by indices. If CMD_NOMATCH or
CMD_NOENTRY, no text will be generated to indicate the
option exists.
cols (int): How many columns to use for displaying options.
helptext (str): If defined, this is shown when using the help command
instead of the normal help index.
selectcmds (list): A list of custom cmdclasses for
handling each option. Must match links list, but some
entries may be set to None to use default menu cmds.
The given command's key will be used for the menu list
entry unless it's CMD_NOMATCH or CMD_NOENTRY, in which
case no text will be generated. These commands have
access to self.menutree and so can be used to select
nodes.
callback (function): Function callback. This will be
called as callback(currentnode) just before this node is
loaded (i.e. as soon as possible as it's been selected
from another node). currentnode.caller is available.
nodefaultcmds (bool): If `True`, don't offer the default
help and look commands in the node
separator (str): This string will be put on the line
between menu nodes.
"""
self.key = key
self.cmdset = None
@ -296,15 +321,11 @@ class MenuNode(object):
self.keywords = keywords
self.cols = cols
self.selectcmds = selectcmds
self.code = code
self.callback = MethodType(callback, self, MenuNode) if callback else None
self.nodefaultcmds = nodefaultcmds
self.separator = separator
Nlinks = len(self.links)
if code:
evennia.logger.log_depmsg("menusystem.code is deprecated. Use menusystem.callback.")
# validate the input
if not self.links:
self.links = []
@ -399,17 +420,21 @@ class MenuNode(object):
# make use the node system since there is only one level of choice.
#
def prompt_yesno(caller, question="", yesfunc=None, nofunc=None, yescode="", nocode="", default="N"):
def prompt_yesno(caller, question="", yesfunc=None, nofunc=None, default="N"):
"""
This sets up a simple yes/no questionnaire. Question will be
asked, followed by a Y/[N] prompt where the [x] signifies the
default selection. Note that this isn't making use of the menu
node system.
default selection. Note that this isn't actually making use of the
menu node system, but does use the MenuCmdSet.
Args:
caller (Object): The object triggering the prompt.
question (str, optional): The Yes/No question asked.
yesfunc (function, optional): Callback for a Yes answer.
nofunc (functionm optional): Callback for a No answer.
default (str, optional): Default used if caller just hits
return. Either `"Y"` or `"N"`
yesfunc - function callback to be called as yesfunc(self) when choosing yes (self.caller is available)
nofunc - function callback to be called as yesfunc(self) when choosing no (self.caller is available)
yescode - deprecated, executable code
nocode - "
"""
# creating and defining commands
@ -441,14 +466,6 @@ def prompt_yesno(caller, question="", yesfunc=None, nofunc=None, yescode="", noc
self.caller.execute_cmd('%s' % default)
defaultcmd.callback = MethodType(_defaultcmd, defaultcmd, CmdMenuNode)
# code exec is deprecated:
if yescode:
evennia.logger.log_depmsg("yesnosystem.code is deprecated. Use yesnosystem.callback.")
cmdyes.code = yescode + "\nself.caller.cmdset.delete('menucmdset')\ndel self.caller.db._menu_data"
if nocode:
evennia.logger.log_depmsg("yesnosystem.code is deprecated. Use yesnosystem.callback.")
cmdno.code = nocode + "\nself.caller.cmdset.delete('menucmdset')\ndel self.caller.db._menu_data"
# creating cmdset (this will already have look/help commands)
yesnocmdset = MenuCmdSet()
yesnocmdset.add(cmdyes)
@ -481,33 +498,57 @@ def prompt_choice(caller, question="", prompts=None, choicefunc=None, force_choo
"""
This sets up a simple choice questionnaire. Question will be
asked, followed by a series of prompts. Note that this isn't
making use of the menu node system.
making use of the menu node system but uses the MenuCmdSet.
Args:
caller (object): The object calling and being offered the choice
question (str, optional): Text describing the offered choice
prompts (list, optional): List of strings defining the available choises.
choicefunc (function, optional): A function called as
`choicefunc(self)` when a choice is made. Inside this function,
`self.caller` is available and `self.prompt_index` is the index
(starting with 0) matching the chosen prompt in the `prompts` list.
force_choose - force user to make a choice
Examples:
```python
def mychoice(self):
self.caller.msg("Index of choice is %s." % self.prompt_index)
prompt_choice(caller, "Make a choice:", prompts=["A","B","C"], choicefunc=mychoice)
```
When triggering the above from a command or @py prompt you get the following options:
>>> Make a choice:
[1] A
[2] B
[3] C
<<< 2
>>> Index of choice is 1.
caller - the object calling and being offered the choice
question - text describing the offered choice
prompts - list of choices
choicefunc - functions callback to be called as func(self) when
make choice (self.caller is available) The function's definition
should be like func(self, menu_node), and menu_node.key is user's
choice.
force_choose - force user to make a choice or not
"""
# creating and defining commands
count = 0
choices = ""
commands = []
for choice in utils.make_iter(prompts):
# create the available choice-commands
count += 1
choices += "\n{lc%d{lt[%d]{le %s" % (count, count, choice)
cmdfunc = CmdMenuNode(key="%d" % count)
cmdfunc.prompt_index = count-1
if choicefunc:
cmdfunc.choicefunc = choicefunc
def _choicefunc(self):
self.caller.cmdset.delete('menucmdset')
del self.caller.db._menu_data
self.choicefunc(self)
# set a new method "callback" on cmdfunc
cmdfunc.callback = MethodType(_choicefunc, cmdfunc, CmdMenuNode)
commands.append(cmdfunc)
@ -517,6 +558,7 @@ def prompt_choice(caller, question="", prompts=None, choicefunc=None, force_choo
prompt = question + choices + "\nPlease choose one."
# create the error-reporting command
errorcmd = CmdMenuNode(key=CMD_NOMATCH)
if force_choose:
def _errorcmd(self):
@ -531,6 +573,7 @@ def prompt_choice(caller, question="", prompts=None, choicefunc=None, force_choo
self.choicefunc(self)
errorcmd.callback = MethodType(_errorcmd, errorcmd, CmdMenuNode)
# create the fallback command
defaultcmd = CmdMenuNode(key=CMD_NOINPUT)
if force_choose:
def _defaultcmd(self):
@ -547,7 +590,8 @@ def prompt_choice(caller, question="", prompts=None, choicefunc=None, force_choo
# creating cmdset (this will already have look/help commands)
choicecmdset = MenuCmdSet()
for cmdfunc in commands: choicecmdset.add(cmdfunc)
for cmdfunc in commands:
choicecmdset.add(cmdfunc)
choicecmdset.add(errorcmd)
choicecmdset.add(defaultcmd)
choicecmdset.add(CmdMenuLook())

View file

@ -4,22 +4,19 @@ Evennia Talkative NPC
Contribution - Griatch 2011
This is a simple NPC object capable of holding a
simple menu-driven conversation. Create it by
creating an object of typeclass contrib.talking_npc.TalkingNPC,
For example using @create:
This is a simple NPC object capable of holding a simple menu-driven
conversation. Create it by creating an object of typeclass
contrib.talking_npc.TalkingNPC, For example using @create:
@create John : contrib.talking_npc.TalkingNPC
Walk up to it and give the talk command
to strike up a conversation. If there are many
talkative npcs in the same room you will get to
choose which one's talk command to call (Evennia
handles this automatically).
Walk up to it and give the talk command to strike up a conversation.
If there are many talkative npcs in the same room you will get to
choose which one's talk command to call (Evennia handles this
automatically).
Note that this is only a prototype class, showcasing
the uses of the menusystem module. It is NOT a full
mob implementation.
Note that this is only a prototype class, showcasing the uses of the
menusystem module. It is NOT a full mob implementation.
"""

View file

@ -1,14 +1,12 @@
"""
Example script for testing. This adds a simple timer that
has your character make observations and notices at irregular
intervals.
Example script for testing. This adds a simple timer that has your
character make observations and notices at irregular intervals.
To test, use
@script me = examples.bodyfunctions.BodyFunctions
The script will only send messages to the object it
is stored on, so make sure to put it on yourself
or you won't see any messages!
The script will only send messages to the object it is stored on, so
make sure to put it on yourself or you won't see any messages!
"""
import random

View file

@ -66,6 +66,7 @@ class RedButton(DefaultObject):
"""
Opens the glass lid and start the timer so it will soon close
again.
"""
if self.db.lid_open:
@ -91,6 +92,7 @@ class RedButton(DefaultObject):
Close the glass lid. This validates all scripts on the button,
which means that scripts only being valid when the lid is open
will go away automatically.
"""
if not self.db.lid_open:
@ -111,6 +113,9 @@ class RedButton(DefaultObject):
"""
Breaks the lamp in the button, stopping it from blinking.
Args:
feedback (bool): Show a message about breaking the lamp.
"""
self.db.lamp_works = False
desc = self.db.desc_lamp_broken
@ -126,7 +131,10 @@ class RedButton(DefaultObject):
def press_button(self, pobject):
"""
Someone was foolish enough to press the button!
pobject - the person pressing the button
Args:
pobject (Object): The person pressing the button
"""
# deactivate the button so it won't flash/close lid etc.
self.scripts.add(scriptexamples.DeactivateButtonEvent)