Gears

ModSettings.xml Reference

The complete V2 schema for ModSettings.xml as the parser reads it — every element, every attribute, and what happens when something is wrong.

Use this page to look up any element or attribute of the V2 ModSettings.xml schema. Where the parser drops or ignores something, the page says so and gives the log line to search for. Every log line is prefixed [Gears] [XmlSettingsParserV2] unless stated otherwise.

New to Gears? Start with Getting Started instead.

A dropped setting is silent in the game

One bad setting does not stop the rest of the file from loading. The parser logs the problem, skips that element, and carries on. Nothing in the game tells you a setting went missing, so read the log when something does not appear. See Troubleshooting.

File location and root element

RuleDetail
Location<mod folder>\ModSettings.xml, beside ModInfo.xml. Gears tries no other path or name. It skips a mod without one and logs nothing.
Root<ModSettings version="2">.
versionRequired, and must be 2. A root with no version is a V1 file and is rejected, and so is any other value. Both log an error from [ModSettingsFromXml] naming the mod, and the whole file is skipped.
Malformed XMLThe whole file is skipped: Mod <Name> ModSettings Failed parsing <folder>: followed by the exception.
Wrong root name or no child elementsThe whole file is skipped with an error.
When it is readOnce, at game start (GameAwake), for every loaded mod in the game's load order.

A skipped file removes your players' saved values

When Gears skips the whole file and your mod creates no global settings from C#, the mod has no global settings that startup. Gears then removes the mod's section from each player's saved settings file, so every saved global value for your mod is lost and cannot be recovered. This keeps the saved file from growing with entries for settings that no longer load. Test your ModSettings.xml in the game before you release it.

Document structure

<ModSettings version="2">
	<Global>
		<Tab name="" displayKey="" tooltipKey="">
			<Category name="" displayKey="">
				<!-- Selector | Slider | Switch | Color | Binding -->
			</Category>
		</Tab>
	</Global>
	<World>
		<Category name="" displayKey="">
			<!-- Selector | Slider | Switch -->
		</Category>
	</World>
</ModSettings>

<Global> holds the player's settings and <World> holds one world's settings. Both are optional, and Gears reads only the first of each.

<Global> reads only its <Tab> children, and <World> reads only its <Category> children. Gears ignores anything else directly under them and logs nothing.

<Tab>, global only

AttributeRequiredNotes
nameyesIdentity within Global. Gears merges two tabs with the same name into one.
displayKeynoLocalization key for the tab label. An empty value falls back to name.
tooltipKeynoLocalization key for the hover text. Tab is the only element that still uses tooltipKey. Everywhere else it became <Description>.

A tab is not a setting, so it takes no <Caption>, <Description>, <Preview> or <RestartScope>. Gears reads only its <Category> children and drops a setting placed directly under a tab, without a log line. A tab with no categories still exists.

<Category>

Categories have the same shape under Global and World.

AttributeRequiredNotes
nameyesIdentity within its tab, for a global setting, or within World. See How duplicate names merge.
displayKeynoFalls back to name.

A category counts as a setting for display purposes, so it accepts <Caption>, <Description> and a single value-less <Preview><Image path=""/></Preview>. It does not accept tooltipKey or <RestartScope>. Gears tries every child element as a setting and drops unknown element names without a log line.

Setting elements

ElementGlobalWorldValue types
<Selector>yesyesint, float, string, any enum
<Slider>yesyesint, float only
<Switch>yesyesbool, string, any enum
<Color>yesnoalways a color; type is accepted and ignored
<Binding>yesnonone; a key binding has no value

These five are the only elements a <Category> accepts. Gears drops a Color or Binding under <World> without a log line, and drops any other element name the same way. When constructing a setting throws for any reason, Gears drops it with Failed to parse global <Element> '<name>': <message>, or world in place of global.

The rules below apply to every one of them. Each element's own subsection follows, and the child elements they take are described under Child elements.

Attributes every setting takes

