7.2. Data types

MScript supports the following data types:

There is no decicated boolean type. Instead, none acts as false, and any other value acts as true when a boolean is expected. Functions that return a bool usually return either 1 (true) or none (false).


7.2.1. number

Used for properties that describe amounts, distances and volumes, but also for properties where a value can be selected from a list, because these are stored as numbers internally. Spawn flags are also stored as a number, in the special spawnflags property. They are written the same both inside and outside expressions, for example 1 and -4.5. Inside expressions, hexadecimal notation can also be used, for example, 31 can also be written as 0x1F.

Numbers can be used in arithmetic operations and can be compared against each other. They do not have any member properties or functions. Numerical operations are mostly done with operators instead. All numbers are 64-bit floating point numbers (doubles).

See also: standard mathematics functions and standard trigonometry functions.


7.2.2. string

A string is a piece of text. Any property value that does not look like a number or a sequence of numbers is treated as a string. Within expressions strings must be surrounded by single quotes, to distinguish them from identifiers: 'targetname' produces the literal text targetname, whereas targetname refers to the targetname property of the macro entity that is instantiating the current template.

Strings can be indexed in much the same way as arrays can, except that indexing returns a 1-character string instead of a number. Negative indexing is also supported, and indexes that do not exist produce the special value none.

The following escape sequences are recognized: \' (single quote), \" (double quote), \\ (backslash), \0 (null-terminator), \a (alert), \b (backspace), \f (form feed), \n (newline), \r (carriage return), \t (horizontal tab), \v (vertical tab), \xHH (2-digit Unicode sequence) and \uHHHH (4-digit Unicode sequence).

Properties

number length

Returns the number of characters in this string.

For example, 'hello'.length returns 5.


Indexing

string [number index]

Returns the character at the given index as a 1-character string, or none if the index is out of range. Negative indexes start counting from the end of the string.

For example, 'hello'[-1] returns 'o'.


Member functions

Comparisons and checks

bool equals(string str, bool ignore_case = false)

Checks whether this string is equal to the given string. Unlike the == operator, this function can also be used to do a case-insensitive comparison. Returns 1 (true) if the strings are equal, or none if not.

For example, 'abc'.equals('ABC', 1) returns 1 (true).


bool contains(string str, bool ignore_case = false)

Searches this string for the given string, and returns 1 (true) if the string is present, or none if it is not. The search is case-sensitive by default.

For example, 'a small sentence'.contains('small') returns 1 (true).


bool startswith(string str, bool ignore_case = false)

Checks whether this string starts with the given string. Returns 1 if true, or none if not. The comparison is case-sensitive by default.

For example, 'firestorm'.startswith('fire') returns 1 (true).


bool endswith(string str, bool ignore_case = false)

Checks whether this string ends with the given string. Returns 1 if true, or none if not. The comparison is case-sensitive by default.

For example, 'firestorm'.endswith('orm') returns 1 (true).


number|none index(string str, number offset = 0, bool ignore_case = false)

Returns the index of the first occurrence of the given string in this string, or none if the given string could not be found. If an offset is specified, the search will start from that index, which can be useful for skipping earlier occurrences. Negative offsets are counted from the end of the string. The comparison is case-sensitive by default.

For example, 'ABCBCA'.index('C') returns 2.


number|none lastindex(string str, number offset = none, bool ignore_case = false)

Returns the index of the last occurrence of the given string in this string, or none if the given string could not be found. If an offset is specified, the search will start from that index, which can be useful for skipping later occurrences. Negative offsets are counted from the end of the string. The comparison is case-sensitive by default.

For example, 'ABCBCA'.lastindex('C') returns 4.


number count(string str, number offset = none, bool ignore_case = false)

Returns the number of non-overlapping occurrences of the given string. If an offset is specified, the search will start from that index. Negative offsets are counted from the end of the string. The comparison is case-sensitive by default.

