cleanup and revisions

This commit is contained in:
InspectorCaracal 2022-09-26 12:34:42 -06:00
parent ce41753cde
commit 0d50f9bcf8
4 changed files with 70 additions and 30 deletions

View file

@ -8,8 +8,8 @@ This contrib is designed to be used in MULTISESSION_MODE = 2 or higher, where ch
In your game folder `commands/default_cmdsets.py`, import and add `ContribCmdCharCreate` to your `AccountCmdSet`. In your game folder `commands/default_cmdsets.py`, import and add `ContribCmdCharCreate` to your `AccountCmdSet`.
Example: Example:
```py ```python
from evennia.contrib.base_systems.character_creator.character_creator import ContribCmdCharCreate from evennia.contrib.rpg.character_creator.character_creator import ContribCmdCharCreate
class AccountCmdSet(default_cmds.AccountCmdSet): class AccountCmdSet(default_cmds.AccountCmdSet):
@ -23,18 +23,21 @@ In your game folder `typeclasses/accounts.py`, import and inherit from `ContribC
(Alternatively, you can copy the `at_look` method directly into your own class.) (Alternatively, you can copy the `at_look` method directly into your own class.)
Example: Example:
```py ```python
from evennia.contrib.base_systems.character_creator.character_creator import ContribChargenAccount from evennia.contrib.rpg.character_creator.character_creator import ContribChargenAccount
class Account(ContribChargenAccount): class Account(ContribChargenAccount):
# your Account class code # your Account class code
``` ```
Lastly, in your `settings.py` file, define `CHARGEN_MENU` to your character creation menu module's location. By default, the new `charcreate` command will reference the example menu provided by the contrib, so you can test it
out before building your own menu. You can reference [the example menu here]() for ideas on how to build your own.
Example: Once you have your own menu, just add it to your settings to use it. e.g. if your menu is in mygame/word/chargen_menu.py,
```py you'd add the following to your settings file:
CHARGEN_MENU = "evennia.contrib.base_systems.character_creator.example_menu"
```python
CHARGEN_MENU = "world.chargen_menu"
``` ```
## Usage ## Usage
@ -75,7 +78,7 @@ The contrib overrides the character creation command - `charcreate` - to use a c
### Changes to `Account.at_look` ### Changes to `Account.at_look`
The contrib version works mostly the same as core evennia, but adds an additional check to recognize an in-progress character. If you've modified your own `at_look` hook, it's an easy addition to make: just add this section to the playable character list loop. The contrib version works mostly the same as core evennia, but adds an additional check to recognize an in-progress character. If you've modified your own `at_look` hook, it's an easy addition to make: just add this section to the playable character list loop.
```py ```python
for char in characters: for char in characters:
# contrib code starts here # contrib code starts here
if char.db.chargen_step: if char.db.chargen_step:

View file

@ -27,7 +27,11 @@ from evennia.objects.models import ObjectDB
from evennia.utils import create, search from evennia.utils import create, search
from evennia.utils.evmenu import EvMenu from evennia.utils.evmenu import EvMenu
_CHARACTER_TYPECLASS = settings.BASE_CHARACTER_TYPECLASS _CHARACTER_TYPECLASS = settings.BASE_CHARACTER_TYPECLASS
try:
_CHARGEN_MENU = settings.CHARGEN_MENU
except AttributeError:
_CHARGEN_MENU = "evennia.contrib.rpg.character_creator.example_menu"
class ContribCmdCharCreate(MuxAccountCommand): class ContribCmdCharCreate(MuxAccountCommand):
""" """
@ -97,7 +101,7 @@ class ContribCmdCharCreate(MuxAccountCommand):
account.execute_cmd("ic {}".format(char.key)) account.execute_cmd("ic {}".format(char.key))
EvMenu(session, EvMenu(session,
settings.CHARGEN_MENU, _CHARGEN_MENU,
startnode=startnode, startnode=startnode,
cmd_on_exit=finish_char_callback) cmd_on_exit=finish_char_callback)

View file

@ -76,7 +76,7 @@ def menunode_welcome(caller):
game wiki if you have one. game wiki if you have one.
""") """)
help = "You can explain the commands for exiting and resuming more specifically here." help = "You can explain the commands for exiting and resuming more specifically here."
options = [{"desc": "Let's begin!", "goto": "menunode_info_base"}] options = {"desc": "Let's begin!", "goto": "menunode_info_base"}
return (text, help), options return (text, help), options
@ -231,7 +231,6 @@ def _set_category_opt(caller, raw_string, category, value, **kwargs):
# go back to the base node for the categories choice to pick another # go back to the base node for the categories choice to pick another
return "menunode_categories" return "menunode_categories"
######################################################### #########################################################
# Multiple Choice # Multiple Choice
######################################################### #########################################################
@ -301,6 +300,18 @@ def _set_multichoice(caller, raw_string, selected=[], **kwargs):
return ("menunode_multi_choice", {"selected": selected}) return ("menunode_multi_choice", {"selected": selected})
#########################################################
# Simple List Options
#########################################################
# If you just want a straightforward list of options, without any of the
# back-and-forth navigation or modifying of option text, evennia has an
# easy to use decorator available: `@list_node`
# For an example of how to use it, check out the documentation for
# evennia.utils.evmenu - there's lots of other useful EvMenu tools too!
######################################################### #########################################################
# Starting Objects # Starting Objects
######################################################### #########################################################
@ -381,47 +392,69 @@ def menunode_choose_name(caller, raw_string, **kwargs):
# another decision, so save the resume point # another decision, so save the resume point
char.db.chargen_step = "menunode_choose_name" char.db.chargen_step = "menunode_choose_name"
text = dedent("""\ # check if an error message was passed to the node. if so, you'll want to include it
# into your "name prompt" at the end of the node text.
if error := kwargs.get("error"):
prompt_text = f"{error}. Enter a different name."
else:
# there was no error, so just ask them to enter a name.
prompt_text = "Enter a name here to check if it's available."
# this will print every time the player is prompted to choose a name,
# including the prompt text defined above
text = dedent(f"""\
|wChoosing a Name|n |wChoosing a Name|n
Especially for roleplaying-centric games, being able to choose your Especially for roleplaying-centric games, being able to choose your
character's name after deciding everything else, instead of before, character's name after deciding everything else, instead of before,
is really useful. is really useful.
Enter a name here to check if it's available. {prompt_text}
""") """)
help = "You'll have a chance to change your mind before confirming, even if the name is free." help = "You'll have a chance to change your mind before confirming, even if the name is free."
# since this is a free-text field, we just have the one # since this is a free-text field, we just have the one
options = [ { "key": "_default", "goto": "menunode_check_charname" } ] options = { "key": "_default", "goto": "_check_charname" }
return (text, help), options return (text, help), options
def menunode_check_charname(caller, raw_string, **kwargs): def _check_charname(caller, raw_string, **kwargs):
"""Check and confirm name choice""" """Check and confirm name choice"""
# strip any extraneous whitespace from the raw text # strip any extraneous whitespace from the raw text
# if you want to do any other validation on the name, e.g. no punctuation allowed, this is the place! # if you want to do any other validation on the name, e.g. no punctuation allowed, this is the place!
charname = raw_string.strip() charname = raw_string.strip()
# aside from validation, the built-in normalization function from the caller's Account does
# some useful cleanup on the input, just in case they try something sneaky
charname = caller.account.normalize_username(charname)
# check to make sure that the name doesn't already exist # check to make sure that the name doesn't already exist
candidates = Character.objects.filter_family(db_key__iexact=charname) candidates = Character.objects.filter_family(db_key__iexact=charname)
if len(candidates): if len(candidates):
# the name is already taken - loop this node with new input to enter another name # the name is already taken - report back with the error
text = f"|w{charname}|n is unavailable.\n\nEnter a different name." return ("menunode_choose_name", {"error": f"|w{charname}|n is unavailable.\n\nEnter a different name."})
options = [ { "key": "_default", "goto": "menunode_check_charname" } ]
return text, options
else: else:
# it's free! set the character's key to the name to reserve it # it's free! set the character's key to the name to reserve it
caller.new_char.key = charname caller.new_char.key = charname
text = f"|w{charname}|n is available! Confirm?" # continue on to the confirmation node
# let players change their mind and go back to the name choice, if they want return "menunode_confirm_name"
options = [
{ "key": ("Yes", "y"), "goto": "menunode_end" }, def menunode_confirm_name(caller, raw_string, **kwargs):
{ "key": ("No", "n"), "goto": "menunode_choose_name" }, """Confirm the name choice"""
] char = caller.new_char
return text, options
# since we reserved the name by assigning it, you can reference the character key
# if you have any extra validation or normalization that changed the player's input
# this also serves to show the player exactly what name they'll get
text = f"|w{char.key}|n is available! Confirm?"
# let players change their mind and go back to the name choice, if they want
options = [
{ "key": ("Yes", "y"), "goto": "menunode_end" },
{ "key": ("No", "n"), "goto": "menunode_choose_name" },
]
return text, options
######################################################### #########################################################
# The End # The End