Jump to content

Documentation: Modular mods system


llunak

Recommended Posts

This documentation describes how the support for creating mods in a modular way, instead of the old technique of overwriting game files.

For a tutorial and examples (which should be simpler to understand), see http://www.goldhawkinteractive.com/forums/showthread.php/11638-Modular-mods-system-tutorial-and-examples


The information below applies to X:CE 0.34 (and later).

General concepts

- All subdirectories of assets/mods/ are treated as mods. Each mod directory acts as that mod's assets/ subdirectory (so a mod called "foo" would provide assets/aircombatimages/paused.png as assets/mods/foo/aircombatimages/paused.png).

- Mods can be installed and deleted using the 'Modding Tools' support in the launcher (the combobox is currently useful only for selecting which mod to delete, the UI has not been updated yet).

- A mod file for installation is a .zip file with no toplevel directory (i.e. the contents should be e.g. xenopedia.xml, not mymodname/xenopedia.xml). Each mod file must include modinfo.xml (currently empty is enough).

- When the game wants to load an asset, it will merge it from all mods (if they provide/change the asset) and the stock game. Mods will overwrite what the game provides, higher priority mods overwrite lower priority mods (currently mod priority is in their alphabetical order, later in alphabet is higher priority).

- There are several types of resources:

* Binary files, such as images (currently only images work). These obviously cannot be merged. The asset will be used from the mod with the highest priority that provides the asset.

* Excel spreadsheet XML files, such as xenopedia.xml. These always use the first column as the identifier of the whole item. It is not necessary to copy the entire file into a mod, XML spreadsheet from a mod will be merged with data from game's file (and files from mods with lower priority), as described below.

* "Normal" XML files, such as gameconfig.xml . It is not necessary to copy the entire file into a mod, XML file from a mod will be merged with data from game's file (and files from mods with lower priority), as described below.

* Lua scripts. These currently work the same way as binary files, with the Lua script from the mod with the highest priority being used (limited merging between mods is planned). If a script needs to refer to another script, it should be done in the usual "scripts/script.lua" way, regardless of the mod in which the script is located. Note that for technical reasons lua scripts are modified and cached (currently in assets/mods/internal), (un)installing them using the game loader and editing them manually before the game launch will update cached versions, but e.g. manual removal of a mod instead of using the game loader may not work properly.

Merging of XML spreadsheets

First row is header, it must match.

First column is identifier of each item (i.e. row).

For each row from a merged XML spreadsheet:

- if the item doesn't exist yet, it is appended

- if the item already existed

- if the item has all columns except for identifier empty, the item is removed (even if it previously existed)

- if the item has all columns non-empty, the item is replaced

- if the item has some columns empty, the item is updated - empty columns will keep previous values

- a column may contain one or more of the following commands, the value is then split by these commands

(whitespace before and after is ignored) and each command is executed:

- MODMERGEAPPEND - it will cause the value to have the prefixed text appended (this is
meant e.g. for "When finished" column of researches.xml)
- MODMERGEREPLACE - it will find text to be replaced by the following MODMERGEWITH
- MODMERGEWITH - text found by MODMERGEREPLACE (one occurence) will be replaced by given text
- MODMERGEALLWITH - like MODMERGEWITH, but will replace all occurences of text found by MODMERGEREPLACE
- for example, "MODMERGEREPLACE: foo MODMERGEWITH: bar MODMERGEAPPEND: huh" will replace one "foo" in text with "bar" and then append "huh"

Notes:

- alien missions (AM_*.xml files) allow appending /<ticker> to the first column in order to have unique keys.

Merging of XML files

- if an element has a special attribute MODMERGEATTRIBUTE, this attribute specifies the name of attribute that will be used for matching, i.e. elements match if their names match and values for the given attribute match (this is for merging e.g. <Weapon name="weapon"...> elements in weapons_gc.xml), if the attribute does not exist, two elements match if their names match

