For my next article I’m going to explain how I implemented modding. Please be aware that this is a more technically focused article.
I wanted to make sure the game was moddable because it can be lots of fun for the players: either by total conversions or just changing a few options and increase the game’s longevity. The game generally sticks around longer. That can only be a good thing!
I decided I would take the common approach of using XML files to hold the majority of the game data. I like XML because I feel it gives the players readable files that can easily be edited. It’s also generally easy to work with. However, I wanted to make sure these were “simple” XML files. So I don’t include any of the more complex features you can do with XML (ie: DTD’s).
What can you mod?
I made it possible so the majority of the game data can be modded. This includes, but is not limited to:
- orbitals (planets)
- stellar objects (stars)
- trade guilds
- technology upgrades
- races (which includes all necessary starting values)
- ship types (ie: destroyer, battleship values)
- ship components
- particle effects (there is actually a tool present to make these)
You can also mod parts of the UI, namely the look and feel. Since TWL is defined by XML, this fits in nicely. I do not expect anyone but the hardcore modders to really try to mod the UI. TWL can be fairly complex if you are not familiar with UIs and programming in general. But at least the option is there.
How does the XML look? Here is an example for one of the races:
This is an image of the modifier section and the starting ship components the empire knows. As you can see, the modifiers are listing what are the valid modifiers for the various weapons (WEAPON_1 can be marked as LONG_RANGE or RAPID_FIRE during ship design).
Here is another example of defining a ship type:
This is one of the rare ship types you can find. You can see how it can hold loads of components (4,000 spacial units) but costs A LOT! (27,000 industry). You can add or change these to your liking.
I also wanted to have modding for some uncommon elements of the game. I wanted to be able to allow the player to specify their own unique maps that can be outside of the game’s usual settings. So these are essentially pre-made maps. You’ll be able to specify the exact locations, and every single piece of useful information in these pre-mades. You could make up the Star Wars galaxy (this is pretty popular) if you wanted too, or something else. Yep, I’m a big Star Wars fan.
I think that having the ability to make pre-made maps is important. But I wanted to take it one step further. Since having to define every single piece of information could be a lot of work, I’m going to support random generation for various elements. Maybe you only want to have one or two unique planets. Maybe you just want to place certain stars in certain locations. Or maybe you just care about having their names right and everything else about them random. You’ll be able to do this! Random tags will exist to generate information you don’t care about it.
What can’t you mod?
Right now the main parts that you cannot mod are: any of the AI – fleet AI, game AI or anything else. For the time being, this is going to be hard coded. I may change this depending on how much funding I receive in the future.
You also cannot change any of the locations of the UI or the components on them. I don’t think I’ll ever support this.
Some Pit Falls
I ran into some pitfalls while coding up the game to support modding. The first one is maybe not so obvious to the average person: the time and effort to require to support modding. It took me quite awhile to make up the infrastructure to handle this feature. The reason is because all of the data is not only defined in the code but is now outside, in a file somewhere. This means that the game has to be able to load and read the various data files, then build the in memory objects to represent it. This can be a big project since more code and testing needs to be done.
Another issue was with the XML parsers. I started to write nested XML files in some cases, namely the races XML file. The Race file has everything that defines a race: name, bonuses/negatives, starting locations(which include the stellar objects, orbitals, resources, built structures, etc), starting technologies and so on. As I’m sure you are thinking, it gets nested fast! Also I started using the same tags in different files, such as the modifier tags (gives a modifier to something, like +10 Industry) and resource tags (defining what resources are required to build something). The races.xml and technologies.xml both use the modifier tags. I wanted an easy way to be able to reuse the parsing code but make it obvious what’s going on code-wise. This would help me maintain the game and extend it for the future (which I intend to support for a long time!) easier. We should always strive to have some level of code reuse in our programs.
There are many XML parsers out there, DOM, SAX, and various pulling parsers. I usually use SAX and sometimes I use DOM. I’m personally not a fan of pulling parsers. All of these parsers were not capable of easily parsing many nested documents without writing lots and lots of code. I haven’t been able to find a good/easy way of using SAX to do many nested statements and DOM is just a pain to use sometimes, plus it isn’t as efficient as SAX. So I decided to write my own parser!
The Pew Pew XML Parser
I named this after nukers(casters) in MMORPGS – they blast (pew pew) mobs with spells. You can think of it as being able to blast away the nestings of the XML file with little effort. This is built on top of SAX.
Now, this is a bit technical, so bear with me. Feel free to skip to the Mod Support section if you aren’t interested.
Where in SAX, you simply read a file and then implement the code to read the data in and decide what to do when a tag comes with no state data, the Pew Pew Parser works differently. With Pew, you attach a top level filter to a parser and provide a file name. This filter is responsible for looking at the tags and deciding what to do. Each filter has “tags” and then “group tags”. The “tags” are straight data, like name, description, or ID. The filter will fill this in on the correct in-memory object. So for example, we can have a Race object with Name as a field. The filter would read in the name tag and then insert that data into the Race’s Name field.
Here is an example:
The other part are the group tags. These group tags are for nested tags. You attach a filter to this tag. So when the parser detects a group tag has been read, it’ll pass control to the next filter in a stack format. That filter will be able to handle everything it’s supposed to. For example, I could have a ModifierFilter that handles modifiers for something (in this case a Race). So when the XML gets to a point where the tag appears, the parser will pass control from the RaceFilter to the ModifierFilter.
Then the ModifierFilter will be able to handle everything that is supposed to happen during a Modifier. The beauty of this is…you guessed it…I can reuse this code for any XML file.
Here are the tags for the RaceFilter:
You can see the normal tags (name, description, etc) and then the group tags (such as mod). When a group tag is seen, the parser will automatically change to that filter (so the ModifierFilter will be called). When the ModifierFilter is completed, it’ll return control back to the RaceFilter. The same goes with the improvement tag.
Using this parser I have been able to define sets of nested XML tags – and have successfully hidden it from the modder. I’ll also be able to use these filters to load saved games.
I do have some code to do proper error reporting so if the parser finds something it does not like, it’ll display an error message. This helps figure out what went wrong before you even play the game. As such, a modded game will be more stable.
Even though it took me a few weeks to get this written, I can reuse it constantly in this game, as well in future games I make. Overall, I’m pretty happy with my implementation.
On a side note: This parser cannot be obtained anywhere on the web. I’m thinking about releasing it for free use. I do not know if anyone is interested in using this thing but if there is enough interest, I may release it. Feel free to contact me outside of this article at: firstname.lastname@example.org
It is my goal to try my best at supporting the mod community. I have a couple of goals here:
- Ensure mods are stable. I really do not like it when I’m playing a modded game and it is prone to crashing. I will try my best to resolve any issues with mods crashing the game. I’ve tried to write a lot of code that handles error conditions gracefully, as well as having the Pew Pew Parser ensure the data from the XML files is in a more valid format and it has all of the right data.
- I will take mod feature requests and attempt to put them into the game. So maybe a player needs a special function for a weapon type or something. I’ll try to honor this request. Of course, this is no guarantee, and I may get more requests than I can fulfill, but you can be sure I’ll try my best in regards of adding new features and functionality.
I feel this is an important investment of my time as I want the game to be around for many years to come – either in the base game or modded in some form. I really love playing Hearts of Iron 3 mods, but some of them just do not jell well with the engine and they crash a lot. I would love to be able to have my game be stable with mods.
Finally, I have been documenting the XML files with explanations on how things work. I’ve also written documentation on the game’s website. So anyone should be able to easily find out how to mod this game and get to work making their favorite mods faster!
Intended Side Benefit
With everything I’ve done so far for the game in regards to modding, there is one large benefit I am getting: I will be able to design the content using my modding tools. Generally, for me, using a tool (like these XML files) to define the game values is faster than writing the content in the code (ie: defining ship components in tables or classes). So in a way, I save time in the end. This is the same for the documentation – it’ll help me remember what does what if I haven’t looked at it for a while.
I can also tweak game play aspects without having to recompile the code – I can simply tweak values and see how they work. This’ll help with balancing and ensuring good game play quickly.
What is left?
There are a few items left, namely being able to have a separate mod directory and the functionality to turn the mod on/off without editing the main data files. I’ll be working on this later, after the game is mostly completed. Then the other items deal with changing many of the “hard coded” values in the game moddable, such as size of fleet combat nodes, and so on. These are defined in the game’s code at the moment so I’ll need to transfer them to files (I have a class that handles all of this, so it isn’t too much of an effort).
So there you have it – this is how I’ve modded the game. I hope to be able to support many mod types such as Star Wars, Star Trek, Mass Effect, or any of the popular Sci-fi IPs out there.
What am I currently working on?
I decided to add this section to give you all an idea of what I’ve been up too. These articles usually are about topics I completed a long time ago, sometimes up to 6 months. My policy is to mostly write only about what I’ve done, not what I will do. I do not want to create any false impressions about the game.
I’ve been spending time programming the fleet combat system – which includes ship components, ship design, colonization, of course, the combat. I will be doing a large article on this and it’s one I’m personally really excited for! But we’ll just have to wait until that article appears in the coming months.
Thanks for reading and I look forward to your comments!
dayrinni has been a Space Sector contributor since October 2011. This is his first foray into writing articles for any review site. He is an avid gamer in the genres of 4X, Strategy, MMO’s and RPGs. Finally, he has been the implementor of several MUDs and is currently working on a space 4X game that offers large scope and complexity. See all dayrinni’s posts here. In particular, check his “what makes a good game” and “making a space 4X game” series.Subscribe RSS
- Making a Space 4X Game: Setting the Stage
- Distant Worlds: Universe to Launch in May 2014
- Making a Space 4X Game: An Overview on Graphics Libraries
- Endless Space: New Big Patch, Mac News and Modding
- Beyond Beyaan: A Space 4X Game Engine [Kickstarter]