AttributeRequiredNotes
nameyesIdentity within its category, and the key the player's saved value is stored under. See How duplicate names merge. Renaming a setting after release discards the saved value, so treat a released name as fixed; see Troubleshooting. A world setting's name must also be unique across every world category of the mod. Gears restores saved world values by name alone, into the first setting with that name. When two categories share a setting name, the first category's setting takes the value saved last, and the second one goes back to its default every time the world loads.
displayKeynoFalls back to name.
typeyes, except on Color and BindingSee Value types.
defaultValueyes, except on BindingSee defaultValue.

Value types

Gears trims type and matches it case-insensitively.

WriteMeaning
int, Int32, integer32-bit integer
float, Singlesingle-precision float. Accepts a % suffix, so 50% is stored as 0.5. This applies wherever a float is parsed: defaultValue, increment, minValue, maxValue, List entries and Image value.
stringtext
bool, booleantrue or false
Color, Color32resolves, but no Selector or Switch exists for it, so the setting is dropped. Use the <Color> element instead, which ignores type.
doubleresolves, but no Selector, Slider or Switch exists for it, so the setting is dropped
anything elsetreated as a type name and looked up in every loaded assembly, case-insensitively. Write the full name (MyMod.Difficulty), the assembly-qualified name (MyMod.Difficulty, MyMod), or the bare name (Difficulty). For an enum declared inside a class, separate the class from the enum with a plus sign (MyMod.PlayerController+Difficulty); a dot does not resolve. The type must be an enum or have a registered parser. See Use Custom Value Types.

Each of these failures drops the setting:

Log lineCause
<Element> '<name>' has no type.type is missing or whitespace
<Element> '<name>' has unknown type '<raw>'. Use one of int, float, string, bool, Color, or the name of an enum type such as 'MyMod.Difficulty, MyMod'.not an alias and not a resolvable type name
<Element> '<name>' uses type '<raw>', which is neither an enum nor a type with a registered parser.resolves to a real type Gears cannot read
Slider '<name>' has unsupported type '<type>'; sliders support int and float only.a Slider with anything but int or float
Setting '<name>' of type '<Type>' could not be created: <message>an enum or custom type with no setting implementation for that element

An enum Selector starts with every declared member as its allowed values, in declaration order, so it needs no <List>. An enum Switch takes the first two declared members as left and right unless <Buttons> says otherwise.

defaultValue

defaultValue is required on Selector, Slider, Switch and Color. It seeds three things at once: the setting's default value, its applied value and its selected value. The player's saved value, if there is one, replaces the last two after the file has loaded.

CaseResult
Missing or whitespaceSetting dropped: <Element> '<name>' has no defaultValue; defaultValue is required, skipping.
Present but unparseableSetting kept at default(T): 0, false, empty, or black. [GlobalModValueSetting] or [WorldModValueSetting] logs Setting '<name>': could not parse defaultValue '<raw>' as <Type> - <message>, then the same line twice more with value and selectedValue in place of defaultValue
Outside the List, the Incremental range or the Buttons valuesNot checked. The setting loads with the value you gave.

<Selector>

One value at a time, with arrows on either side to step through the allowed values. Global and world.

Set the allowed values one of three ways:

  • <List allowedValues="a,b,c" /> names them outright.
  • <Incremental increment="" minValue="" maxValue="" /> gives a numeric range, which Gears expands into every step. int and float only.
  • Naming an enum as the type uses its declared members, in declaration order, and needs neither child element.

A Selector also takes <Formatter>, <LocalizationPrefix> and <Wrap>, and it is one of the three elements that accept a per-value <Preview> image. See Child elements.

<Selector name="Units" displayKey="myModUnits" type="string" defaultValue="metric">
	<List allowedValues="metric,imperial" />
	<LocalizationPrefix prefix="myModUnits_" />
</Selector>

<Slider>

A bar the player drags, with arrows that nudge it one step. Global and world.

type must be int or float, and anything else drops the setting. <Incremental> sets the range, and a Slider without one has a range of 0 to 0. <Formatter> controls both the text drawn over the bar and the value written to disk. A float Slider accepts % notation, so 50% is stored as 0.5.

