Jump to content

Modular mods system tutorial and examples


llunak

Recommended Posts

This is a series of examples of creating mods using the modular way introduced in X:CE 0.25.

The actual technical documentation of the modular mods system is at http://www.goldhawkinteractive.com/forums/showthread.php/11433-Documentation-Modular-mods-system . Refer to the relevant parts for exact details of a specific feature.

This thread intentionally does not allow comments. If something is unclear, use the documentation thread (both for consulting the details first and possibly asking afterwards).

Edited by llunak
Link to comment
Share on other sites

Mods are .zip files containing all the mod assets. A minimal mod requires file modinfo.xml at the toplevel of the archive:

<?xml version="1.0"?><ModInfo><Name>Empty example mod</Name><Version>0.1</Version></ModInfo>

A .zip file containing this file ([ATTACH]5069[/ATTACH]) can be installed using "Modding Tools" in the launcher (as of X:CE 0.26, the user interface of that part still requires changes).

Note: This mod does not do anything, other than being installed. It is however not completely useless. If you know how to mod files manually, you can add files to the mod's files under assets/mods/ instead of modifying game's files.

tutorial1.zip

tutorial1.zip

Edited by llunak
Link to comment
Share on other sites

Each mod has a structure matching that of the game's assets/ directory. When the game wants to load a binary file (such as an image or audio file), it searches all mods using the same location and if it finds a matching file, it will one that one instead of the game's file.

For example, the game's pointing cursor is located at assets/cursor/cursor.png . Placing a modified image as cursor/cursor.png to a mod will make the game use this modified image:

[ATTACH]5070[/ATTACH]

If there are several mods providing the same binary file, the one with the highest priority wins and its file is used. Currently , as of X:CE 0.26, priority is alphabetical, with mod names later in the alphabet having higher priority. This will be changed in future versions.

tutorial2.zip

tutorial2.zip

Link to comment
Share on other sites

Most UI strings displayed by the game are in the file assets/strings.xml . This file is an Excel XML spreadsheet, and it can be opened and modified using Microsoft Excel. Alternatively, it can be also opened and modified using for example LibreOffice Calc, or edited manually if one is careful enough.

The file contains two columns, first one is a key by which the game refers to UI strings, and the second column is the actual UI string the game will display. In order to modify or add new UI strings, a similar spreadsheet XML file needs to be created in the mod as strings.xml .

There is no conflict if more mods provide strings.xml but provide different UI strings (i.e. the first columns differ). If two or more mods provide the same UI string, the one with the highest priority wins.

For example, in order to change the main menu's "Load game" UI string to "Continue game", strings.xml should contain one row, with the first column being "LoadGame.MainMenu" and the second column "Continue game" :

[ATTACH]5071[/ATTACH]

tutorial3.png

tutorial3.zip

tutorial3.png

tutorial3.zip

tutorial3.png.d5398fa80b7715f14c2006e803

Edited by llunak
Link to comment
Share on other sites

If there is any problem with a mod, the game logs an error in its log file. If Xenonauts.exe is launched with -modinfo switch, the log file will contain also informative messages about how mod resources are used. This can be useful when testing a new mod or trying to find out why it does not work.

The log file is PlayFirst\Xenonauts\logfile.txt in the user's application data directory (the exact location varies, it's something like C:\Users\username\AppData\Roaming\PlayFirst\Xenonauts\logfile.txt ).

For example, launching a game with the tutorial2 mod above ("Mod that replaces an image") produces this information with -modinfo :

Thu Jul 24 21:21:19 2014: MOD INFO: Initializing mod list (highest priority last).Thu Jul 24 21:21:19 2014: MOD INFO: Adding mod directory: mods/tutorial2/Thu Jul 24 21:21:25 2014: MOD INFO: Using texture cursor/cursor from mod mods/tutorial2/ .
Link to comment
Share on other sites

