Skip to content

Statements

Positron edited this page Aug 8, 2017 · 5 revisions

Variable Declaration as Condition

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 Loop

Syntax
foreach ( value ; collection ) {}
foreach ( key , value ; collection ) {}
foreach ( key ; value ; collection ) {}
Description

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

Syntax
goto label ;
label :
Description

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
}

Assertions

Syntax
assert ( condition [, description] );
static assert ( condition [, description] );
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.

Message-building Blocks

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!
}