Gears reads no <List>, <Wrap> or <LocalizationPrefix> on a Slider.

<Slider name="Fov" displayKey="myModFov" type="int" defaultValue="65">
	<Incremental increment="5" minValue="45" maxValue="120" />
</Slider>

<Switch>

Two buttons side by side, and the lit one is the current value. Global and world.

type may be bool, string or any enum. <Buttons left="" right="" /> names the two sides. A bool Switch is false on the left and true on the right, an enum Switch takes its first two declared members, and a string Switch has no sides at all until <Buttons> gives it some. <LocalizationPrefix> turns both labels into localization keys.

Gears ignores <Formatter> on a Switch.

<Switch name="ShowHints" displayKey="myModShowHints" type="bool" defaultValue="true">
	<LocalizationPrefix prefix="myModOnOff_" />
</Switch>

<Color>

Global only.

<Color name="Crosshair" displayKey="myModCrosshair" defaultValue="255,0,0" />

A Color setting has a fixed type, so type is accepted and ignored. It takes defaultValue, which is required, plus <Caption>, <Description>, <RestartScope> and a value-less <Preview>.

Write defaultValue as R,G,B or R,G,B,A, each 0–255. Gears serializes the value as R,G,B only, so an alpha value is not kept once the player's value has been saved.

<Binding>

Global only.

<Binding name="Boost" displayKey="myModBoost">
	<Description key="myModBoostDesc" />
</Binding>

A Binding takes only name, displayKey, <Caption>, <Description>, <RestartScope> and a value-less <Preview>. It has no type, no defaultValue and no valued previews.

Declaring the binding in XML gives it a row in the menu. You must attach the actual key binding from C# through IControlBindingSetting.PlayerAction. See Use Global Settings in C#.

Child elements

Gears matches each child by name among the setting's direct children. Unless noted, the order in the file does not matter.

<Incremental increment="" minValue="" maxValue="" /> on Selector and Slider

Gears parses all three attributes with the setting's value type. All three must parse or Gears applies none of them. Each failure logs Setting '<name>': could not parse <increment|minValue|maxValue> '<raw>' as <Type> - <message>.

  • On a Slider, the three values become the slider's range. A slider with no <Incremental> has a range of 0 to 0.
  • On an int or float Selector, Gears expands the range into the list min, min+increment, … up to and including max. increment must be greater than 0 and min no greater than max. Otherwise Gears ignores the range and [SelectorSetting] or [SelectorWorldSetting] logs Setting:'<name>', SetAllowedValues(increment, min, max) requires increment > 0 and min <= max; …
  • On a string or enum Selector, Gears ignores the range and logs Setting:'<name>', SetAllowedValues(increment, min, max) requires a numeric type; '<Type>' is not supported.

<List allowedValues="a,b,c" /> on Selector only

Gears splits the value on commas, then trims and parses each entry. One bad entry drops the whole list, logging Setting '<name>': could not parse allowedValues entry '<raw>' as <Type> - <message>. The setting survives with no allowed values, except that an enum Selector keeps its declared members. There is no way to include a literal comma in a value.

When a Selector declares both <List> and <Incremental>, Gears applies the list first and the range second, whatever order they appear in, so the range wins.

<Formatter ui="" serialize="" /> on Selector and Slider

Both attributes are optional, and Gears applies each one only if it is non-empty.

  • ui is what the player sees.
  • serialize is what Gears writes to the saved settings file and what modsetting() returns.

Each is a .NET numeric format string, such as "0.0", "000" or "0%", handed to the value's formatter. They take effect on int, float and double. bool, string, Color and enums ignore the format string, and Gears ignores <Formatter> entirely on Switch, Color and Binding.

<LocalizationPrefix prefix="" /> on Selector and Switch

Gears joins the prefix to the formatted value with no separator and looks the result up as a localization key. A prefix of myModUnits_ and a value of metric display whatever myModUnits_metric says in Localization.csv.

