Scripting API

Home Scripting API Index

The Basics



Class Files

A script is made up of at least one main text file with the .nlvm file extension. 'nlvm' stands for NoLimits Virtual Machine. The script can be split up into multiple files. Each file holds exactly one class. A class is a specific type of programming module in object oriented programming languages. Node that the explanation of object oriented programming concepts is beyound the scope of this document. Each class needs to have a name and the file name must be identical with the class name. The name needs to follow Identifier Restrictions. It is recommended but not required to start the name of a class using an uppercase letter and use camelcases (simulate spaces using upper case characeters) within the name. The main class of a script contains the starting point code of a script, it can make use of other classes, either custom classes or internal classes as part of the API.

Example:

Class name: MySuperCoolClass
File name: MySuperCoolClass.nlvm



NL2Script Description Files

Scripts can be assigned to custom scene objects inside the NL2SCO Editor, or to coasters inside the coaster property dialog, or to custom environments inside the Environment Editor. There are two methods to assign a script, either directly by selecting the main .nlvm class file, or by selecting a script description file (.nl2script). It is recommended to create a script description file using the Script Description Editor when the script should be reused in the future. For specialized or simple scripts, it is sufficent to directly select the .nlvm class file. Node that plugins for the editor require a script description file.


Classpaths

The classpath is the uppermost folder of all class files used by the script. If left empty, the classpath will be assumed to be identical to the folder of the main class.


Packages

Class files can be organized into optional packages, which are identical to folders in the file hierarchy. Each package is represented by a folder and optional class files inside. Also it is possible to have packages inside packages. The name of a package must follow Identifier Restrictions. Files that are stored on top level are assumed to be in the root package. The root package has no name. Inside the class files, packages that are inside packages are separated by dots '.'.

Here is an example without packages:

Classpath: 'c:\my script files'
Main class: 'MyCoolScript'
File path of main class: 'c:\my script files\MyCoolScript.nlvm'

Here is an example with the main class inside a single package:

Classpath: 'c:\my script files'
Package: 'mypackage'
Main class: 'mypackage.MyCoolScript'
File path of main class: 'c:\my script files\mypackage\MyCoolScript.nlvm'



Play Mode and Editor Mode

There a differences between scripts designed for Play Mode and Editor Mode. Editor Mode scripts can only be used as editor plugins and can only access the editor API. Play Mode scripts have access to the simulator API only.


Hello World Examples

File name: HelloWorldPlay.nlvm
public class HelloWorldPlay extends com.nolimitscoaster.Script
{
  public bool onInit()
  {
    System.out.println("Hello World");
    return false;
  }
}
Hello World in Play Mode (displays to the message window)


File name: HelloWorldEditor.nlvm
public class HelloWorldEditor
{
  public static void main()
  {
    System.out.println("Hello World");
  }
}
Hello World in Editor Mode (displays to the message window)



Scripts Designed for Play Mode

Most objects (e.g. scene object instances, coasters, track triggers) are called 'Entities' inside the Play Mode and they are identified using a so called Entity ID. It is represented by a value of type int. Some entities can have child entities. Even a script is an entity and has its own ID. A script that is attached to a scene object, will be a child entity of the scene object instance. The scene object instance will be the parent entity of the script entity. The same applies to scripts attached to coasters. The script will be the child entity of the coaster entity, which represents the coaster in Play Mode.

Scripts that are designed for Play Mode need to implement the following:

The main class needs to inherit from the com.nolimitscoaster.Script class using the extends directive:

public class MyScript extends com.nolimitscoaster.Script
{
  ...
}

We recommend to use an import directive to abbreviate full class names...

import com.nolimitscoaster.*;

public class MyScript extends Script
{
  ...
}


There are three methods declared in the com.nolimitscoaster.Script class that can be overridden:

The public bool onInit() method will be called at park loading time. The script can do initialization in here. The returned value will decide if the initialization was successful and if the script should continue to run (true) or if the script should exit (false) after initialization.

The public void onNextFrame(float tick) method will be called for each frame that will be computed when the onInit method previously returned true. The tick parameter represents the simulation delta time (in seconds) since the last frame. It can be used for animations etc.

The public void onDeinit() method will be called when the play mode ends. Typically the engine will automatically clean up all resources created by the script, so there is not much to do in here in the current version. Maybe in the future it might be used to close file handles etc.

The sim field of the com.nolimitscoaster.Script class can be used to access the simulator API.

Typically the script will want to get a reference to its parent entity (either scene object instance or coaster) inside the onInit() method, so that it can modify (e.g. animate) this object inside the onNextFrame() method later on.


Scripts Attached to Scene Objects (NL2SCO Files) in Play Mode

A short example of a script designed for scene objects:

import com.nolimitscoaster.*;

public class DemoScript extends Script
{
  // Reference to the scene object instance
  private SceneObject sco;

  // Variable to sum up the total simulation time
  private float totalTime;

  public bool onInit()
  {
    // Get the entity ID of the scene object instance this script is attached to...
    int parentID = getParentEntityId();

    // Get a reference to the scene object instance
    sco = sim.getSceneObjectForEntityId(parentID);

    if (sco == null)
    {
      // Something is wrong, most likely this script is not attached to a scene object
      return false;
    }

    // Everything fine
    return true;
  }

  public void onNextFrame(float tick)
  {
    // Demonstrate some animation by rotating the object...

    totalTime += tick;

    sco.setRotation(0, totalTime, 0);
  }
}
This script will rotate the scene object instance with a constant speed



Scripts Attached to Coasters in Play Mode

Scripts that are attached to coasters, will typically get a reference to the coaster inside the onInit() method...

import com.nolimitscoaster.*;

public class DemoScript extends Script
{
  // Reference to the coaster
  private Coaster coaster;

  public bool onInit()
  {
    // Get the entity ID of the coaster this script is attached to...
    int parentID = getParentEntityId();

    // Get a reference to the scene object instance
    coaster = sim.getCoasterForEntityId(parentID);

    if (coaster == null)
    {
      // Something is wrong, most likely this script is not attached to a coaster
      return false;
    }

    // Everything fine
    return true;
  }

  public void onNextFrame(float tick)
  {
    //...
  }
}