Some of game's file are in the Excel spreadsheet XML format, which can be opened using spreadsheet applications like Microsoft Excel or LibreOffice Calc (but can be also edited manually if careful).

These files are normal spreadsheets. The first row is header, describing the information in each of the columns. First column is the key column that internally described the row (the game usually searches for information from each row using this column, for example information about manufacturing the Foxtrot is in manufactures.xml in the row "ManTech.MiG32"). The rest of the columns are various values about the item, format depends on each file.

When modding a spreadsheet XML file, a mod needs to include a matching spreadsheet XML file, with a matching header, and each row to be modified (or added). The easiest way to create these is to copy the original file and delete rows that are not needed. When the game merges in the mod's changes, it will match rows depending on the first column values and replace game's information with that one from the mod. Additionally, value in any column except for the first one can be left empty, in which case that value will not be updated, or if all columns except for the first one are empty, then the whole row will be deleted.

For example, changing Foxtrot's cost from $200k to $300k and removing Corsair's cost is done using a spreadsheet XML file that contains the header and two rows, first one containing only the first row and a new value for the "Cost" column, the second one containing only the first row.

[ATTACH]5902[/ATTACH]

tutorial4.png

tutorial4.zip

tutorial4.png

tutorial4.zip

tutorial4.png.e1893d7fba8853b1f2d83040c4

Edited by llunak
Link to comment
Share on other sites

Most of game's files that allow modding are XML files. Note that in order to understand changing them (and both this tutorial and the further modding documentation) it is a prerequisite to undertand basic XML concepts such as tags, elements, content, attributes. Find a good XML introduction/tutorial if needed.

Doing simple XML changes is done by a mod providing the same XML file, with only the parts of the XML structure that need changing. When the game merges in the changes, it update the information from the game's XML file with changes from the mod file.

For example, assets/gameconfig.xml contains element startingTime that sets the in-game date of the start. In order to change the starting year, it is necessary to include the tag again, its attributes that need changing, and all the parent tags. It is not necessary to include other XML elements, and other attributes of startingTime (their original values will be kept).

<?xml version="1.0"?><GameConfig> <startingTime year="1975"/></GameConfig>

NOTE: This works only for changing XML elements without children in XML files with simple structure. More complicated cases, like replacing larger XML elements including their children, or XML files that contain several XML elements of the same type (such as weapons_gc.xml, which has Weapon element per each weapon) need additional information for the game to do the merging properly. In case this information is not provided, the merging will fail and an error will be logged in the game's log file.

[ATTACH]5095[/ATTACH]

tutorial5.zip

tutorial5.zip

Link to comment
Share on other sites

Some XML files may need more complicated merging. When there are several XML elements with the same name (such as sounds.xml having multiple Sound elements, one per case when the game needs to play a sound), the game would not know reliably on its own how to merge them, as it would not be able to decide if the element provided by a mod is to be added to the list of elements, or if it's to update an existing one and which one.

In order to control this, the merging relies on several attributes that have names starting with MODMERGE. Refer to the documentation for their full explanation.

For example, the music to be played in geoscape is controlled by the following part of sounds.xml :

<?xml version="1.0"?><Sounds>... <Sound name="Geomusic" volume="0.7" repeattime="0-1" group="2" comment="BGM for the geoscape.">   <Wave>audio/music/Geoscape 1.ogg</Wave>   <Wave>audio/music/Geoscape 2.ogg</Wave>   <Wave>audio/music/Geoscape 3.ogg</Wave> </Sound>...</Sounds>

In order to change it so that the air combat music is played in geoscape, XML merging would need to be done that would result (internally) in the Sound element being this:

 <Sound name="Geomusic" volume="0.7" repeattime="0-1" group="2" comment="BGM for the geoscape.">   <Wave>audio/music/Air Combat 1.ogg</Wave> </Sound>