The prefix applies to each allowed value, to both Switch buttons, and to the current and selected value. Gears ignores it on Slider, Color and Binding.

<Wrap wrap="true" /> on Selector only

Write true or false, in any case. Gears ignores anything else and leaves wrapping off. Wrapping controls whether stepping past the last value returns to the first.

<Buttons left="" right="" /> on Switch only

Both attributes must be present and both must parse as the value type. Otherwise Gears applies neither and these defaults stand:

TypeLeftRight
boolfalsetrue
enumfirst declared membersecond declared member
stringnonenone, so set <Buttons>

The lit button follows the selected value. It is Right when the value equals the right side and not the left, and Left in every other case.

<Caption key="" /> and <Description key="" /> on every setting and category, but not Tab

Both take a localization key, and Gears applies each one only if key is non-empty. Writing <Caption /> or <Caption key="" /> leaves the property unset.

  • The caption is the short heading in the description pane. Unset, it falls back to the display name.
  • The description is the body text. Unset, nothing is shown. This is the V2 replacement for the V1 tooltipKey on settings and categories.

<RestartScope scope="" /> on global settings only

Write None, Reload or Restart, in any case. Gears shows the player a warning that a change needs a world reload or a game restart. An unrecognized value leaves the scope at None, and an empty one is ignored.

Gears ignores <RestartScope> on a world setting and on a category, without a log line. A world setting is applied along with the world it belongs to, so there is nothing to ask the player to restart.

<Preview> with <Image path="" value="" />

A preview is an image shown beside the setting. There are two forms:

  • <Image path="…" /> with no value is the setting's own image. It is allowed on every setting and on a category. With several, the last one wins.
  • <Image value="…" path="…" /> is shown while that value is selected, on Selector, Slider and Switch only. Gears parses value as the setting's type and skips an unparseable one with Setting '<name>': could not parse preview value '<raw>' as <Type> - <message>. With two images for the same value, the first one wins.

Color accepts only the value-less form. Gears skips a valued <Image> on a Color with the warning Setting '<name>': Color settings do not support per-value previews, ignoring <Image value="…">. Binding and Category also take the value-less form only. Gears ignores an <Image> with no path, and one placed outside a <Preview>.

Gears passes path to the game's texture loader untouched, so use the game's own mod-folder form:

<Image path="@modfolder(MyMod)://Textures/low.png" />

Here MyMod is the <Name> from ModInfo.xml.

How duplicate names merge

Whether a repeated name merges or is dropped depends on where the repeat is:

RepeatResult
Two <Tab> elements with the same name under <Global>Merged into one tab. Their categories merge by the same rules.
Two <Category> elements with the same name under <World>Merged into one category.
A category with the same name as one in a separate <Tab> element of the same nameMerged, along with the settings inside it.
Two settings with the same name in categories that mergeMerged into one setting, as described below.
Two <Category> elements with the same name inside one <Tab> elementThe second category and every setting in it are dropped, without a log line.
Two settings with the same name inside one <Category> elementThe second setting is dropped, without a log line.

When two settings merge, the later default, applied and selected values overwrite the earlier ones. A Selector's allowed values, formatters and prefix are taken only when the earlier one had none. Wrap is true if either one set it.

To keep the file predictable, give every tab, category and setting a unique name in its parent. Two world settings in different categories never merge, but they still need different names; see Attributes every setting takes.

What gets dropped and what survives

ProblemOutcome
No version, wrong version, malformed XML, wrong rootWhole file skipped. With no global settings from C#, the mod's saved global values are also removed.
A category name repeated inside one <Tab> elementSecond category and its settings dropped, no log line
A setting name repeated inside one <Category> elementSecond setting dropped, no log line
Setting with no type, an unknown type, or a type with no implementation for that elementSetting dropped
Selector, Slider, Switch or Color with no defaultValueSetting dropped
string or bool on a SliderSetting dropped
Color or Binding under <World>Setting dropped, no log line
Setting element directly under <Tab>Setting dropped, no log line
Unparseable defaultValueSetting kept at default(T)
One bad allowedValues entryWhole list dropped, setting kept
One bad increment, minValue or maxValueWhole range dropped, setting kept
increment of 0 or less, or min above maxRange dropped, setting kept
<Buttons> with one side missing or unparseableNeither side applied, setting kept
Non-boolean WrapIgnored
Unknown RestartScopeIgnored
RestartScope on a world setting or a categoryIgnored
<Formatter> on Switch, Color or BindingIgnored
<Image> with no path, outside <Preview>, or with an unparseable valueImage skipped

