Formats and Examples

Goals/Background of MSON

I started with JSON but quickly grew tired of the tedious syntax. So I relaxed the rules a bit to make it easier for human creation/editing. Later I realized that the operation of modifying existing objects (versus creating objects from scratch, for which JSON is purposed) would be facilitated by some additional features not present in JSON; namely the ability to merge specified values into an existing object or array.

So the goal of MSON is to make it easy for humans to selectively modify existing objects (merging), as well as create new objects from scratch.

After establishing this new MSON format, I became aware of the HOCON format which is remarkably similar in functionality and shares most of the same goals. It is also more complex to parse/process HOCON, so I'm sticking with what I've created and calling it MSON (pronounced /ˈɛmsən/ EM-sən), for Modding Support Object Notation.

Differences from JSON

To explain the MSON format, let's assume the definition of JSON and then make the following changes:

  • Quotes around keys and values are optional (only required if string must begin or end with whitespace).
  • C-Style comments added (// and /* */).
  • Comma separator between fields is optional with newline sufficing as a separator.
  • '@' before a quoted string (no whitespace between) denotes a verbatim string (as in C# verbatim string). I.e. no escape sequences interpreted except for \" for internal quotes.
  • Import/Include of other MSON file into current file with the '#' token.
  • Allow defining a new object/array by starting with the values of an existing object/array and then overriding.

Examples of MSON files for Wasteland 2

Note: The examples below, and more, are included in a Mods zip file you can download to see it working and use as example templates. Unzip it into the installed game's data folder and run the game to see the changes. Walk over to the supply vendor in Ranger Citadel to see changes in appearance made to her clothing and skin-color.

The MSON files for Wasteland 2 are organized in a folder hierarchy. Non-Spawner classes are stored in subfolders based on their custom (non-built-in) class hierarchy. For example the file for a ranged weapon is stored here:
\ItemTemplate\ItemTemplate_Equipment\ItemTemplate_Weapon\ItemTemplate_WeaponRanged\

NPCTemplates are in:
\MobTemplate\NPCTemplate\

The others (besides Spawner) derive from ScriptableObject which is not included in the folder hierarchy (since it is a built-in class):
\Dropset\
\VendorSet\
\JournalEntryTemplate\
\StatusEffect\

The Spawners, which only exist inside scene files are stored by scene hierarchy first, then under a "Spawner" folder. Example:
\Arizona\AZ00_Ranger_Citadel\Spawner\
\LosAngeles\ CA00_SantaFeSprings\Spawner\

Mod File Names

Any public field or property of the asset is modifiable by specifying a value for it in its corresponding .mson file.  For non-Spawner classes, the mod-file's base name is same as the asset file's base name.  You can download lists of the names of the assets in CSV format on the Downloads Page

For Spawners, the mod-file base-name is the name of the gameobject in the scene plus its GUID (delimited by underscore)--the GUID is needed because some scenes contain different spawners with the same game object name (e.g. "dog", or "honey badger").  You can download the spawner names and locations in this SpawnerNames CSV zip file, which is also on the Downloads Page.

Spawner Example

An example of a Spawner mod file (included in the downloadable Mod examples) is "Supply Officer Spawner_43438dd5-943a-4b9c-a7d0-6f10d4a31cef.mson" in the folder "\Arizona\AZ00_Ranger_Citadel\Spawner\".  It contains the following:

{
	bOverrideDisplayName: true,
	overrideDisplayName: "Cpl. Sally Fields{F}",
	bOverrideSkinColor: true,
	overrideSkinColor: Mutant, 

	bOverrideDropSet : true
	overrideDropSet : FooDrops

	bOverrideEquipment : true

	/* The # include lines below demonstrate different ways to
	* specify an external text-file from which to import data.
	* All but the last one are commented out.
	* In these examples:  
	*    The local file URIs all indicate the same file. 
	*    The http URL indicates a copy of that file on an inXile server.
	*/

	//** Load from internet by http
	//#"http://wasteland2.inxile-entertainment.com/static/share/SupplyOfficerEquipment.mson"

	//** Load from local file system using verbatim string format.
	//** A verbatim string is a string prefixed with @
	//#@" D:\Program Files\Steam\steamapps\common\Wasteland 2\Build\WL2_Data\Mods\Import\Arizona\AZ00_Ranger_Citadel\Spawner\SupplyOfficerEquipment.mson"

	//** Below starts at default base folder, which is the Mods/Import/ folder.
	//#@"Arizona\AZ00_Ranger_Citadel\Spawner\SupplyOfficerEquipment.mson"

	//** Below starts at the root of the local file system's current storage device.
	//#@"\Program Files\Steam\steamapps\common\Wasteland 2\Build\WL2_Data \Mods\Import\Arizona\AZ00_Ranger_Citadel\Spawner\SupplyOfficerEquipment.mson"

	//** Below is relative to location of currently parsed file's folder. The @ as first character of the string signals to use current file's folder as base.
	#@"@SupplyOfficerEquipment.mson"
}

There are a few notable features in this example.

  • The format is based on JSON but is less strict—commas and quotes are optional.
  • Comments are allowed (both C-Style line comments // and multi-line comments /* */).
  • The # syntax is an added feature which says to continue loading data for the current object from the specified external source.

If the value (the part after the ':') is not a basic type (string, int, float, bool, or "null"), then the reader-code asks the game to interpret it and return an object to use. So the "FooDrops" value is sent to the DropSet class for interpretation, which (in this case) looks for the matching mson file "Mod/Imports/DropSet/FooDrops.mson" and asks the MSON reader to create a DropSet object from that. This means the reader can operate recursively to create objects from other .mson files.

In the case of an ItemTemplate field, the ItemTemplate class asks the ItemManager for a value (which looks first in its stored list of assets before trying to find a matching MSON file to create a new template from).

Here is what is in the FooDrops.mson file:

{
	drops : [
		{
			dropItems : [
				{ item : Usable_AntiBiotics_1}
				{ item : Ammo_762mm_S, min : 50, max: 60}
				{ item : @"ItemTemplate_WeaponRanged\MyAssaultRifle_Tier7" }
			]
		}
	]
}

So this replaces the DropSet with a drop of 3 items: antibiotics, ammo and a new custom weapon defined in the MSON file "MyAssaultRifle_Tier7.mson". The parent folder of new items must be specified because that is how the code knows what subclass of item to create (in this case a ranged weapon). The MyAssaultRifle_Tier7.mson file contains the following:

AssaultRifle_Tier_6_2 : {
	atlas : icon
	spriteName : T_Shovel
	alwaysHits : true
	firingModeInfos : [
		{actionPointCost : 2,  ammoCost : 1, chanceToHitPenalty : 0}
		{actionPointCost : 4,  ammoCost : 2, chanceToHitPenalty : 0}
		{actionPointCost : 5,  ammoCost : 10, chanceToHitPenalty : 0}
	]
}

This file demonstrates another notable feature of the MSON format: the ability to initialize the values of the current object by copying another existing object (namely AssaultRifle_Tier_6_2, in this example). So the ItemManager creates a default ItemTemplate_WeaponRanged then passes it into the MSON reader, which sees the name before the opening brace and asks the game for that named object (which the ItemManager returns from its cache of pre-existing assets), then the reader copies its values (a shallow copy) into the new object, then it proceeds to override with the data in the remainder of the file. In this case, I've changed the Sprite Atlas and the Sprite, as well as making it always hit and changing the firing modes to make it more awesome. This feature makes it easy to create new items based on existing items with less typing (just specify the things you want to change).

The SupplyOfficerEquipment.mson contents below (which is referenced above) shows an example of specifying an array by selectively modifying just the elements you want to change (of the existing array). The first way that specifies all the elements is commented out, but retained in a comment to show the laborious way and what all the elements are.

SupplyOfficerEquipment.mson file:

{
/* This way creates a NEW list and specifies all 18 elements of the equipment array.
	overrideEquipment : [
		null // 0 =None,
		Kathy_Hair // 1=Hair,
		Default_Fem_Head // 2=Head,
		null // 3=Shoulders,
		Kathy_Torso // 4=Torso,
		null, // 5=Packs,
		Default_Fem_Legs, // 6=Legs,
		AssaultRifle_Tier_4_2, // 7=WeaponR,
		null, // 8=AmmoR_DEPRECATED,
		null, // 9=WeaponL,
		null, // 10=AmmoL_DEPRECATED, 
		null, // 11=Trinket1,
		null, // 12=Trinket2, 
		null, // 13=Trinket3,
		null, // 14=GasMask,
		null, // 15=RadSuit,
		null, // 16=UnderArmor,
		null, // 17=Canteen
	] 
*/
	// This way CLONES (using '&' token) the existing array and just modifies the elements we want to change.
	overrideEquipment :  & [
		1 : Kathy_Hair 		// 1 = Hair,
		4 : Kathy_Torso 		//  4 = Torso,
		null,				// 5=Packs
		Default_Fem_Legs	// 6 = legs
	] 
}


Next: Classes & Members

ESRBESRB