this is a very random comment but
every game should have a command to pet the doggo. doggos good.
that said, this is an interesting thread to follow!
Evennia has a lot of tutorials, but they’re geared at the basics, not what you’d actually want in your game.
So here’s one where I write the code for you and tell you want to do.
Lesson 1: Make skills and roll modifiers for your characters.
Disclaimer: I typed this all up from memory. It’s probably got a few typos, so I trust you to be able to figure out what’s wrong, by looking at adjacent code and making yours look just like the code that’s next to it. One of the most valuable skills you can learn is figuring out what to do when your code spits out an error. Make errors early on! The site Stack overflow is your friend, too.
So you have Evennia running. You can log in as your admin account. You have access to the command line.
First, pull up characters.py in your game directory.
Now, set up your skills as a dict, in characters.py, in the at_object_creation method, which should be near the top.
self.db.skills = {
"Medicine": 1,
"Underwater Basket Weaving": 1
}
Your skills won’t automatically get added to existing characters, so you’ll have to create a method to add them manually, or reload your character object. Reloading your character object resets ALL attributes to what’s in at_character_creation, so make sure you only use it when you’re fine with resetting your character back to nothing. Check the Evennia documentation for how to do this. I don’t remember offhand, since it’s been over a year since I’ve reloaded an object.
Once you get your skills on your object, you can reference them easily. Here’s an example line. Don’t add it anywhere yet.
self.db.skills.get("Medicine", 0)
The zero at the end says that if the Medicine skill isn’t found, default to zero.
You can run python lines as your admin account while being logged in.
Try typing:
py self.msg(self.db.skills.get("Medicine", 0))
This should message (msg) your character the value of its Medicine skill.
Now, let’s add buffs / debuffs or other roll modifiers. Once again, add a dict of modifiers to your at_character_creation method:
self.db.modifiers = {}
It can go just below your skills dict.
Now we need a method in your character class to add modifiers.
First, add this to the top of your characters.py file.
import time
We do this because we need to know the time for this part. It’ll make sense eventually.
Next, add this to the bottom of your characters.py file.
def add_mod(self, name, value, effect, duration):
# adds a value to a modifier, value can be negative for a debuff
# name is the name of the mod, e.g. "Squeamish"
# value is how strong this mod is, e.g. 2 or -4
# effect is the skill or other roll it targets, e.g. "Medicine"
# duration is how long it should last, in minutes
# get the strength of the current_mod
current_mod = self.db.modifiers.get(name, 0)
# update or set the value of the modifier
self.db.modifier[name] = (current _mod + value, effect, time.time() + duration * 60)
# What does the above mean?
# We're adding a list of 3 entries to self.db.modifier, using the name of the mod as the key
# current_mod + value is our new value
# effect is set without change
# time.time() means to get the current numeric time, and we add to it the duration we set, but we multiply the duration by 60 because the duration is in minutes, but time.time() is in seconds, so we need to convert it
A line that begins with a # is a comment. Read the comment lines above to learn what this method is doing. There are only two real lines of code in that method. The rest are comments explaining what’s going on.
If you want buffs & debuffs that don’t stack, you can alter the above code by removing the current_mod code. This will set static values so that your +2 Holy Weaver buff doesn’t stack to a +4 the second time it’s used in succession. If you want both cumulative and static buffs, make two methods. Alternatively, add a “stacking” flag to the method and set stacking = True or stacking = False, then add a little check for whether or not it should stack, setting current_mod to 0 if it doesn’t stack.
Now, modifiers don’t expire on their own. We need a method to expire old modifiers. This method has only 3 lines of code, but again, I’ve commented it to explain it all.
def expire_mods(self):
# check all mods and remove any that have expired
# first, iterate through all keys in the modifier dict
for mod_name in self.db.modifiers:
# check if its expiration time (entry 2 in the mod's list) is before the current time
# We're iterating on the keys of self.db.modifiers, not the lists, so we need to use .get to get the list, and pull out entry [2], the expiration time, then compare that to the current time.
if self.db.modifiers.get(mod_name)[2] < time.time():
# if we're here, then we've confirmed that a mod is old and should be removed, so let's .pop it out of there
self.db.modifiers.pop(mod_name)
There’s only one last thing you need: a way to check skills with their mods. Again, this method is only 2 lines, but commented a bunch:
def get_skill(self, name):
# First, expire old mods. We don't need to check for expiration and removal at any point up until now.
self.expire_mods()
# There are no arguments with this, even though the expire_mods method has "self" as an argument. This is because "self" is automatically sent for any method call, regardless of whether or not you want it to be sent.
# Next, pull the value of the skill out of the skills dict, and add the value of the corresponding mod from the modifier dict
# If the mod is negative, you'll be adding a negative, which is just subtraction, so this accounts for buffs and debuffs.
return self.db.skills.get(name, 0) + self.db.modifiers.get(name, 0)
In your commands.py, add a command to test your code.
class ListSkills(command):
# Type "skills" to use this command
key = ["skills"]
def func:
# Set our message to be a blank string.
message = ""
# The "self" from characters.py is now "self.caller" since we're "calling" this command.
for skill in self.caller.db.skills:
# We're creating a string that will eventually be sent to the player. We can add additional text to that string with +=. The code \n means to go down one line, as if you pressed enter.
message += "Your " + skill + " skill is at level " + self.caller.get_skill(skill) + "\n"
# We now have a string that lists the names and values of each skill, one per line. Let's send this message to the player.
self.caller.msg(message)
Whenever you add a command, you need to import and add it to the default_cmdset.py file.
from command.commands import ListSkills
And then further down the file near the “super,” add something like this:
ListSkills.add()
Now at your command prompt, type:
Evennia restart
If you get no errors in the command line of your logged in character, type “skills” and press enter, and look at your beautiful skills.
Congrats, you now know about 80% of what it takes to code in Evennia.
If you do this lesson and you’re still confused about any errors or lines of code, feel free to ask me and I’ll be happy to help.
@Jumpscare None of this tells me how to pet the doggy in code combat, the new limbo I am stuck in.
(actually trying to figure out Virtual Box, since I do not have Hyper-V)
@Jennkryst I don’t know what any of that means, sorry.
I installed WSL2 on my desktop, which is Linux on Windows.
Some combination of these commands should work. Change “mygame” to whatever you want your game to be called internally.
source evenv/bin/activate
pip install python3.9
python3.9 -m venv evenv
pip install evennia
evennia --init mygame
cd mygame
evennia start
To start Evennia after rebooting, I type the following.
source evenv/bin/activate
python3.9 -m venv evenv
cd heaven
evennia start
@Jumpscare I got linked to this here thingy:
@IoleRae said in Learning to Code - A Sprite Break:
And there is a section where you tell your hero sprite to hero.moveTo(2), and there is a dog sprite standing there, but no instruction on how to give the dog head pats.
This is criminal.
Sorry, I don’t know how to code anything besides Evennia.
@Jennkryst This is a really weird response to someone typing out a bunch of stuff to try and help you after you asked for help.
@Jumpscare said in Learning to Code - A Sprite Break:
Disclaimer: I typed this all up from memory.
I can’t type up a damn thing from memory without looking at it 4,000,000 times, this is very impressive to me lol
@Roz @Jumpscare said she didn’t know what any of what I was talking about meant, so I explained.
I should have clarified the code combat people are the criminals, for not letting me pet the dog.
ahem
Right now, I’m stuck at trying to even install evennia onto the Linux virtual machine (which finally worked on the 4th try, horray!) So progress is happening, just slow. Efforts to resume after work.
You could theoretically run Evennia and all its prereqs inside a Docker container to avoid that.
However, that’s advanced work that involves mashing together two ideas that work well in a vacuum.
EDIT: Even more advanced theory, with Evennia running in Docker you could theoretically hook it into k8s to make it autoscale when under load. Why you would do this is another question.
@Jennkryst You likely did not reactivate your venv.
@Istus is right.
source evenv/bin/activate
Make sure you’re in the same directory that you setup your venv before doing this command.
python3.9 -m venv evenv
I don’t know what this does, but it’s necessary from what I’ve seen. I think it sets what Python version you’re using. The latest version of Evennia requires 3.9 or 3.10.
cd game/directory
Replace game/directory with the name of your game’s directory.
evennia start
Now you get to shout orders to Evennia.
@Jumpscare said in Learning to Code - A Sprite Break:
@Istus is right.
source evenv/bin/activate
Make sure you’re in the same directory that you setup your venv before doing this command.python3.9 -m venv evenv
I don’t know what this does, but it’s necessary from what I’ve seen. I think it sets what Python version you’re using. The latest version of Evennia requires 3.9 or 3.10.cd game/directory
Replace game/directory with the name of your game’s directory.evennia start
Now you get to shout orders to Evennia.
#2 on your list is what creates the venv in the first place, so if it’s already established, then this step isn’t needed. Specifically, it’s telling Python 3.9 to run the venv module and output the virtual environment to the evenv directory, which will be created inside the directory you run the command from.
@dvoraen said in Learning to Code - A Sprite Break:
@Jumpscare said in Learning to Code - A Sprite Break:
@Istus is right.
source evenv/bin/activate
Make sure you’re in the same directory that you setup your venv before doing this command.python3.9 -m venv evenv
I don’t know what this does, but it’s necessary from what I’ve seen. I think it sets what Python version you’re using. The latest version of Evennia requires 3.9 or 3.10.cd game/directory
Replace game/directory with the name of your game’s directory.evennia start
Now you get to shout orders to Evennia.#2 on your list is what creates the venv in the first place, so if it’s already established, then this step isn’t needed. Specifically, it’s telling Python 3.9 to run the venv module and output the virtual environment to the evenv directory, which will be created inside the directory you run the command from.
This.
Step 1, that source
command, it sets up your terminal window to know where to find your specially set up python
that your Evennia is using.
So you have to do step 1 every time you open your terminal and get to work.
Step 3 tells your terminal what files you want to work on. So you do that after.
Step 4 starts evennia, the actual program.
Step 2 is part of the install process and should not need repeated.
Thanks. I must’ve made a mistake at some point.
I consider it a miracle that I’m 97% done with making a game in Evennia and it hasn’t exploded in my face yet.
@Jumpscare Revisiting THIS, (I trouble-shot a bug! There is an erroneous space up in (current _mod + value…) and it made things go wobbly, but I fixed it, huzzah!)
… but there is another error getting thrown.
self.db.characteristics = {
name ‘self’ is not defined
@Jennkryst
Where is that code? Where’s the }? I need to see more. When asking for help on errors, it’s best to post the entire method that the error comes from.
But it sounds like your indentation might be wrong and you’ve wandered outside of a method.
Also, congrats on finding errors in my hastily typed tutorial!
@Jumpscare said in Learning to Code - A Sprite Break:
@Jennkryst
Where is that code? Where’s the }? I need to see more. When asking for help on errors, it’s best to post the entire method that the error comes from.
So this is what the bit in characters.py looks like:
self.db.characteristics = {
"Agility": 1,
"Brawn": 1,
"Cunning": 1,
"Intellect": 1,
"Presence": 1,
"Willpower": 1
}
Now, in terminal:
(evenv) jennkryst@Ubuntu:~/muddev/FFGTest$ evennia start
Traceback (most recent call last):
File “/home/jennkryst/evenv/bin/evennia”, line 11, in <module>
main()
File “/home/jennkryst/evenv/lib/python3.10/site-packages/evennia/server/evennia_launcher.py”, line 2344, in main
error_check_python_modules(show_warnings=args.tail_log)
File “/home/jennkryst/evenv/lib/python3.10/site-packages/evennia/server/evennia_launcher.py”, line 1766, in error_check_python_modules
_imp(settings.BASE_CHARACTER_TYPECLASS)
File “/home/jennkryst/evenv/lib/python3.10/site-packages/evennia/server/evennia_launcher.py”, line 1733, in _imp
import(mod, fromlist=[fromlist])
File “/home/jennkryst/muddev/FFGTest/typeclasses/characters.py”, line 16, in <module>
self.db.characteristics = {
NameError: name ‘self’ is not defined
But it sounds like your indentation might be wrong and you’ve wandered outside of a method.
I also forgot a space in there, fixed it, but the problem persisted.
Also, congrats on finding errors in my hastily typed tutorial!
The terminal deserves all the credit, it pointed me at the line in question, I just stared at it until I figured out why. But thanks!
… also, I’m sure I have more issues than just figuring out the self.db problem, but.