Blank template

Every element in one place. Copy it and delete what you do not need. Remember that type and defaultValue must be filled in on every Selector, Slider, Switch and Color.

ModSettings.xml
<?xml version="1.0" encoding="utf-8"?>
<ModSettings version="2">
	<Global>
		<Tab name="" displayKey="" tooltipKey="">
			<Category name="" displayKey="">
				<Caption key="" />
				<Description key="" />
				<Preview>
					<Image path=""/>
				</Preview>

				<Selector name="" displayKey="" type="(int,float,string,enum)" defaultValue="">
					<Incremental increment="" minValue="" maxValue="" />
					<Formatter ui="" serialize="" />
					<List allowedValues="" />
					<LocalizationPrefix prefix=""/>
					<Wrap wrap="true" />
					<Caption key="" />
					<Description key="" />
					<RestartScope scope="(none/reload/restart)" />
					<Preview>
						<Image path="" value=""/>
					</Preview>
				</Selector>

				<Slider name="" displayKey="" type="(int,float)" defaultValue="">
					<Incremental increment="" minValue="" maxValue="" />
					<Formatter ui="" serialize="" />
					<Caption key="" />
					<Description key="" />
					<RestartScope scope="(none/reload/restart)" />
					<Preview>
						<Image path="" value=""/>
					</Preview>
				</Slider>

				<Switch name="" displayKey="" type="(bool,string,enum)" defaultValue="">
					<Buttons left="" right="" />
					<LocalizationPrefix prefix=""/>
					<Caption key="" />
					<Description key="" />
					<RestartScope scope="(none/reload/restart)" />
					<Preview>
						<Image path="" value=""/>
					</Preview>
				</Switch>

				<Color name="" displayKey="" defaultValue="">
					<Caption key="" />
					<Description key="" />
					<RestartScope scope="(none/reload/restart)" />
					<Preview>
						<Image path=""/>
					</Preview>
				</Color>

				<Binding name="" displayKey="">
					<Caption key="" />
					<Description key="" />
					<RestartScope scope="(none/reload/restart)" />
					<Preview>
						<Image path=""/>
					</Preview>
				</Binding>
			</Category>
		</Tab>
	</Global>
	<World>
		<Category name="" displayKey="">
			<Caption key="" />
			<Description key="" />
			<Preview>
				<Image path=""/>
			</Preview>

			<Selector name="" displayKey="" type="(int,float,string,enum)" defaultValue="">
				<Incremental increment="" minValue="" maxValue="" />
				<Formatter ui="" serialize="" />
				<List allowedValues="" />
				<LocalizationPrefix prefix=""/>
				<Wrap wrap="true" />
				<Caption key="" />
				<Description key="" />
				<Preview>
					<Image path="" value=""/>
				</Preview>
			</Selector>

			<Slider name="" displayKey="" type="(int,float)" defaultValue="">
				<Incremental increment="" minValue="" maxValue="" />
				<Formatter ui="" serialize="" />
				<Caption key="" />
				<Description key="" />
				<Preview>
					<Image path="" value=""/>
				</Preview>
			</Slider>

			<Switch name="" displayKey="" type="(bool,string,enum)" defaultValue="">
				<Buttons left="" right="" />
				<LocalizationPrefix prefix=""/>
				<Caption key="" />
				<Description key="" />
				<Preview>
					<Image path="" value=""/>
				</Preview>
			</Switch>
		</Category>
	</World>
</ModSettings>

On this page