Guide:FOMOD
Preface
If followed, this guide will facilitate construction of a fully functional FOMOD by that layman. Before getting started, a little explanation of why this guide exists.
There aren't many quality references detailing FOMOD syntax outside of looking at another author's work. The only real reference has been the Guide to FOMOD scripting by nyrb. This PDF guide covers the basics and gets the information presented, but it isn't presented as ideally as it could be. For example, it only offers a basic layout example of the moduleConfig.xml file, without delving into enough detail to demonstrate how to make more complex FOMODs to fully utilize thier potential. This Guide aims to provide the information required to produce everything from simple FOMOD installers to more in-depth and complex ones. The information will be presented in an order to promote learning, while being more detailed to explain the code and how to employ it.
What is a FOMOD?
FOMODs are scripted installers for game mods. Though they can be deployed for any mod, when scripted correctly, they make particularly complex mod installations an easy experience. They also provide an effective way for authors to ensure mod requirements are satisfied before the mod/options is installed. FOMOD scripts are parsed and displayed as a graphical user interface (GUI) of pages with selectable options. These pages are utilized to guide the user through a mod's installation and its possible options. Though these installers can be scripted in C#, this guide will only focus on FOMODs using XML. It's recommended to become familiar with the terms associated with XML since this Guide uses them extensively.
Tools
The only tool required to script a FOMOD is a text editor. Having an editor with syntax highlighting will make coding far easier. NotePad++ is highly recommended for this task and is what will be used in this guide's examples. Notepad++ is highly customizable, and the default "Darke Mode" is used in the examples provided here.
Mod Mangers parse the scripts into a GUI for the user to install a mod; therefore, one is required for testing. Each Manager's GUI may be slightly different, but the outcome of should be the same. Once a FOMOD script is complete, it's recommended to thoroughly test them using a mod manager. Mod Organizer is used for testing in this Guide.
There is a FOMOD Validator by Ganda that is very help in tracking down errors. Simply run it, point it to the mod's root folder, and Validate. A list of issues and their line numbers will be printed out, when present.
Download these tools for free at the links below:
Differences Between Mod Managers
The main difference between mod manages are the GUI, how coding errors are handled, and how the info.xml file is handled.
The GUI isn't anything to worry about as it can't be controlled. However, how errors are handled is the biggest difference between managers. Mod Organizer uses a heuristics system that attempts to correct any issues it finds in the code. Often MO simply ignores the error and continues to install the mod as expected. There are circumstances where Mod Organizer will halt an installation, if the error is too big. During a FOMOD installation in Mod Organizer, the message pane at the bottom of the window will have valuable information, which can be used to help narrow down the issue.
Other Managers handle errors completely different. For example, when an error in the code is found some managers may completely halt the installation and display an error message in its information box. The hope is the manager's message is coded well enough to be helpful in resolving the error.
The info.xml script contains information about the mod being installed such as its name, version, categories, web link, and description. For Mod Organizer this script is used, but MO isn't reliant upon it since MO can gleam most of this information from Nexus via API. However, other managers may use this script to its fullest extent by displaying all the information it contains to the user. Info.xml should always be present with meaningful information within it. Setting up this script is explained later in this Guide.
Building the Structure
There are a few basics that must be in place before scripting begins:
- Creating XML Files
- Folder Structure
The folder structure is something that should be considered before writing any scripts. If it's changed after the scripts are written, it causes lot of necessary editing of the scripts to update folder names. Though FOMODs do not require any specific folder structure, it's recommended to use something sensible and simple. A format from Wrye Bash called, Bash Installer (BAIN), is perfect for this. It's both organized and easy to understand. As such, it's the folder structure recommend by this Guide. More information can be found on the BAIN structure on the Wrye Bash General Readme.
XML Files
The first folder that is always required is the fomod folder. This folder is not case sensitive, though authors format in multiple ways. Two files must be created within the fomod folder; info.xml and ModuleConfig.xml.
- From within the mod's root folder, click the [New Folder] button on the ribbon bar. Alternatively, right-click in the window pane, hover over "New", and select [Folder]. Name this new folder:
fomod
. - Open the new fomod folder.
- Right-click in the window pane, hover over "New", and select [Text Document].
- Delete the entire name, including the extension, and name it:
info.xml
. If a message box appears, click [Yes] to change the file extension. - Repeat steps 3 and 4, but this time name the file:
ModuleConfig.xml
- NOTE:For steps 3 through 5 to work properly, Windows file extensions must be enabled. If necessary, please do so by following this guide.
Folder Structure
Now that the files are created, it's time to create the remainder of the folder structure. For this Guide, our mod will have:
- required files that must be installed, regardless of options chosen by the user
- two required choices for two plugin versions
- two optional choices that provide three install options
Folders need to be created for all of the above following the BAIN format. To do this:
- For each new folder, click the [New Folder] button on the ribbon bar. Alternatively, right-click in the window pane, hover over "New", and select [Folder].
- Name the first new folder:
000 Required - Core Files
- Repeat, naming the folders as follows:
100 Required - PluginVersion01
100 Required - PluginVersion02
200 Optional - Addon01
200 Optional - Addon01 - Addon02 Compatible
210 Optional - Addon02
BAIN Overview
Those familiar with the BAIN schema may skip ahead as this is a basic introduction.
BAIN Numbering Schema
Lets review the BAIN folder structure above, which is all in the numbering. With BAIN, the numbers correspond to specific option "groups". It's recommended to always use a 3-digit schema, as it allows for greater flexibility and expansion as mods develop. The schema remains the same, so once it's understood and if set up correctly, any user should be abled to install the mod manually by following BAIN.
The first number is always 000, which is used to signify files that are always installed with the mod. Anytime a folder starts with 000, a user should automatically know to install it first. The next "group" would be numbered 100. Note that both folders in the example start with 100! In the BAIN schema, when multiple options exist for something like a plugin but the user should only install one of them, they are given the same number. In this example, since only one of the plugins should be installed, not both, they both start with 100.
The next "group" starts with 200. Note that there is the same setup as explained above for Addon01; however, Addon02 has the second digit increased. In the BAIN schema, advancing the second digit keeps those folders within the larger 200 "group", while signifying it being a separate folder that can be installed within the larger group. In the example, only one of the 200 folders should be installed, but a 201 or a 210 folder can be installed as well.
That is BAIN just a quick review of the basics with BAIN. Adding more folders is as simple as continuing the BAIN schema.
BAIN Folders
The next thing to know about BAIN is that each folder only contains game files. These means the only files and folders within the root BAIN folders are game-specific files. Do not put any sub-folder structures within these root folders! To be clear...
Don't do this! Do this! - Mod Folder
- 100 FolderName
- 110 Option01
- 111 Option01 Color01
- 111 Option01 Color02
- 120 Option02
- 110 Option01
- 100 FolderName
This is not BAIN!
- Mod Folder
- 100 FolderName
- 110 Option01
- 111 Option01 Color01
- 111 Option01 Color02
- 120 Option02
Everything is a root folder in BAIN.
- Mod Folder
The rest is simply using a naming schema that is organized and easy to understand. The example shows the use of a user-readable schema that notifies the user if the folder is required or optional. This is followed by a recognizable name that usually corresponds to the name of what the folder contains (e.g., 200 Optional - NoRunning).
The folder structure should resemble the one in the image above. If not, correct any mistakes before continuing. The setup stage is now completed. Populate the created folders with the correct files representing the corresponding options. The remainder of this guide will focus on the XML scripting for the two XML files.
XML Scripting - The Basics
Those familiar with XML scripting may skip ahead as this is a basic introduction.
Scripting in XML is very similar to HTML. XML consists of elements, commonly called "tags", which must be opened and closed. Within select opening tags, there are various attributes that can be defined within them, just like HTML. The basic XML code looks like the following:
<installStep name="Select Option(s)">
<optionalFileGroups>
<group name="Install Options" type="SelectExactlyOne">...</group>
</optionalFileGroups>
</installStep>
XML structure consists of a "root element", elements, and child elements; each may or may not have attributes with defined values within them. In the example above,
<installStep name="Select Option(s)">
is the root element with a "name" attribute defined as "Select Option(s)"<optionalFileGroups>
is an element<group name="Install Options" type="SelectExactlyOne">
is a child element with two attributes within it
When scripting XML, every tag is a set of two tags; an opening tag and a close tag. Opening tags are defined by enclosing the tags name within brackets; <textHere>
. Closing tags are defined by the addition of a forward slash ( / ), in front of the tag's name; </textHere>
. This can be seen in the example above. All opened elements were also closed in the order of which they were opened. This order of opening and closing is important in XML and is called, "nesting". All XML tags must be closed in the order they were opened. Some tags can be even be opened and closed within the the same element. To do this, add a forward slash before the closing bracket. In FOMODs, this is seen used with the "image" element; <image path="Fomod\fomodImage.png" />
.
Before moving on, another thing to note is the indention of each child element from its parent. In the example above, each child is indented from the parent. This is not necessary but is basic practice to help humans visualize the code. It also helps to keep track of sections of code when the scripting starts getting more complex. If using NotePad++, code can be organized by indentation using the [Tab] key.
XML Comments
Comments in any scripting are used many things such as descriptions explaining what a section of code does, instructions for others to follow who may come behind the author to edit, and markers to help separate the code into sections for complex or large FOMODs. They will also serve as reminders for authors who may return for edits after a long period of time has past and some familiarity with their own work is rusty (this happens often).
Pro Tip:
Use comments to hide code when making or testing changes. For example, if you have a simple option that installs only one file when selected that is being converted into a complex option with conditional statements, then it's best to hide the known 'good' code within comment tags until testing is complete. If anything happens that requires the code to be reverted, it's as simple as un-commenting the working code.
Outlined below are a few best practices for when and where to leave comments within FOMOD scripts:
- Leave descriptive comments where options or complex code, like conditions, need to be explained. Conditions are explained in the advanced section of this Guide.
- Descriptive comments can also be used for information within the files, such as a changelog for when multiple authors are collaborating.
- For complex FOMODs, leave markers in the code using comments to help sectionalize the code; making it easier to read and find different sections.
Comments in XML are the same as they are in HTML:
<!-- Text goes here -->
Some authors like to create a theme for their comments and markers so that they stand out among the code. An example is provided below which shows the use of the "=" symbol as a top and bottom border for the comment. All text is within the boundaries of the borders. This also shows the use of a comment section used for a changelog:
<!--
=================================================================================
Step SkyrimSE Guide FOMOD
Version: 1.0
Created and Maintained by: The STEP Team
Changelog:
November 23rd, 2015 - TechAngle85
Fomod written and released as v1.0 for Step v2.2.9 release.
=================================================================================
-->
XML CDATA
In XML scripting, output text will be parsed ignoring any line breaks by default. Therefore, text blocks (paragraphs) are ignored and displayed as one continuous block. To prevent this from happening, CDATA (character data) tags are placed to encapsulate text blocks. Doing so tells the parser to honor all characters within these tags, thus honoring line breaks spacing, etc. These are most often used for description elements.
No CDATA | CDATA |
---|---|
<Description>
My first line with some some information.
My second line with something clever:
- My list item
- My list item
</Description> |
<Description>
<![CDATA[My first line with some some information.
My second line with something clever:
- My list item
- My list item]]>
</Description> |
Parsed and displayed as: | |
My first line with some some information.My second line with something clever:- My list item- |
My first line with some some information.
|
NOTE
Most mod managers will honor the formatting without CDATA being present due to their own, internal programming. Regardless of this fact, it is a coding best practice to use CDATA for all text blocks within XML.
FOMOD Scripting
Their are two script files that comprises a FOMOD, info.xml and moduleConfig.xml. These and advanced scripting topics are handled on their own subpages. Please navigate to their respective pages to learn more about each topic.
info.xml
As explained above within Differences Between Mod Managers, the "info.xml" file contains valuable information that is typically displayed to the user such as the mod name, author, version, and more.
moduleConfig.xml
The moduleConfig.xml file is where all the magic happens. It houses the code used by mod managers to configure and display the GUI to the user. This Guide intends to cover all of the scripting available, and FOMODs can be fairly complex; however, not all situations require complex configurations. As such this reference will cover the basics and the more advanced elements within the "Advanced Scripting" reference.
Advanced Scripting
DescriptionHere
Troubleshooting
Tags are case sensitive! It's important to know that XML tags are case sensitive.
NOTES
Nothing as of yet...