> from world.test import hello_world
-> hello_world()
+> hello_world(me)
Hello World!
-> hello_world()
+> hello_world(me)
Hello World!
-> hello_world()
+> hello_world(me)
Hello World!
> quit()
Closing the Python console.
diff --git a/docs/latest/Howtos/Beginner-Tutorial/Part2/Beginner-Tutorial-Planning-The-Tutorial-Game.html b/docs/latest/Howtos/Beginner-Tutorial/Part2/Beginner-Tutorial-Planning-The-Tutorial-Game.html
index ba351bfa00..3fe88b5a48 100644
--- a/docs/latest/Howtos/Beginner-Tutorial/Part2/Beginner-Tutorial-Planning-The-Tutorial-Game.html
+++ b/docs/latest/Howtos/Beginner-Tutorial/Part2/Beginner-Tutorial-Planning-The-Tutorial-Game.html
@@ -420,7 +420,7 @@ how to train a neural net.
3.6.9. Are NPCs and mobs different entities? How do they differ?
-“Mobs” or “mobiles” are things that move around. This is traditionally monsters you can fight with, but could also be city guards or the baker going to chat with the neighbor. Back in the day, they were often fundamentally different these days it’s often easier to just make NPCs and mobs essentially the same thing.
+“Mobs” or “mobiles” are things that move around. This is traditionally monsters you can fight with, but could also be city guards or the baker going to chat with the neighbor. Back in the day, they were often fundamentally different. These days it’s often easier to just make NPCs and mobs essentially the same thing.
EvAdventure Answer
In EvAdventure, Monsters and NPCs do very different things, so they will be different classes, sharing some code where possible.
diff --git a/docs/latest/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Chargen.html b/docs/latest/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Chargen.html
index a78d1cd9d2..16627c0c20 100644
--- a/docs/latest/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Chargen.html
+++ b/docs/latest/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Chargen.html
@@ -133,23 +133,19 @@
6. Character Generation
-In previous lessons we have established how a character looks. Now we need to give the player a
-chance to create one.
+In previous lessons we have established how a character looks. Now we need to give the player a chance to create one.
6.1. How it will work
-A fresh Evennia install will automatically create a new Character with the same name as your
-Account when you log in. This is quick and simple and mimics older MUD styles. You could picture
-doing this, and then customizing the Character in-place.
-We will be a little more sophisticated though. We want the user to be able to create a character
-using a menu when they log in.
+A fresh Evennia install will automatically create a new Character with the same name as your Account when you log in. This is quick and simple and mimics older MUD styles. You could picture doing this, and then customizing the Character in-place.
+We will be a little more sophisticated though. We want the user to be able to create a character using a menu when they log in.
We do this by editing mygame/server/conf/settings.py and adding the line
-AUTO_CREATE_CHARACTER_WITH_ACCOUNT = False
+AUTO_CREATE_CHARACTER_WITH_ACCOUNT = False
When doing this, connecting with the game with a new account will land you in “OOC” mode. The ooc-version of look (sitting in the Account cmdset) will show a list of available characters if you have any. You can also enter charcreate to make a new character. The charcreate is a simple command coming with Evennia that just lets you make a new character with a given name and description. We will later modify that to kick off our chargen. For now we’ll just keep in mind that’s how we’ll start off the menu.
In Knave, most of the character-generation is random. This means this tutorial can be pretty
compact while still showing the basic idea. What we will create is a menu looking like this:
-Silas
+Silas
STR +1
DEX +2
@@ -159,15 +155,15 @@ compact while still showing the basic idea. What we will create is a menu lookin
CHA +2
You are lanky with a sunken face and filthy hair, breathy speech, and foreign clothing.
-You were a herbalist, but you were pursued and ended up a knave. You are honest but also
-suspicious. You are of the neutral alignment.
+You were a herbalist, but you were pursued and ended up a knave. You are honest but also
+suspicious. You are of the neutral alignment.
-Your belongings:
-Brigandine armor, ration, ration, sword, torch, torch, torch, torch, torch,
+Your belongings:
+Brigandine armor, ration, ration, sword, torch, torch, torch, torch, torch,
tinderbox, chisel, whistle
----------------------------------------------------------------------------------------
-1. Change your name
+1. Change your name
2. Swap two of your ability scores (once)
3. Accept and create character
@@ -180,7 +176,7 @@ compact while still showing the basic idea. What we will create is a menu lookin
You can now enter a new name. When pressing return you’ll get back to the first menu node
showing your character, now with the new name.
If you select 2, you go to another menu node:
-
Your current abilities:
+Your current abilities:
STR +1
DEX +2
@@ -196,12 +192,9 @@ To swap the values of e.g. STR and INT, write 'STR INT'. Empty to abort.
------------------------------------------------------------------------------------------
-If you enter WIS CHA here, WIS will become +2 and CHA +1. You will then again go back
-to the main node to see your new character, but this time the option to swap will no longer be
-available (you can only do it once).
-If you finally select the Accept and create character option, the character will be created
-and you’ll leave the menu;
-Character was created!
+If you enter WIS CHA here, WIS will become +2 and CHA +1. You will then again go back to the main node to see your new character, but this time the option to swap will no longer be available (you can only do it once).
+If you finally select the Accept and create character option, the character will be created and you’ll leave the menu;
+
@@ -217,7 +210,7 @@ and you’ll leave the menu;
Since most of Knave’s character generation is random we will need to roll on random tables
from the Knave rulebook. While we added the ability to roll on a random table back in the
Rules Tutorial, we haven’t added the relevant tables yet.
-# in mygame/evadventure/random_tables.py
+# in mygame/evadventure/random_tables.py
chargen_tables = {
"physique": [
@@ -226,8 +219,8 @@ from the Knave rulebook. While we added the ability to roll on a random
"statuesque", "stout", "tiny", "towering", "willowy", "wiry",
],
"face": [
- "bloated", "blunt", "bony", # ...
- ], # ...
+ "bloated", "blunt", "bony", # ...
+ ], # ...
}
@@ -247,19 +240,19 @@ keep in here.
During character generation we will need an entity to store/retain the changes, like a
‘temporary character sheet’.
-# in mygame/evadventure/chargen.py
+# in mygame/evadventure/chargen.py
from .random_tables import chargen_tables
-from .rules import dice
+from .rules import dice
class TemporaryCharacterSheet:
-
+
def _random_ability(self):
return min(dice.roll("1d6"), dice.roll("1d6"), dice.roll("1d6"))
-
+
def __init__(self):
self.ability_changes = 0 # how many times we tried swap abilities
-
+
# name will likely be modified later
self.name = dice.roll_random_table("1d282", chargen_tables["name"])
@@ -291,7 +284,7 @@ keep in here.
f" {alignment} alignment."
)
- #
+ #
self.hp_max = max(5, dice.roll("1d8"))
self.hp = self.hp_max
self.xp = 0
@@ -323,7 +316,7 @@ Abilities once. We will use this to know if it has been done or not.
6.3.1. Showing the sheet
Now that we have our temporary character sheet, we should make it easy to visualize it.
-# in mygame/evadventure/chargen.py
+# in mygame/evadventure/chargen.py
_TEMP_SHEET = """
{name}
@@ -336,15 +329,15 @@ Abilities once. We will use this to know if it has been done or not.CHA +{charisma}
{description}
-
+
Your belongings:
{equipment}
"""
-class TemporaryCharacterSheet:
-
- # ...
-
+class TemporaryCharacterSheet:
+
+ # ...
+
def show_sheet(self):
equipment = (
str(item)
@@ -372,18 +365,18 @@ Abilities once. We will use this to know if it has been done or not.6.3.2. Apply character
Once we are happy with our character, we need to actually create it with the stats we chose.
This is a bit more involved.
-# in mygame/evadventure/chargen.py
+# in mygame/evadventure/chargen.py
-# ...
+# ...
from .characters import EvAdventureCharacter
from evennia import create_object
-from evennia.prototypes.spawner import spawn
+from evennia.prototypes.spawner import spawn
class TemporaryCharacterSheet:
-
- # ...
+
+ # ...
def apply(self):
# create character object with given abilities
@@ -399,28 +392,28 @@ This is a bit more involved.
("charisma", self.wisdom),
("hp", self.hp),
("hp_max", self.hp_max),
- ("desc", self.desc),
- ),
- )
+ ("desc", self.desc),
+ ),
+ )
# spawn equipment (will require prototypes created before it works)
- if self.weapon:
- weapon = spawn(self.weapon)
+ if self.weapon:
+ weapon = spawn(self.weapon)
new_character.equipment.move(weapon)
- if self.shield:
- shield = spawn(self.shield)
+ if self.shield:
+ shield = spawn(self.shield)
new_character.equipment.move(shield)
- if self.armor:
- armor = spawn(self.armor)
+ if self.armor:
+ armor = spawn(self.armor)
new_character.equipment.move(armor)
- if self.helmet:
- helmet = spawn(self.helmet)
+ if self.helmet:
+ helmet = spawn(self.helmet)
new_character.equipment.move(helmet)
-
+
for item in self.backpack:
item = spawn(item)
new_character.equipment.store(item)
-
- return new_character
+
+ return new_character
We use create_object to create a new EvAdventureCharacter. We feed it with all relevant data from the temporary character sheet. This is when these become an actual character.
@@ -441,11 +434,11 @@ armor” etc.
EvMenu.
# in mygame/evadventure/chargen.py
-from evennia import EvMenu
+from evennia import EvMenu
# ...
-# chargen menu
+# chargen menu
# this goes to the bottom of the module
@@ -461,29 +454,33 @@ armor” etc.
# this generates all random components of the character
tmp_character = TemporaryCharacterSheet()
- EvMenu(caller, menutree, session=session, tmp_character=tmp_character)
+ EvMenu(
+ caller,
+ menutree,
+ session=session,
+ startnode="node_chargen",
+ startnode_input=("", {"tmp_character": tmp_character}),
+ )
-This first function is what we will call from elsewhere (for example from a custom charcreate
-command) to kick the menu into gear.
+This first function is what we will call from elsewhere (for example from a custom charcreate command) to kick the menu into gear.
It takes the caller (the one to want to start the menu) and a session argument. The latter will help track just which client-connection we are using (depending on Evennia settings, you could be connecting with multiple clients).
-We create a TemporaryCharacterSheet and call .generate() to make a random character. We then feed all this into EvMenu.
+We create a TemporaryCharacterSheet and feed all this into EvMenu. The startnode and startnode_input keywords makes sure to enter the menu at the “node_chargen” node (which we will create below) and call it with with the provided arguments.
The moment this happens, the user will be in the menu, there are no further steps needed.
-The menutree is what we’ll create next. It describes which menu ‘nodes’ are available to jump
-between.
+The menutree is what we’ll create next. It describes which menu ‘nodes’ are available to jump between.
6.5. Main Node: Choosing what to do
This is the first menu node. It will act as a central hub, from which one can choose different
actions.
-# in mygame/evadventure/chargen.py
+# in mygame/evadventure/chargen.py
# ...
# at the end of the module, but before the `start_chargen` function
-def node_chargen(caller, raw_string, **kwargs):
+def node_chargen(caller, raw_string, **kwargs):
tmp_character = kwargs["tmp_character"]
@@ -491,20 +488,20 @@ actions.
options = [
{
- "desc": "Change your name",
+ "desc": "Change your name",
"goto": ("node_change_name", kwargs)
}
]
if tmp_character.ability_changes <= 0:
- options.append(
- {
+ options.append(
+ {
"desc": "Swap two of your ability scores (once)",
"goto": ("node_swap_abilities", kwargs),
}
)
options.append(
{
- "desc": "Accept and create character",
+ "desc": "Accept and create character",
"goto": ("node_apply_character", kwargs)
},
)
@@ -517,12 +514,14 @@ actions.
A lot to unpack here! In Evennia, it’s convention to name your node-functions node_*. While
not required, it helps you track what is a node and not.
Every menu-node, should accept caller, raw_string, **kwargs as arguments. Here caller is the caller you passed into the EvMenu call. raw_string is the input given by the user in order to get to this node, so currently empty. The **kwargs are all extra keyword arguments passed into EvMenu. They can also be passed between nodes. In this case, we passed the keyword tmp_character to EvMenu. We now have the temporary character sheet available in the node!
+
+Note that above we created the menu with the startnode="node_chargen" and the tuple startnode_input=("", {"tmp_character": tmp_character}). Assuming we register the above function as the node "node_chargen", it will start out being called as node_chargen(caller, "", tmp_character=tmp_character) (EvMenu will add caller on its own). This is one way we can pass outside data into the menu as it starts.
+
An EvMenu node must always return two things - text and options. The text is what will
show to the user when looking at this node. The options are, well, what options should be
presented to move on from here to some other place.
-For the text, we simply get a pretty-print of the temporary character sheet. A single option is
-defined as a dict like this:
-{
+For the text, we simply get a pretty-print of the temporary character sheet. A single option is defined as a dict like this:
+{
"key": ("name". "alias1", "alias2", ...), # if skipped, auto-show a number
"desc": "text to describe what happens when selecting option",.
"goto": ("name of node or a callable", kwargs_to_pass_into_next_node_or_callable)
@@ -546,11 +545,11 @@ to each node, since that contains our temporary character sheet.
# ...
-# after previous node
+# after previous node
def _update_name(caller, raw_string, **kwargs):
"""
- Used by node_change_name below to check what user
+ Used by node_change_name below to check what user
entered and update the name if appropriate.
"""
@@ -570,11 +569,11 @@ to each node, since that contains our temporary character sheet.
text = (
f"Your current name is |w{tmp_character.name}|n. "
- "Enter a new name or leave empty to abort."
+ "Enter a new name or leave empty to abort."
)
options = {
- "key": "_default",
+ "key": "_default",
"goto": (_update_name, kwargs)
}
@@ -603,11 +602,11 @@ were at.
6.7. Node: Swapping Abilities around
You get here by selecting the second option from the node_chargen node.
-# in mygame/evadventure/chargen.py
+# in mygame/evadventure/chargen.py
# ...
-# after previous node
+# after previous node
_ABILITIES = {
"STR": "strength",
@@ -635,24 +634,24 @@ were at.
if abi1 not in _ABILITIES or abi2 not in _ABILITIES:
caller.msg("Not a familiar set of abilites.")
return None, kwargs
-
+
# looks okay = swap values. We need to convert STR to strength etc
tmp_character = kwargs["tmp_character"]
abi1 = _ABILITIES[abi1]
abi2 = _ABILITIES[abi2]
abival1 = getattr(tmp_character, abi1)
abival2 = getattr(tmp_character, abi2)
-
+
setattr(tmp_character, abi1, abival2)
setattr(tmp_character, abi2, abival1)
-
+
tmp_character.ability_changes += 1
-
+
return "node_chargen", kwargs
-
+
def node_swap_abilities(caller, raw_string, **kwargs):
- """
+ """
One is allowed to swap the values of two abilities around, once.
"""
@@ -675,7 +674,7 @@ were at.
"""
options = {"key": "_default", "goto": (_swap_abilities, kwargs)}
-
+
return text, options
@@ -693,44 +692,47 @@ we use caller.msg()
6.8. Node: Creating the Character
We get here from the main node by opting to finish chargen.
node_apply_character(caller, raw_string, **kwargs):
- """
+ """
End chargen and create the character. We will also puppet it.
-
- """
+
+ """
tmp_character = kwargs["tmp_character"]
- new_character = tmp_character.apply(caller)
-
- caller.account.add_character(new_character)
-
+ new_character = tmp_character.apply(caller)
+
+ caller.account.add_character(new_character)
+
text = "Character created!"
-
- return text, None
+
+ return text, None
-When entering the node, we will take the Temporary character sheet and use its .appy method to create a new Character with all equipment.
+When entering the node, we will take the Temporary character sheet and use its .apply method to create a new Character with all equipment.
This is what is called an end node, because it returns None instead of options. After this, the menu will exit. We will be back to the default character selection screen. The characters found on that screen are the ones listed in the _playable_characters Attribute, so we need to also the new character to it.
6.9. Tying the nodes together
def start_chargen(caller, session=None):
-"""
-This is a start point for spinning up the chargen from a command later.
+ """
+ This is a start point for spinning up the chargen from a command later.
"""
menutree = { # <----- can now add this!
- "node_chargen": node_chargen,
- "node_change_name": node_change_name,
- "node_swap_abilities": node_swap_abilities,
- "node_apply_character": node_apply_character
+ "node_chargen": node_chargen,
+ "node_change_name": node_change_name,
+ "node_swap_abilities": node_swap_abilities,
+ "node_apply_character": node_apply_character,
}
-
+
# this generates all random components of the character
tmp_character = TemporaryCharacterSheet()
- EvMenu(caller, menutree, session=session,
- startnode="node_chargen", # <-----
- tmp_character=tmp_character)
-
+ EvMenu(
+ caller,
+ menutree,
+ session=session,
+ startnode="node_chargen", # <-- make sure it's set!
+ startnode_input=("", {"tmp_character": tmp_character}),
+ )
Now that we have all the nodes, we add them to the menutree we left empty before. We only add the nodes, not the goto-helpers! The keys we set in the menutree dictionary are the names we should use to point to nodes from inside the menu (and we did).
diff --git a/docs/latest/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Equipment.html b/docs/latest/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Equipment.html
index 31bf79b53c..6786c6f7c3 100644
--- a/docs/latest/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Equipment.html
+++ b/docs/latest/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Equipment.html
@@ -612,7 +612,7 @@ double-check we can actually fit the thing, then we add the item to the backpack
self.equipment.add(moved_object)
-At this means that the equipmenthandler will check the NPC, and since it’s not a equippable thing, an EquipmentError will be raised, failing the creation. Since we want to be able to create npcs etc easily, we will handle this error with a try...except statement like so:
+This means that the equipmenthandler will check the NPC, and since it’s not a equippable thing, an EquipmentError will be raised, failing the creation. Since we want to be able to create npcs etc easily, we will handle this error with a try...except statement like so:
# mygame/evadventure/characters.py
# ...
from evennia import logger
diff --git a/docs/latest/Setup/Installation.html b/docs/latest/Setup/Installation.html
index 56463c2c18..c6c64a7eef 100644
--- a/docs/latest/Setup/Installation.html
+++ b/docs/latest/Setup/Installation.html
@@ -128,10 +128,11 @@
Installation
Important
-
If you are converting an existing game from a previous Evennia version, see here.
+
If you are converting an existing game from a previous Evennia version, you will need to upgrade.
The fastest way to install Evennia is to use the pip installer that comes with Python (read on).
You can also clone Evennia from github or use docker. Some users have also experimented with installing Evennia on Android.
+If you are converting an existing game, please follow the upgrade instructions.