Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

The attributes onfail, checkinterval, checktime are not allowed for cues with event conditions.

 


Note

Reminder: When using an XSD-capable editor, it's a great help, but you cannot rely on that alone to verify correctness. Please also check the documentation and look for errors in the game debug output. Concretely, the schema cannot tell whether the above cue attributes are used correctly.

...


Actions

The <actions> node contains the actions that are performed one after another, without any delay inbetween. You can enforce a delay after activation of the cue and actual action performance, using a <delay> node right before the <actions>:

...

When the ref attribute is provided, all other attributes (except for name) will be ignored and taken from the library cue instead. (By default a library creates its own namespace, as if namespace="static" were specified. See the section about namespaces.)

Also all sub-cues of the library will be created as sub-cues of the cue that uses it. They are defined in the library as <cue>, not as <library>. (Although you can define a library as a sub-cue of another library, the location in the file does not matter, as already stated above.) It is even possible to reference other libraries in sub-cues of a library!

...

So when writing the library, you don’t have to worry about name confusion, just use the names of cues in your library and it will work as expected when the library is used. Names of cues that do not belong to the library will not be available in expressions (see Foo in the example above), however, names of other libraries in the file are available when referencing them in the ref attribute.

Notes:

  • It is not possible to directly call a cue which is 'inside' the library from 'outside' of the library, but it is possible to signal the library ref itself (possibly with parameters) and have a sub-cue inside the library listen to the signal on the library ref (possibly checking the parameters).
  • You can access variables in the library root but generally this should be avoided in favor of parameterizing the library!
    • there are some cases where you do want to access these variables directly, for example for maintaining savegame compatibility when patching.

Library Parameters

A library can be parametrised, so that it can be adapted to the needs of a missions that uses it. You can define required and/or optional parameters for a library, and it will be validated at load time that the user of the library has provided all required parameters.

...

Here is the complete list of numeric data types and corresponding unit suffixes:



 

Data type

Suffix

Examples

Description

null

(none)

null

Converted to non-null data type of value 0 when needed.

integer

i

42

32-bit signed integer. Default for integer literals, so the suffix is not required for them.

largeint

L

0x1ffffffffL

Large 64-bit signed integer.

float

f

3.14

0x100f

32-bit float (single precision). Default for floating point literals, so the suffix is not required for them.

largefloat

LF

1.5e300 LF

Large 64-bit floating point number (double precision).

money

ct (default)
Cr

200Cr
50ct

Money in Credits or cents, always stored in cents. Do not forget to write Cr when working with Credits.

length

m (default)

km

500m

2.3km

Length in metres or kilometres, respectively. A length value is always stored in metres.

angle

rad (default)

deg

90deg

3.14159rad

Angle in radians or degrees, respectively. An angle value is always stored in radians.

hitpoints

hp

100hp

Hit points

time

ms

s (default)

min

h

800ms

1.5s

10min

24h

Time in milliseconds, seconds, minutes, or hours, respectively. A time value is always stored in seconds.

Note

All unit data types are floating point types, except for money, which is an integer data type.

 


Anchor
operators
operators
Operators

You can build expressions by combining sub-expressions with operators. For Boolean operations, expressions are considered “false” if they are equal to zero, “true” otherwise. The following operators, delimiters, and constants are supported:



 

Operator / Delimiter / Constant

Type

Example

Result of example

Description

null

constant

null + 1

1

Null value, see above

false

constant

1 == 0

false

Integer value 0, useful in Boolean expressions

true

constant

null == 0

true

Integer value 1, useful in Boolean expressions

pi

constant

2 * pi

6.2831853rad

π as an angle (same as 180deg)

()

delimiter

(2 + 4) * (6 + 1)

42

Parentheses for arithmetic grouping

[]

delimiter

[1, 2, 2+1, 'string']

[1, 2, 3, 'string']

List of values

table[]delimitertable[$foo='bar', {1+1}=40+2]table[$foo='bar', {2}=42]Table of values

{}

delimiter

{101, 3}

'Some text'

Text lookup (page ID and text ID) from TextDB
(Note: Braces are also used for property lookups)

+

unary

+21 * (+2)

42

Denotes positive number (no effect)

-

unary

-(21 * -2)

42

Negates the following number

not

unary

not (21 == 42)

true

Yields true if the following expression is false (equal to zero), false otherwise

typeof

unary

typeof null

typeof 0

typeof 'Hello world'

datatype.null

datatype.integer

datatype.string

Yields the data type of the following sub-expression

sin

unary

sin(30deg)

sin(pi)

0.5

1.0

Sine (function-style, parentheses required)

cos

unary

cos(60deg)

cos(pi)

0.5

0.0

Cosine (function-style, parentheses required)

sqrt

unary

sqrt(2)

1.414213LF

Square root (function-style, parentheses required)

exp

unary

exp(1)

2.71828LF

Exponential function (function-style, parentheses required)

