Oblivion XML Reference/Operators
Operators act as a stack of sorts. Each operator element has its own value (either as the contents of its XML tag, or pulled from another element via the src and trait attributes) and it returns a value, operating with awareness of its previous sibling’s returned value.
Trait elements can only contain raw number values, raw string values, or operator child elements. Operator elements can generally only contain raw number values or operator child elements. Besides copy, there are no string operators. Here are some examples of operators:
<copy>3</copy> <copy src="other_tile" trait="other_trait" /> <add>3</add> <add src="other_tile" trait="other_trait" /> <copy>&true;</copy> <!-- "&true;" equals "2" under the hood -->
Operators can also be nested up to any depth:
<copy>3</copy> <mult> <copy>1</copy> <add>2</add> </mult> <!-- This code computes: 3 * (1 + 2) -->
The following terms are used when explaining operators:
- argument
- The value inside of an operator's tags.
- current working value
- The value that has been computed right up to an operator being processed.
- to select
- To pull a value from somewhere else, using the src and trait attributes.
- to return
- The act of providing a result. As an example, the mult operator multiplies the argument by the current working value, and "returns" the result. The returned value then becomes the next operator's current working value.
In the above code sample, the add operator has a current working value of 1, and an argument of 2.
Copy operator
The copy operator is used to overwrite the current working value:
<copy>3</copy> <add>2</add> <!-- Current working value: 3 + 2 --> <copy>1</copy> <!-- Current working value: 1 -->
However, the copy operator can also be used to implement XML switch-cases. If the current working value is a number, and the copy operator selects a trait whose name starts and ends with an underscore, then that trait is treated as a list of choices suffixed with numbers:
<_traitName_1> First Value </_traitName_1> <_traitName_2> Second Value </_traitName_2> <_traitName_3> Third Value </_traitName_3> <string> <copy>2</copy> <add>1</add> <copy src="me()" trait="_traitName_" /> </string>
In that code example, the current working value is (2 + 1), or 3. The last copy operator selects a trait bordered by underscores (_traitName_
), so the current working value is tacked onto that trait name (_traitName_3
), and the resulting trait's value is returned. The underscore-bordered traits are referred to as cases.
The utility of this is that you can switch-case on any value. For example, the RepairMenu
is actually used for selecting an item to repair, selecting an ingredient to add to a potion, or selecting a soul gem to use for an enchantment. The user0 trait on the menu identifies what it's being used for. That means you can do something like this:
<text name="menu_title"> <_title_1> Repair your gear </_title_1> <_title_2> Pay a merchant to repair gear </_title_2> <_title_3> Select an alchemy ingredient </_title_3> <_title_4> Select an item to enchant </_title_4> <_title_5> Select a soul gem to enchant with </_title_5> <_title_6> Select a sigil stone </_title_6> <string> <copy src="RepairMenu" trait="user0" /> <copy src="me()" trait="_title_" /> </string> </text>
There are a few caveats to keep in mind regarding XML switch-cases:
- The zeroth (0) case will never be used.
- If the copy operator ends up looking for a missing trait, then the number zero will be returned — not an empty string.
- The switch-case feature doesn't handle trait names properly if they contain an underscore in the middle, e.g.
_trait_name_3
. The XML properly extracts the3
, but it will then look for_trait_3
. - According to Bethesda’s code comments (in the stats menu), switch-cased strings only work on the first frame if the cases are defined before the copy operator is used.
Other operators
- abs
- If the current working value is less than zero, then the operator’s argument is added to it, and the operator returns the absolute value of the result. Otherwise, the current working value is returned verbatim.
- add
- Adds its value to the current working value, and returns the result.
- and
- Returns
&true;
if both the current working value and the operator’s argument evaluate to&true;
, or&false;
- ceil
- Returns the current working value rounded up to the nearest integer. Disassembly of the executable suggests that the operator’s argument is added to the current working value before the rounding is performed.
- div
- Divides the current working value by the argument, and returns the result.
- eq
- Returns
&true;
if the current working value is equal to the argument, or&false;
otherwise. Note that this operator only works on floating-point values; it always returns false for strings. - floor
- trunc
- Returns the current working value rounded down to the nearest integer. Disassembly of the executable suggests that the operator’s argument is added to the current working value before the rounding is performed.
- The trunc tag isn’t used in any vanilla menus, but its meaning was verified through examining the executable.
- gt
- Returns
&true;
if the current working value is greater than its value, or&false;
otherwise. - gte
- Returns
&true;
if the current working value is greater than or equal to its value, or&false;
otherwise. - log
- Computes and returns the base-10 logarithm of the current working value. Disassembly suggests that the operator’s argument is not used.
- ln
- Computes and returns the natural logarithm of the current working value. Disassembly suggests that the operator’s argument is not used.
- lt
- Returns
&true;
if the current working value is less than the argument, or&false;
otherwise. - lte
- Returns
&true;
if the current working value is less than or equal to its value, or&false;
otherwise. - max
- Compares the argument to the current working value, and returns whichever value is larger.
- min
- Compares the argument to the current working value, and returns whichever value is smaller.
- mod
- Returns the current working value modulo the operator’s argument.
- mul
- mult
- Multiplies the current working value by the argument, and returns the result.
- neq
- Returns
&true;
if the current working value is not equal to the argument, or&false;
otherwise. - not
- Casts the argument to a Boolean, inverts it, and returns the result.
- onlyif
- Returns the current working value if the operator’s argument evaluates to
&true;
, or zero otherwise. - onlyifnot
- Returns the current working value if the operator’s argument evaluates to
&false;
, or zero otherwise. - or
- Returns
&true;
if one or both of the current working value and the operator’s argument evaluate to&true;
. - rand
- Sets the current working value to a random integer between 1 and the operator’s argument, inclusive.
- ref
- This operator generally does nothing, and is completely ignored. It is only handled by keyboard navigation.
- sub
- Subtracts the argument from the current working value, and returns the result.