-
Notifications
You must be signed in to change notification settings - Fork 10
Statements
For the if
, switch
, while
, until
, and for
statements, you can declare
and use a variable as the condition at the same time. The variable is first
initialized, and the value of the variable is then used as the condition:
script "Main" open {
// This if-statement will only be executed if `value` is nonzero.
if ( let int value = Random( 0, 5 ) ) {
Print( d: value );
}
}
For the if
and switch
statements, the variable can be followed by an
expression. The variable must be used in the expression, and the expression
becomes the condition:
script "Main" open {
// This if-statement will only be executed if `value` is greater than 3.
if ( let int value = Random( 0, 5 ); value > 3 ) {
Print( d: value );
}
}
foreach ( value ; collection ) {} foreach ( key , value ; collection ) {} foreach ( key ; value ; collection ) {}
A foreach
loop goes over every item in a collection. An array is a
collection, and the elements of the array are the items. A string is also a
collection, and the characters of the string are the items. value
is a
variable that will contain the current item being looked at:
script "Main" open {
static int set[] = { 1, 2, 3 };
foreach ( let int number; set ) {
Print( d: number );
}
}
You can declare another variable before the value
variable. This variable is
called the key
variable. The key
variable will contain the index of the
array element or string character:
script "Main" open {
static int set[] = { 1, 2, 3 };
foreach ( let int index, number; set ) {
Print( s: "set[", d: index, s: "] == ", d: number );
}
}
If the key
and value
variables are of different type, you can declare two
different variables by separating them with a semicolon:
strict namespace {
script "Main" open {
static fixed set[] = { 1.0, 2.0, 3.0 };
foreach ( int index; fixed number; set ) {
Print( s: "set[", d: index, s: "] == ", f: number );
}
}
}
The key
and value
variables can be modified. On every iteration of the
loop, the key
and value
variables will be reset with the next key and
value:
strict namespace {
script "Main" open {
static fixed set[] = { 1.0, 2.0, 3.0 };
foreach ( int index; fixed number; set ) {
++index;
number += 1.5;
Print( s: "index == ", d: index, s: ", number == ", f: number );
}
// Output:
// index == 1, number == 2.5
// index == 2, number == 3.5
// index == 3, number == 4.5
}
}
goto label ; label :
A goto
statement is used to move to some location within a script
or a function. A location is identified with a label. A label consists of a
name, followed by a colon character. There must be no duplicate labels inside
the same script or function.
script "main" open {
goto bottom;
top:
Print( s: "top" );
goto end;
bottom:
Print( s: "bottom" );
goto top;
end:
// Output:
// bottom
// top
}
assert ( condition [, description] ); static assert ( condition [, description] );
The assert
statement evaluates the specified condition. If the condition is
false
, an error message is logged into the game console and the script that
contains the failed assert statement is terminated. The error message will
contain the full path to the source file that contains the failed assert
statement, along with the line and column positions. An optional description
may be included in the error message.
script "Main" open {
enum { A, B, C } d = C;
switch ( d ) {
case A:
case B:
break;
default:
assert( 0, "missing case" );
}
}
The static assert
statement executes at compile time. If the condition is
false
, the compiler outputs an error message and aborts compilation.
For functions that take a message argument, functions like Print()
,
message-building blocks allow you to dynamically create the message:
select what text will form the message, in what order, and in what quantity.
Message-building blocks offer more flexibility than specifying a sequence
of comma-separated message items.
A message-building block begins with the buildmsg
keyword, followed by an
expression between parentheses, and ends with a block, which is called the body of a
message-building block:
script "Main" open {
buildmsg ( Print() ) {
Append( s: "abc", d: 123, c: '!' );
}
// Output: abc123!
}
A message-building block evaluates its expression. The expression should contain calls
to Print()
-like functions. For a call to actually use a message-building block, the call must not
have a message argument. The body of a message-building block is executed for every call that uses
the message-building block.
In the body of a message-building block, a special function called Append()
becomes visible.
You use Append()
to output the content of the message. Append()
supports all of the cast
types that are supported by Print()
.
The following example is a little more interesting. In this example, a border is drawn below a message:
script "Main" open {
buildmsg ( Print() ) {
str text = "Message-building blocks are awesome!";
Append( s: text, c: '\n' );
for ( let int i = 0; i < StrLen( text ); ++i ) {
Append( c: '*' );
}
}
// Output: Message-building blocks are awesome!
// ************************************
}
For functions that take arguments after the message argument, functions like HudMessage()
, the
semicolon (;
) that separates the message argument from the rest of the arguments must not be specified:
#include "zcommon.h"
script "Main" open {
buildmsg ( HudMessage( HUDMSG_PLAIN, 1, CR_BLUE, 1.5, 0.5, 5.0 ) ) {
Append( s: "abc", d: 123, c: '!' );
}
// Output: abc123!
}
The following example shows how to use StrParam()
with a message-building block:
script "Main" open {
str s;
buildmsg ( s = StrParam() ) {
Append( s: "abc", d: 123, c: '!' );
}
// `s` now contains the string "123abc!"
}
A message-building block can be combined with a return statement. The value returned is the result of the expression:
str CreateMessage() {
return buildmsg ( StrParam() ) {
Append( s: "abc", d: 123, c: '!' );
}
}
script "Main" open {
Print( s: CreateMessage() );
// Output: 123abc!
}