As said above, providing this in this exact form in the mod's sounds.xml file would cause an error, because the game wouldn't know whether to add it to use it to alter already existing data. Therefore, mod's sounds.xml file needs to look like this:

<?xml version="1.0"?><Sounds> <Sound name="Geomusic" MODMERGEATTRIBUTE="name">   <Wave MODMERGE="deleteall"></Wave>   <Wave MODMERGE="insert">audio/music/Air Combat 1.ogg</Wave> </Sound></Sounds>

The MODMERGE attribute says to merge this XML element with an already existing element that has the same value for the given attribute (i.e. name). The following MODMERGE attribute in the first Wave element is used to remove all the audio files from the game's sounds.xml for this sound. Finally, the last element is inserted in the place, adding the new audio.

[ATTACH]5096[/ATTACH]

Note: Another solution might be to replace the matching Sound element completely:

<?xml version="1.0"?><Sounds> <Sound MODMERGE="replace" name="Geomusic" volume="0.7" repeattime="0-1" group="2" comment="BGM for the geoscape.">   <Wave>audio/music/Air Combat 1.ogg</Wave> </Sound></Sounds>

However this is an inferior solution to the one presented above, because it again specifies information that is not to be changed, such as the volume. If the game (or a mod) changed those values, modding the sound this way would inadvertently reset the change.

tutorial6.zip

tutorial6.zip

Link to comment
Share on other sites

  • 4 weeks later...

When changing spreadsheet XML files, it can be sometimes useful to alter only part of an item. While the whole item can be replaced using the way described above, this could sometimes introduce unwanted changes. For example, when modding the soldier capacity of Shrike, its Xenopedia description should be updated too. But replacing the whole Xenopedia entry would mean replacing it with the full (modified) description, which could lead to some problems (such as when the original game file changes something, this change would be reverted by such a mod). For this reason, it is possible to change items in spreadsheet XML using MODMERGEAPPEND, MODMERGEREPLACE, MODMERGEWITH and MODMERGEALLWITH.

The following example renames the Shrike dropship to Trike, and adds a paragraph saying that it's a really nice transport. The two items for its Xenopedia are:

MODMERGEREPLACE: Shrike MODMERGEWITH: TrikeMODMERGEREPLACE: Shrike MODMERGEALLWITH: Trike MODMERGEAPPEND: And it is a really nice transport.

If an item contains any MODMERGE command, it is split by these and the commands are executed. MODMERGEREPLACE is used for replacing text, and must be followed by either MODMERGEWITH or MODMERGEALLWITH. When they are encountered, the text to be replaced (marked by MODMERGEREPLACE) is replaced with text after MODMERGEWITH or MODMERGEALLWITH (the sooner replaces just first occurence, the latter all of them). MODMERGEAPPEND is used to simply append some text.

[ATTACH]5328[/ATTACH]

tutorial7.zip

tutorial7.zip

Link to comment
Share on other sites

Some XML files use a format that does not allow using MODMERGEATTRIBUTE (as described above), because XML elements have no attributes that would identify them. Instead, they have child XML elements that can be used to identify them. An example is assets/cities.xml :

<Cities>... <City>   <Name>London</Name>   <Country>United Kingdom</Country>... </City>...

Here each city is identified by its Name XML element. In order to match such XML elements, there is a mechanism similar to MODMERGEATTRIBUTE that works on XML elements.

<Cities> <City MODMERGECHILD="Name" MODMERGECHILDCONTENT="London">   <Name>Tea City</Name>   <Country>Tea Country</Country> </City></Cities>

Here MODMERGECHILD specifies the name of the (direct) XML child element that will be searched for content specified by MODMERGECHILDCONTENT. In other words, this will match the London data specified above. The new data will be merged into it, renaming London and the country it's in to Tea City and Tea Country. Note that since there strings can be translated, they must be also added to strings.xml .

[ATTACH]5329[/ATTACH]

tutorial8.zip

tutorial8.zip

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...