For example, 'ABCBCA'.count('A') returns 2, and 'ABCBCA'.count('b', 3, 1) returns 1.


Substrings, trimming and replacing

string substr(number offset, number length = none)

Returns the specified part of this string as a new string. A negative offset is counted from the end of the string. If no length is specified then the rest of the string is taken, starting from the given offset. An empty string is returned if the offset or length are out of range.

For example, 'hotel_room'.substr(6, 2) returns 'ro'.


string trim(string chars = none)

Returns a copy of this string, with specific characters removed from the start and end. Removes whitespace characters if no characters are specified.

For example, '_test_case_'.trim('_') returns 'test_case'.


string trimstart(string chars = none)

Returns a copy of this string, with specific characters removed from the start. Removes whitespace characters if no characters are specified.

For example, '_test_case_'.trimstart('_') returns 'test_case_'.


string trimend(string chars = none)

Returns a copy of this string, with specific characters removed from the end. Removes whitespace characters if no characters are specified.

For example, '_test_case_'.trimend('_') returns '_test_case'.


string replace(string str, string replacement, bool ignore_case = false)

Returns a copy of this string, with all occurrences of str replaced with the given replacement. The comparison is case-sensitive by default.

For example, 'old is cold'.replace('old', 'new') returns 'new is cnew'.


Changing case

string upper()

Returns a copy of this string, with all characters turned into uppercase characters.

For example, 'Hello there'.upper() returns 'HELLO THERE'.


string lower()

Returns a copy of this string, with all characters turned into lowercase characters.

For example, 'This is GOOD'.lower() returns 'this is good'.


Splitting and joining

array split(any delimiters = none, number count = none)

Splits this string into multiple parts and returns those as an array of strings. The delimiter can be a single string or an array of strings. Any other value is treated as none, and will result in splitting on whitespace. If a count is specified, then the resulting array will contain at most that many parts.

For example, 'apple;pear;banana;'.split(';') returns ['apple', 'pear', 'banana', ''].


array splitr(string pattern = none, number count = none)

Splits this string into multiple parts using a regular expression pattern. If not pattern is specified, the string will be split on whitespace. If a count is specified, then the resulting array will contain at most that many parts.

For example, 'apple---pear_-_banana   orange'.splitr('[-_\\s]+') returns ['apple', 'pear', 'banana', 'orange'].


string join(array values)

Combines the string representation of the values in the given array, while inserting this string in-between each pair of values.

For example, ';'.join(['apple', 'pear', 'banana']) returns 'apple;pear;banana'.


Regular expressions

bool match(string pattern)

Returns 1 (true) if this string matches the given regular expression pattern, or none (false) if it does not.

For example, 'env_beam'.match('^env_.*') returns 1.


array matches(string pattern)

Returns an array that contains all non-overlapping occurrences of the given regular expression in this string.

For example, 'This is a sentence.'.matches('\\w+') returns ['This', 'is', 'a', 'sentence'].


7.2.3. array

An array can store multiple values of different types. Property values that contain two or more numbers, separated by whitespace, are treated as an array. Within expressions, arrays must be surrounded by brackets and values must be separated by commas: [1, 2, 3]. When an array is converted to text, the brackets and commas are omitted and the values are separated by spaces, to match the entity property format.

Arrays can be indexed, where a[0] returns the first item, and a[a.length - 1] returns the last item. Negative indexes are also supported: a[-1] returns the last item, a[-a.length] returns the first item. Indexes that are outside the range of the array will produce the special value none.

See also: standard array functions.

Properties

number length

Returns the number of items in this array.

For example, ['A', 'B', 'C'].length returns 3.


Position, angles and colors

Arrays contain a few properties that don't make sense in all contexts, but they can be convenient when working with positions, angles and colors.

number|none x
number|none y
number|none z

These properties return the first, second and third item respectively, but only if they are a number. For example, [1, 2, 3].x returns 1, but ['A', 'B', 'C'].y returns none.