- if an element has a special attribute MODMERGEATTRIBUTESET, when updating element's attributes while merging, this is the new value for the attribute specified by MODMERGEATTRIBUTE (which cannot have a new value specified the usual way, because that would prevent matching)

- if an element has a special attribute MODMERGEINDEX, this attribute specifies the index (starting from 1) of element that will be matched, i.e. MODMERGEINDEX-th element will be the matching element (this is for merging e.g. <tilemap> .xml files under assets/maps, which have a given grid, using it for anything that doesn't have exact index positions is most certainly wrong).

- if an element has special attributes MODMERGECHILD and MODMERGECHILDCONTENT, MODMERGECHILD specifies the name of a child XML element whose content must match MODMERGECHILDCONTENT, as an additional condition for matching (this for matching e.g. <city><name>London</name>...</city>)

- if an element has a special attribute MODMERGECONTENT (its value does not matter), then the content of the element itself will be used for matching (this is for matching e.g. <DeletedMap>alienbase_medium_1</DeletedMap>)

- if an element has a special attribute MODMERGE, this attribute specifies how the element will be merged with a possibly already existing matching element

- if the value is "insert", if there is no matching element, insert the element, it is an error if a matching element already exists
- if the value is "replace", the already existing matching element is replaced by this element (including all its children), it is an error if there's no or more than one element to replace
- if the value is "replaceifexists", an already existing matching element is replaced by this element (including all its children) if it exists, otherwise nothing happens, it is an error if there are more than one elements to replace
- if the value is "insertreplace", use "insert" if there is no matching element, otherwise use "replace"
- if the value is "delete", the already existing matching element is deleted if it exists, it is an error if there are more than one element to delete
- if the value is "deleteall", all already existing matching elements are deleted, if they exist
- if the value is "update", it is an error if there are no or more than one matching elements, otherwise update possible attribute values and (direct) content, descent one level down and repeat for all children
- if the value is "updateifexists", it is an error if there is more than one matching element, otherwise nothing happens if there is no matching element, otherwise update possible attribute values and (direct) content, descent one level down and repeat for all children
- if the value is "updateall", use "update" for all matching elements

- if an element has no MODMERGE attribute

- if the file is inside the maps/ or tiles/ folders, then with the exception of mapinfo.xml files the file gets automatic MODMERGE="replace"
- if a matching element doesn't exist yet, it is appended in the right place including all its child elements
- if an element has no children elements
- if there's already exactly one matching element, update attribute values and content (this is mainly for simpler modding of files like gameconfig.xml)
- if there are already more matching elements, that is an error
- (the no-element-yet case is handled above)
- if an element has children elements but no attributes besides the internal MODMERGE* attributes or XML internal xmlns:* attributes (in this case an already existing element can match even if it has attributes, this allows for easy updating of config elements that have attributes, such as in moraleconfig_gc.xml)
- if there's already exactly one matching element, descend one level down and repeat for all children
- if there are already more matching elements, that is an error
- (the no-element-yet case is handled above)
- otherwise it is an error (the element has both children and attributes and there already exists an element with the same name - in this case it's not easy to say if the element should be merged (which would be suitable for settings) or added or replaced (either of which could be suitable e.g. for <Weapon> elements in weapons_gc.xml)

Testing And Finding Errors

Any errors encountered will be logged in the game's log file. If Xenonauts.exe is launched with -modinfo, there will be additional information logged about the loading and merging of resources. The log file is located in Goldhawk Interactive/Xenonauts folder inside user's application data folder (exact location depends on Windows version). Older game versions use PlayFirst/Xenonauts folder.

Examples

Two testing example mods : [ATTACH]4919[/ATTACH] [ATTACH]4920[/ATTACH] . See tutorials for more examples.

mod1.zip

mod2.zip

mod1.zip

mod2.zip

Edited by llunak
Link to comment
Share on other sites

The game will print any errors to game's standard output (text console). If Xenonauts.exe is launched with -modinfo, there will be additional information printed.

Where do I find this information? I've run Xenonauts through the console with -modinfo but I don't know where to find the output.

Link to comment
Share on other sites

Where do I find this information? I've run Xenonauts through the console with -modinfo but I don't know where to find the output.

In the bit bucket apparently, at least quick google search suggests that graphical Windows applications just silently discard it (I'm on Linux + Wine, so I didn't know). I'll change it for the next version to dump it into some log file.

Link to comment
Share on other sites

Any chance you could indicate what you'd need to do in weapons_gc to add in an entirely new weapon.

My reading of the instructions above implies to me it should just be possible to include full weapon entries in weapon_gc and that's it. I.e.:

- if an element has no MODMERGE attribute

* if a matching element doesn't exist yet, it is appended in the right place including all its child elements

However, I keep getting CTD every time I load GC with the said weapons equipped (while it works fine if I add them in directly). Have I misunderstood, or is this a bug?

Link to comment
Share on other sites

Further to the above: I've just checked the mod upload log (the full -modinfo version) and there's no reference to trying to load the weapons_gc file at all. So either it's just not working, or I'm doing something thoroughly wrong.

EDIT:

For reference, this is the contents of my modded weapon_gc file:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Weapons> <Weapon name="weapon.explosive.BreachingCharge" bulletType="explosiveCharge" emptySound="Empty Click 1">	<props range="20" hands="1" recoil="0" weight="8" isHeavy="0" clipSize="1" reloadAPCost="0" reactionModifier="0" disableDamageScaling="1" throwingRangeModifier="-20.0"/>	<SingleShot delay="0.85" suppressionValue="0" suppressionRadius="0.0">	  <Set1 ap="60" accuracy="30" />	</SingleShot>	<BurstFire/>	<GUIImage name="gui/weapons/HBP_BreachingCharge.png"/>	<GroundImage name="grounditemimages/c4charge.png"/>	<Ammos>		<Ammo name="ammo.none" type="incendiary" damage="1500" stunDamage="0" mitigation="0" isOverdamage="1">			<Projectile spectre="projectiles/grenades/grenade_c4" speed="1000" />			<Impact spectre="particles/explosion/explosion" radius="1.0" sound="Vehicle Weapon Rocket Explode" fireChance="0" smokeChance="0" gasType="GrenadeFragSmoke" />		</Ammo>	</Ammos></Weapon> <Weapon name="weapon.explosive.PlasmaBreachingCharge" bulletType="explosiveCharge" emptySound="Empty Click 1">	<props range="20" hands="1" recoil="0" weight="2" isHeavy="0" clipSize="1" reloadAPCost="0" reactionModifier="0" disableDamageScaling="1" throwingRangeModifier="-20.0"/>	<SingleShot delay="0.85" suppressionValue="0" suppressionRadius="0.0">	  <Set1 ap="60" accuracy="30" />	</SingleShot>	<BurstFire/>	<GUIImage name="gui/weapons/HBP_PlasmaBreachingCharge.png"/>	<GroundImage name="grounditemimages/c4charge.png"/>	<Ammos>		<Ammo name="ammo.none" type="incendiary" damage="1500" stunDamage="0" mitigation="0" isOverdamage="1">			<Projectile spectre="projectiles/grenades/grenade_plasmacharge" speed="1000" />			<Impact spectre="particles/plasmaexplosion/plasmaexplosion" radius="1.0" sound="Vehicle Weapon Rocket Explode" fireChance="0" smokeChance="0" gasType="GrenadeFragSmoke" />		</Ammo>	</Ammos></Weapon></Weapons>
Edited by kabill
Link to comment
Share on other sites

Any chance you could indicate what you'd need to do in weapons_gc to add in an entirely new weapon.

My reading of the instructions above implies to me it should just be possible to include full weapon entries in weapon_gc and that's it. I.e.:

- if an element has no MODMERGE attribute

* if a matching element doesn't exist yet, it is appended in the right place including all its child elements

However, I keep getting CTD every time I load GC with the said weapons equipped (while it works fine if I add them in directly). Have I misunderstood, or is this a bug?

"

- if an element has a special attribute MODMERGEATTRIBUTE, this attribute specifies the name of attribute that will be used for matching, i.e. elements match if their names match and values for the given attribute match (this is for merging e.g. <Weapon name="weapon"...> elements in weapons_gc.xml), if the attribute does not exist, two elements match if their names match

"

Without MODMERGEATTRIBUTE, elements match only on tag name -> your "new" entries match every single <Weapon> there is -> you need MODMERGE="insert".

Link to comment
Share on other sites

  • 2 weeks later...

Question:

In loadouts.xml, all of the elements have children but no inherent attributes (if I'm understanding those terms correctly). An example for clarity's sake:

<Loadout>	<Name>SoldierRoles.Rifleman</Name>	<Image>uitextures/roles/rifleman</Image>	<Armour>armour.basic</Armour>	<RightHand>weapon.rifle</RightHand>	<BeltItem>		<Name>ammo.ballistic.rifle</Name>		<Point>0,0</Point>	</BeltItem></Loadout>

Firstly, then, can I check I'm right therefore in thinking that this comes under the final category for dealing with .xml merging (i.e. "- if an element has no MODMERGE attribute...").

Secondly, if so, am I right in thinking also that there's therefore no way to currently merge these files using the modular mod system, as there are multiple <loadout></loadout> entries. This seems to be the case empirically (the error log says it won't update because there's multiple elements, but I can't use MODMERGEATTRIBUTE to specify anything to identify the elements individually), but I wanted to check I'm not overlooking something.

EDIT: Apparently I can brute-force it by setting the highest level element to "replace". So it's possible to mod it, just (possibly) not merge it with anything else.

Edited by kabill
Link to comment
Share on other sites

  • 4 weeks later...

Quick question; is the xcesettings mod an exception to the usual load order of mods? Because it's almost at the end of the alphabet, it should load in preference to other mods (which would be problematic, actually, since you probably want to use xcesettings as a base to mod on top of) but in practice that doesn't seem to be the case. Is that intentional, or a bug?

Link to comment
Share on other sites

  • 2 weeks later...

I have been having some big time issues with XCE .28 (modular mods loader). I read that XCE is the last mod to load because the loader uses alphabetical order at this time. So, my mod under the label of "Xeryx" (after XCE) , is still getting over ridden in many files, by the XCE mod files.

I have modularized quite a few mods, and they all come before XCE, but do not contain any base directory file, mostly graphics and such. They of course are unaffected and add in great.

IE. In my mod I changed the ammo capacity in both weapons files, but yet when I start the game there are mismatches to the ammo of the gun, and even if it says the base number of round is say 50 when I load the gun with a clip, only 30 rounds will load (the values used in the XCE mod). My mod previously worked great on my first runthrough because I started with XCE game files, and used them in the XCE directory.

The only way I was able to get this to stop, was to overwrite the XCE files with mine.

Can you give me some insight to what might be occurring here?

Edited by Xeryx
Link to comment
Share on other sites

I have been having some big time issues with XCE .28 (modular mods loader). I read that XCE is the last mod to load because the loader uses alphabetical order at this time. So, my mod under the label of "Xeryx" (after XCE) , is still getting over ridden in many files, by the XCE mod files.

No, "xce" and "xcesettings" are currently special and have the lowest priority.

Can you give me some insight to what might be occurring here?

I'd expect your mod is buggy and some of its data is ignored. See the testing section in the documentation.

Link to comment
Share on other sites

No, "xce" and "xcesettings" are currently special and have the lowest priority.

I'd expect your mod is buggy and some of its data is ignored. See the testing section in the documentation.

So is it then done by alphabetical order (for the other mods)? Is there plans to implement a manual control to change the order of mods? That Skyrim and Mass effect 2 have?

There is always a chance I have bugs in the mod, just like there are bugs in the game. I am mostly changing values with notepad ++ or Excel there shouldn't be any bugs. Especially when you consider that my changes are being seen in the game, when I use the XCE folder for my files ( the base files of the game ).

Edited by Xeryx
Link to comment
Share on other sites

I'm not quite sure how to do something.

<Row ss:AutoFitHeight="0" ss:Height="51">   <Cell ss:StyleID="s77"><Data ss:Type="String">Researches.StunWeapons</Data></Cell>   <Cell ss:StyleID="s72"><Data ss:Type="Number">120</Data></Cell>   <Cell ss:StyleID="s73"><Data ss:Type="String">Weaponary</Data></Cell>   <Cell ss:StyleID="s76"><Data ss:Type="String">Researches.AlienBiology</Data></Cell>   <Cell ss:StyleID="s76"/>   <Cell ss:StyleID="s76"><Data ss:Type="String">UnlockKnowledge( "Researches.StunWeapons" );UnlockItem("weapon.grenade.shockbaton");UnlockItem("weapon.grenade.stun");UnlockItem("weapon.rocket.stun");</Data></Cell>   <Cell ss:StyleID="s76"><Data ss:Type="String">Researches.StunWeapons</Data></Cell>  </Row>

This particular section in Researches.xml. I need to add:

;UnlockItem("weapon.dartgun")

To the end of unlock line, but I'm not sure how I would do that in a separate mod.

I have this mod already made and in my game, I know it works. I'm trying to figure out how to pull it out and make it it's own mod.

Edited by endersblade
Link to comment
Share on other sites

  • 2 weeks later...

Testing

Any errors encountered will be logged in the game's log file. If Xenonauts.exe is launched with -modinfo, there will be additional information logged about the loading and merging of resources. The log file is located in user's Application Data/PlayFirst/Xenonauts folder (this needs 0.25 hotfix, plain 0.25 does not work).

I can't figure out where to find it. I'm running on windows 7 64bit and I dont know where Application Data or PlayFirst folders are. I'm new to this, sorry for noob questions. : C

Link to comment
Share on other sites

I guess it's the appdata folder. At leadt I got PlayFirst\Xenonauts folders there. Username would be the one used on your machine.

Example:

C:\Users\yourusername\AppData\Roaming\PlayFirst\Xenonauts (just need to use your username which obviously I don't know)

That's how it's in my Win7 64 bit.

Link to comment
Share on other sites

I guess it's the appdata folder. At leadt I got PlayFirst\Xenonauts folders there. Username would be the one used on your machine.

Example:

C:\Users\yourusername\AppData\Roaming\PlayFirst\Xenonauts (just need to use your username which obviously I don't know)

That's how it's in my Win7 64 bit.

Yes! Found it! :D

Thank you.

Link to comment
Share on other sites

  • 4 months later...

hey, just have noticed the logfile on my Win 7 x32 seems to be capped by ~100kb size. Every restart gives the logfile of this size, and it ends abruptly, like this:

Tue Feb 03 20:06:27 2015: MOD INFO: Updating item Items.SebillianLeaderCorpse .Tue Feb 03 20:06:27 2015: MOD INFO: Updating item Items.SebillianNonCombatant .em ManTech.ParticleBeam .

any ideas how to overcome this limitation?

Link to comment
Share on other sites

  • 1 month later...

sorry, may you give us more examples ? such "how to add new plain" ? cause i have made the small modification, mod wih buyeble plain is active, but i cant to purchase it and log file says nothing. I`v sitting and crying ))) thx

Link to comment
Share on other sites

sorry, may you give us more examples ? such "how to add new plain" ? cause i have made the small modification, mod wih buyeble plain is active, but i cant to purchase it and log file says nothing. I`v sitting and crying ))) thx

As i know, you cant make buyable planes.. its hardcoded.. so its not your fault..

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...