log

unary

log(8) / log(2)

3.0LF

Natural logarithm (function-style, parentheses required)

^

absunary

abs(42)
abs(-42.0)

42
42.0
Absolute value (function-style, parentheses required) (added in X4 v6.00)
sgnunarysgn(-42)
sgn(0.0)
sgn(42.0)
-1
0
1
Sign function (function-style, parentheses required) (added in X4 v6.00)

^

binary

10 ^ 3

1000.0LF

Power

*

binary

21 * 2

42

Multiplication

/

binary

42 / 10
42.0 / 10.0

4
4.2

Division

%

binary

42 % 10

2

Modulus (remainder of integer division)

+

binary

1 + 1

'Hello' + ' world'

2

'Hello world'

Addition

String concatenation

-

binary

1 - 1

0

Subtraction

lt

&lt; (<)

binary

1 lt 3

1 &lt; 3

true

Less than

le

&lt;=

binary

1 le 3

1 &lt;= 3

true

Less than or equal to

gt

&gt; (>)

binary

1 gt 3

1 &gt; 3

false

Greater than

ge

&gt;=

binary

1 ge 3

1 &gt;= 3

false

Greater than or equal to

==

binary

1 + 1 == 2.0

true

Equal to

!=

binary

1 + 1 != 2.0

false

Not equal to

and

binary

true and false

false

Logical AND (short-circuit semantics)

or

binary

true or false

true

Logical OR (short-circuit semantics)

if ... then ...

if ... then ... else ...

ternary

if 1 == 2 then 'F'

if 1 == 2 then 'F' else 'T'

null

'T'

Conditional operator ("inline if")

 







Operator precedence rules

...

Lists are stored in variables as references, so multiple variables can refer to the same shared list: If you change a shared list through a variable, e.g. by changing the value of an element, you change it as well for all other variables. However, the operators == and != can also be used on two distinct lists to compare their elements.

...

Note

When using <remove_from_list/>, be aware that all elements are checked and potentially removed during the action. Do not provide this action with a index lookup of that list as it may become out of bounds.

Bad usage attempting to remove the last element of the list: <remove_from_list name="$List" exact="$List.{$List.count}"/>

If you know the index, simply use <remove_value/> e.g. <remove_value name="$List.{$List.count}"/>


Anchor
tables
tables
Tables

Tables are associative arrays - they are like lists, but you can assign values to (almost) arbitrary keys, not just to index numbers. A table is constructed within an expression using the table[] syntax. See the section about value properties for how to access the contents of a table. Creating and removing entries works similarly to lists, but instead of inserting, you simply assign a value to a table key. If the key does not exist yet, it will be created.

...

  • $table.keys.list: Yields a list of all keys in the table (reliably sorted by key if all keys are numeric)
  • $table.keys.sorted: Yields a sorted list of all keys in the table, sorted by their associated values (which requires that all keys values are numeric)
  • $table.keys.random: A randomly chosen key (which requires that the table is non-empty)

...

As you can see, an error is already prevented if any link in the property chain does not exist. But use the @ prefix with care, since error messages are really helpful for detecting problems in your scripts. The @ prefix only suppresses property-related error messages and does not change any in-game behaviour. 


Static lookups

There are a few data types which are basically enumerations: They only consist of a set of named values, e.g. the “class” data type, which is used for the component classes that exist in the game. For all these static enumeration classes there is a lookup value of the same name, from which you can get the named values as properties by their name. So for the type “class”, there is a value “class” that can be used to access the classes.

Here are a few enumeration classes and corresponding example lookup values:


 

Data type (= value name)

Examples

Description

class

class.ship

class.ship_xl

class.space

class.weapon

Component classes

purpose

purpose.combat

purpose.transportation

Purposes

killmethod

killmethod.hitbybullet

killmethod.hitbymissile

Ways to die (already used before destruction)

datatype

datatype.float

datatype.component

datatype.class

datatype.datatype

Script value datatypes

profile

profile.flat

profile.increasing

profile.bell

Probability distribution profile (see random ranges)

cuestate

cuestate.waiting

cuestate.active

cuestate.complete

Cue states

level

level.easy

level.medium

level.veryhard

Mission difficulty levels (comparable with each other using lt, gt, etc.)

attention

attention.insector

attention.visible

attention.adjacentzone

Attention levels (comparable with each other using lt, gt, etc.)

ware

ware.ore

ware.silicon

Wares

race

race.argon

race.boron

Races

faction

faction.player

faction.argongovernment

Factions

Note

Anchor
typeof
typeof
With the typeof operator you can get the datatype of any expression and compare it with what you expect, for example:

typeof $value == datatype.faction

However, you should not compare the type to datatype.string because there are strings that have different data types. To check for a string you should use the datatype's property "isstring" instead. For example, to check if the variable $value is a string, use the following term:

(typeof $value).isstring

Info