number|none pitch
number|none yaw
number|none roll

These properties also return the first, second and third item respectively, if they are a number.

number|none r
number|none g
number|none b
number|none brightness

Once more, these properties return the first, second, third and fourth items respectively, if they are a number.

Indexing

any [number index]

Returns the item at the given index, or none if the index is out of range. Negative indexes start counting from the end of the array. For example, -1 will return the last item in the array.

For example, ['A', 'B', 'C'][1] returns 'B'.

Member functions

Cutting and combining

array slice(number start, number end = none, number step = 1)

Returns a new array by taking specific items from this array. By default, the result will contain all items between the start index (inclusive) and the end index (exclusive). If no end is given, then items will be taken until the end of the array is reached. Both start and end index can be negative.

The step argument lets you skip elements or invert the result. For example, a step value of 2 will skip every second item, and a step value of -1 will pick items in reversed order.

For example, ['A', 'B', 'C', 'D'].slice(1, 3) returns ['B', 'C'].


array skip(number count)

Returns a new array that contains all but the first count items from this array.

For example, ['A', 'B', 'C'].skip(2) returns ['C'].


array take(number count)

Returns a new array that contains only the first count items from this array.

For example, ['A', 'B', 'C'].take(2) returns ['A', 'B'].


any first()

Returns the first item from the array, or none if the array is empty.

For example, ['A', 'B', 'C'].first() returns 'A'.


any last()

Returns the last item from the array, or none if the array is empty.

For example, ['A', 'B', 'C'].last() returns 'C'.


array concat(array other)

Returns a new array with the items from the given array added at the end.

For example, ['A', 'B', 'C'].concat(['X', 'Y', 'Z']) returns ['A', 'B', 'C', 'X', 'Y', 'Z'].


array prepend(any value)

Returns a new array with the given value added at the start.

For example, ['A', 'B', 'C'].prepend('Z') returns ['Z', 'A', 'B', 'C'].


array append(any value)

Returns a new array with the given value added at the end.

For example, ['A', 'B', 'C'].append('Z') returns ['A', 'B', 'C', 'Z'].


array insert(number index, any value)

Returns a new array with the given value inserted at the given index. The index can be negative.

For example, ['A', 'B', 'C'].insert(2, 'Z') returns ['A', 'B', 'Z', 'C'].


Searching

bool contains(any value)

Searches the array for the given value, and returns 1 (true) if the value is present, or none if it is not.

For example, ['B', 'A', 'B', 'A'].contains('C') returns none.


number index(any value, number offset = none)

Searches the array for the first occurrence of the given value and returns its index, or none if the value was not found. An optional start offset can be given, which can be useful for finding subsequent occurrences. The offset can be negative.

For example, ['B', 'A', 'B', 'A'].index('A') returns 1.


number lastindex(any value, number offset = none)

Searches the array for the last occurrence of the given value and returns its index, or none if the value was not found. An optional start offset can be given, which can be useful for finding earlier occurrences. The offset can be negative.

For example, ['B', 'A', 'B', 'A'].lastindex('B') returns 2.


Functional programming

array map(function selector)

Calls the given selector function for every item in the array and returns a new array that contains the results.

selector must either be a function that takes a single argument: (any value) => any, or a function that takes two arguments: (any value, number index) => any.

For example, ['apple', 'pear', 'banana'].map(s => s.length) returns [5, 4, 6].


array filter(function predicate)

Returns a new array that only contains the items for which predicate returned true.

predicate must either be a function that takes a single argument: (any value) => bool, or a function that takes two arguments: (any value, number index) => bool.

For example, [2, 8, 5, 7].filter(n => n < 6) returns [2, 5].


any reduce(function reducer, any start_value = none)

Reduces an array to a single value by calling reducer for each item, passing the current result and item, and using the return value as the new result. The start value is used as the initial result.

