# python writes my skills for me

march 4, 2021
#godotengine #json #python
Similar to Magic: The Gathering cards, the functionality of my skills is composed of keywords. For instance, a skill with the 'damage' keyword + 'bleeding' keyword will inflict pure damage + a bleeding status effect.
Since skills derive their effects from existing keywords, each individual skill has very little to no unique code. Repetitive, formulaic tasks are better left to scripts, so I wrote a skillmaker to write skills for me.

## what do blessfrey skills look like?

(Click on the shrunk images for an expanded view.)
They are Godot scenes composed of a single node with an attached script.
The .TSCN and .GD files look like this in the engine.
But Godot files are just simple text, so you can open them in any text editor. Really, you could write the bulk of a Godot game in Notepad, if you wanted to. That's perfect for me!
The same files look like this in xed (similar program to Notepad):
The .GD file is identical to what gets displayed in Godot Engine, but the .TSCN is a little cryptic. If I learn how the syntax, I can make a script to write it for me. I don't understand all of it, since I only deciphered what I need for making a skill.

## examining the skill scene file

(You can also see the text @ Pastebin.)
Since I designed Blessfrey skills to have a simple, consistent structure, the .TSCN for any two skills will be very similar.
After experimenting in + out of Godot Engine, I've found that that first line is always the same.

### red + yellow resources

The red + yellow sections are the scene's resources. This includes any .GD files attached to nodes in the scene tree and any resources (textures, fonts, etc) you load as properties. Those are the properties that look like my icon:
The script + the resources look so similar because they are both treated as properties of the node. The formula is...

- `[ext_resource path="`
- obviously followed by the path of the resource. If resources are kept in a predictable place, it's easier on the script.
- `" type="`
- whatever the resource type is (examples include Script, Texture, DynamicFontData)
- `" id=`
- a unique number (obviously used for referencing)

### green groups

Green marks the groups of each node in the scene. You can see the groups are just an array of strings.
Broken into pieces, that looks like

- `[node`
- `name="CuttheGuy"` - the name of the node (node.name) goes between the quotation marks
- `type="Node"` - the type of the node, so something like Node, Node2D, or Label
- `groups=[`
- `"group_name",` - each group name is wrapped in quotation marks and separated by commas + line-breaks.
- `]]` - close all brackets

Two interesting things about the group_name property. One, the engine adds a comma at the end of every line, even to last or only group of the node. Two, if your scene node has no groups, this property will be omitted from the node. If CuttheGuy belonged to no groups, it would just look like `[node name="CuttheGuy" type="Node"]`.

### blue properties

The properties are inside blue. Since scripts are treated the same as any other resource property, the attached script is referenced in this section.
Resources look like `icon = ExtResource( 2 )`.
`Icon` is my variable. I declared it in a script that the skill inherits from as `export(Texture) var icon = preload('res://res/art/skillIcons/EmptySkillSlot.png') setget , get_icon`. The `script` variable was declared by the engine and isn't in my .GD files.
The `2` is an id from the yellow section. It must match the resource's number from earlier.
If I store all my skill icons in the skillIcons directory and give them the proper name, they'll be found when they're needed, no manually loading necessary. This is a test skill with a generic skill icon, but it would be named something like `CuttheGuy.png`.
Other properties are more straight-forward. They are the same exported member variables declared in the node's attached .GD script, followed by an equal sign and the value.

### overall

They aren't so confusing when read as text files. The Godot team must have planned them to be human-readable. :)

## altar of spellmaking

So as you modify the groups and properties of a node, the engine is actually just formatting your input into text files. Since I have a functional understanding of how to manually format data, I can write a skill-formatting script to do it for me.
The tool is named "Altar of Spellmaking" as an Oblivion reference and uses JSON + Python3. Godot can interpret JSON files on its own, so maybe someday the game will automatically generate skills from on the JSON file at load time. For now, though, I see a frivolous excuse to use Python, so the interpreter is going to be in Python. Its input shall be a JSON file, and its output shall be matching .TSCN + .GD files.

### writing a skill with JSON

JSON isn't a Turing complete language, just a notation. It looks like a dictionary and uses attribute-value relationships. It's good at storing nested groups of information and can be easily interpretted by other languages. Since my skills can be described as a collection of attributes + keyword effects, they can wrestled into the JSON format.
(You can also see the text @ Pastebin.)
All the repetitive, obvious, or derivative aspects of the skill do not need to appear in the JSON, since Python will be compensating.
I identify the skill by its name in lower-case + underscores just for my sake. The program doesn't care what the skill's id is or if it has an id at all.
Inside, I have some basic attributes like the id and associated class + stat. The tags will become some of the node's groups. The keywords take place in the skill's phases, which are lists of dictionaries. To build the skill phase, Python will interate over each item in the dictionary and use the internal data to supply the keyword's necessary input or conditions.
Conditional effects look like the image below.
(You can also see the text @ Pastebin.)
The `cond` consists of the `code` (literal GDscript code) and `desc` (an English translation of that code). It's not perfect, but it's quicker for me to just write the code and write the skill description than try to have Python translate. This does mean my code has to be perfect, and I have pressure to adhere to the standard language of a skill description. That's a problem, but it is much smaller than the problem of not using JSON at all.
Eventually, I would prefer the desc to be an id from the translation spreadsheet instead of hard-coded text. (I discussed translation in blessfrey in japanese.)

### writing a Godot scene with Python3

Using Python to format JSON values into a Godot scene + script is kind of ridiculous, so I have 168 lines of code and half of them start with `f.write`. Now that it's written, though, it's easy to maintain. Since the overall structure doesn't change, all I have to do is tweak a line here or there to reflect refactors. I'll include a picture of the main method, so you can get a sense of the flow of the program:
(You can also see the text @ Pastebin.)
The output is a nested directory of all the skills, so I can just copy + paste the `skills` folder over the one in the engine. And it works! The first skill image's code looks machine-generated because it was.

## is it better than just making skills in the engine?

If I only had ten or eleven skills, then probably not. I'm planning on having around 40 skills per class, though, and I'm only one person. Since the skills are very formulaic, I'd rather have Python do all the copying + pasting for me while I worry about what makes my skills unique!
last updated March 6, 2021