There is also the datatype “tag” with the lookup name “tag” - however, this is not an enumeration type. Looking up a value by name never fails, you actually create a tag value for a given name if it does not exist. For example, if you have a typo, like “tag.mision” instead of “tag.mission”, there won’t be an error because any name is valid for a tag, and the tag “mision” is created on its first use.


...

You can access many player-related game properties via the keyword “player”, for example:

  • player.name: The player’s name

  • player.age: The passed in-game time since game start

  • player.money: The money in the player’s account

  • player.ship: The ship the player is currently on (not necessarily the player's ship), or null if the player is on a station

  • player.primaryship (X Rebirth only): The player's own ship (but the player is not necessarily on board)
  • player.occupiedship (X4 only): The ship that the player is currently piloting, or null if the player is not piloting
  • player.entity: The actual player object
  • player.zone, player.sector, player.cluster, player.galaxy: Location of the player entity

  • player.copilot (X Rebirth only): The co-pilot NPC

The game consists of objects of different classes (zones, ships, stations, NPCs). They have the common datatype "component", however, they have different properties, e.g. NPCs have the property "race", but ships don't.

...

When formatting the money value, any specifier (such as '%s') in the format string is replaced by the money value, so usually the format string only consists of this one specifier. The following modifiers can be used between '%' and the specifier character, to enable formatting options:

1-9TruncationTo enable truncation, specify the number of relevant digits that should be displayed. If the money string is too long, it can be truncated and a metric unit prefix (e.g. k = kilo) is appended. (All digits are shown unless truncation is enabled.)
cColouring

If truncation is enabled, the metric unit prefixes (e.g. k, M, G) can be coloured when displayed on the screen, using the escape sequence '\033C'.

.CentsUsually money values have no cent part, since cents are not used in accounts or trades. However, single ware prices can have a non-zero cent part. (Cents are not displayed if money is truncated)
_SpacesAn underscore adds trailing spaces to the result string for better right-aligned display in a tabular layout.

By default, these options are disabled.

...

  • (151s).formatted.{'%T'} '00:02:31'
  • (151s).formatted.default '00:02:31' (same as {'%T'})
  • (151s).formatted.{'%.3T'} '00:02:31.000'
  • (151s).formatted.{'%h:%M'} '0:02'

...

Complete property documentation

...

documentation

To access the script property documentation that is included in the game, you can extract the required files from the game's catalog files using the X Catalog Tool. Extract the HTML file scriptproperties.html in the game's root folder, and all files in the "libraries" sub-folder. For resolving text references in the browser automatically, also extract 0001-L044.xml in the "t" sub-folder.

The raw documentation data is located in libraries/scriptproperties.xml, but it is recommended to open scriptproperties.html in a browser.

Note

scriptproperties.html has to load files from different folders, which modern browsers do not allow by default for security reasons. In order to open scriptproperties.html, the following is required:

  • Firefox: On the about:config page, the value of "security.fileuri.strict_origin_policy" has to be changed to "false".
  • Chrome: The Chrome launcher has to be started with the command-line parameter --allow-file-access-from-files

This provides you with a complete list of all supported “base keywords” and properties. To filter in this list, you can enter an expression in the text field:

...

Note

The documentation contains some data types that are no real script data types, but which are useful for documentation purposes. For example, ships and stations are both of datatype “component”, but have different properties based on their component class.

...


MD refreshing and patching

When a saved game is loaded, the saved MD state is restored, but also all MD files are reloaded and changes in them are applied to the MD state. This is called “refresh”. It is also possible to refresh the MD at run-time using the command “refreshmd” on the in-game command line. This is a convenient way to update MD scripts while the game is already running. 


Details and restrictions

Here are some noteworthy facts about refreshing scripts and cues, and the restrictions:

...

Warning

When adding a variable in a new MD script version and using that variable in multiple places, be aware that the variable doesn't exist yet in older savegames. You may have to check the existence of the variable before accessing it, or add some patch logic that initiailses the variable after loading the savegame, if necessary.

 


Patching

Cues can have <patch> elements with actions that will be performed when an old savegame is loaded. To control which savegames should be affected, you can add a version attribute to the <cue> node and a sinceversion attribute in the patch. When a cue is loaded from a savegame that has an older version than sinceversion, the <patch> actions will be performed immediately after loading.

...

Note

The <patch> elements will be ignored when refreshing the MD at run-time. They only affect loaded savegames.

...


Common attribute groups

There are many commonly used actions and conditions which share groups of attributes. The most important ones are explained here.

 


Anchor
valuecomparisons
valuecomparisons
Value comparisons

...

Note

Values of most enumeration types cannot be compared via min or max (also not via lt, gt, etc.). The only data types that can be used with min and max are numbers and the enumeration types level and attention (see Boolean operators). The exact attribute can be used with any type, and is equivalent to using the == operator.

...


Anchor
randomranges
randomranges
Random ranges

...