reducer must be a function that takes two arguments: (any result, any value) => any.

For example, [4, 'times', 6].reduce((result, value) => result + ';' + value) returns '4;times;6'.


array groupby(function key_selector)

Groups items by calling key_selector for each item to obtain its key, and creating a group for each distinct key. Returns an array of {any key, array values} objects, where key contains a key returned by a key_selector call, and values contains all items from the original array that are associated with that key.

key_selector must be a function that takes one argument: (any value) => any.

For example, ['bear', 'lion', 'leopard'].groupby(s => s[0]) returns [{key: 'b', values: ['bear']}, {key: 'l', values: ['lion', 'leopard']}].


array zip(array other, function zipper)

Combines items from two arrays by calling zipper with the first items from both arrays, then with the second items from both arrays, and so on, until one of the arrays is exhausted.

zipper must be a function that takes two arguments: (any value, any otherValue) => any.

For example, [1, 2, 3, 4].zip(['A', 'B', 'C'], (n, s) => n + s) returns ['1A', '2B', '3C'].


array sort(function sort_by)

Sorts an array in ascending order, based on the sorting values returned by sortby.

sort_by must be a function that takes one argument and that returns a number: (any value) => number.

For example, ['red', 'green', 'blue'].sort(s => s.length) returns ['red', 'blue', 'green'].


array reverse()

Returns a reversed array.

For example, ['first', 'second', 'third'].reverse() returns ['third', 'second', 'first'].


bool any(function predicate = none)

Checks if any item in the array matches the given predicate, or if the array contains any items if no predicate is given.

predicate can either be none, or a function that takes one argument: (any value) => bool.

For example, [4, 5, 6].any(n => n > 5) returns 1 (true).


bool all(function predicate)

Checks if all items in the array match the given predicate.

predicate can either be none, or a function that takes one argument: (any value) => bool.

For example, [4, 5, 6].all(n => n > 5) returns none (false).


Numerical

number|none max(funtion selector = none)

Returns the highest number from the array. An optional selector function can be provided to convert items to a number first. Returns none if the array does not contain any numbers.

selector can either be none, or a function that takes one argument and that returns a number: (any value) => number.

For example, [4, 8, 3].max() returns 8.


number|none min(function selector = none)

Returns the lowest number from the array. An optional selector function can be provided to convert items to a number first. Returns none if the array does not contain any numbers.

selector can either be none, or a function that takes one argument and that returns a number: (any value) => number.

For example, [4, 8, 3].min() returns 3.


number|none sum(function selector = none)

Returns the sum of all the numbers in the array. An optional selector function can be provided to convert items to a number first. Returns 0 if the array does not contain any numbers.

selector can either be none, or a function that takes one argument and that returns a number: (any value) => number.

For example, [4, 8, 3].sum() returns 15.


7.2.4. object

An object is a collection of named values. It can be used to create more complex data types. An object is written as {field1: value1, field2: value2}.

Objects do not have default properties or functions. Their fields act as properties instead.

See also: standard object functions.


7.2.5. function

A function is a piece of code that, when called, returns a value. For example, max(4, 5) calls a function named max, passing two numbers as arguments (inputs). The result of a function call is the value returned by the function. Functions can require multiple arguments, and some functions have optional arguments, but they always return a single value.

In MScript, functions are 'first-class citizens': just like other values, they can be passed to other functions, and stored in arrays and objects.

Sometimes it's useful to create an 'anonymous' function on the spot, for example when using the array.map and array.filter functions. An anonymous function can be created as following: (a, b) => a + b, where the (a, b) part defines the required arguments and the part after the => is the function 'body', the code that produces the function's output. For example, numbers_array.map(n => n * 2) uses an anonymous function to multiply every number in numbers_array by 2.

See also: standard function functions.


7.2.6. none

none is a special value that indicates the absence of a value. It is the only value that is treated as false in boolean situations.