Trainz/Scenarios (Scripted Activities)

From Wikibooks, open books for an open world
Jump to: navigation, search
logo
Fundamentals for Trainz Trainees
Trainz | Introductory Trainz  | Trainz AM&C | Creation | Appendixes  |  References  • Containers • Kinds • Tags • Index • Grps • Vers
 Glossary
 HKeys-CM
 HKeys-DVR
 HKeys-SUR
 HKeys-WIN
 Mouse use
 Notations
Trainz-scenarios will be an unsupported type in Trainz-TANE (forthcoming post-TS12 release expected circa December 2014.

Scenario Introduction[edit]

The first Game-play in Trainz

A scenario in fiction  has a well understood connotation as the circumstances consisting of a backstory and a situation which a protagonist must somehow deal. This broad definition while applicable in the same broad sense in Trainz, actually has two mechanisms of presenting the game-play aspect of Trainz, that is the Gameplay in the software suite: a task which an operator is supposed to perform in a Driver session, a Goal, or Problem. In short a quest with a mission to master. A well written one presents aome kind of scoring of 'Points' to measure your performing self against both a standard, and your own high score. Also well written ones present a clear outline of the task, it's end conditions, and assumes the Driver (Us) knows nothing of the Route/Layout ahead of time. Most fail that criteria. Further, well written ones allow one to reopen the instructions and refresh the memory and compare the names (sometimes odd to the ear) to the minimap labels.

They also present situational modifiers, it was an unforgettable experience to once drive a Freight to a Schedule only to realize a misidentification of where the consist was (resulting in backing down speed considerably for about four or five minutes) required the Driver to play catch-up—but whilst careful to stay below the posted speed limit, the Session writer didn't bother to tell us the rules in that country automatically decrement at certain ranges of speed, meaning a Freight had to stay 10, 15 or 25 mph under the speed posted limit when and if it fell into those range brackets. Like many such problem missions, this one deducted points for speeding. Would you ever forget the experience of bringing the Freight into the final couple of stops on time, completing it and finding your final score was -384 (down from 800+ when last noticed/checked!)

The older of these game-play quest sequences was in fact called a scenario by Auran in 2001-2002 (hereafter called a 'Trainz-scenario'), while the newer mode is called a session. From the standpoint of game-play to the Driver in Trainz there is virtually no difference save one: They show up differently in the Driver menu. From the standpoint of creation of one or the other, the difference is vast.

Trainz-Scenarios are interactive scripted activities for a user to operate in the Trainz Driver GUI module—the most game-like of the varied kinds of entertainment offered by the software system. They invariably have targeted completion goal or state, and many are written to provide scoring allowing a Driver an opportunity to compete with others or best her previous best score. They vary in nature considerably, some providing step-by-step instructions for each stage of an operation (e.g. Tutorials on how to run Trainz), others merely displaying the details of an objective and leaving it to user to devise a method of achieving it. 'Shunting puzzle scenarios', perhaps the most realistic Trainz Driver 'quest' or 'problems' model  'typical Railroad operations'  tend to adopt the latter style. Some 'schedule keeping challenges' follow the terse mode, presenting a single schedule at the start up of a driver situation. A wide variety of different events can be triggered within a Trainz-Scenario. It is possible to display HTML text and images, and to play sounds, add trains 'out of the blue' as traffic (not visible on the map just moments before), or change load states of rolling stock.

In the earliest Trainz, Trainz-Scenarios which are written using TrainzScript.exe, a separate utility no longer shipped as part of releases beginning with TRS2006, the script language based scenario was necessary for filling coal cars or other such loads 'off camera' and so were well suited to mirror the reality of many shortline or yard engine 'switching' operations where the locomotive engines pick up and drop off cars at various locations and return the loaded or unloaded rolling stock to a collection yard or sorting yard where it is appropriately shunted into or taken from a longer regional train. But TRS2004 also introduced interactive industries (in 2003) and the Session editor and driver rules improvements, while still fully supporting the Trainz-Scenario. Versions since might be best considered as 'read-only' implementations where a downloaded Trainz-Scenario can still be played, but not written.

P train grey.png
Trainz Session Rules, are TrainzScript 'modules' that are far more user friendly to the non-programmer, being implemented as a graphical icon, with a limited number of input or output modes.

Trainz-Scenarios were introduced with the release of Service Pack 3 to the original Trainz release as well as in Trainz UTC, and are one of the main improvements that make many veteran Trainzers consider that Trainz 1.3 version a second separate major release. Scenarios were fully supported in TRS2004, as an alternative back-compatible mode of scripting activities … even as the release introduced the new more generalized Sessions'. They are only partially supported in TRS2006 and Trainz Classics through the newest Trainz Trainz 2012, meaning existing sessions will (usually) still run if imported or downloaded, but the TrainzScript software utility has neither been updated and has not been bundled as part of those newer releases because the 'Session' is more flexible, and can do everything the older Trainz-Scenario technology could do. In other words (compare above vs scenario): "Trainz-Sessions are interactive scripted activities for a user to operate in the Trainz Driver GUI module—the most game-like of the varied kinds of entertainment offered by the software system".

Some Methods Of Creating Scenarios[edit]

  • TRS2004 owners can use the built-in method of creating the initial structure of a scenario, then using a text editor program to write the necessary coding. This method involves programming in GameScript, which is a "C"-like language with numerous extensions.
  • Both TRS2004 and TRS2006 owners can use the SCS (Scenario Creation System) program which is offered as freeware by the Trainz Pro Routes third-party Trainz fansite. There are separate versions of SCS for TRS2004 and TRS2006. SCS aims to make the scenario creation process as straightforward as possible but even then some considerable effort will be required. Full manuals are available for SCS.
This Trainz page is dated or in need of reorganization and improvement, and as such has been listed for Clean-up as soon as we can get around to it. It has been listed at Category:Trainz pages needing attention, and we apologize for any inconvenience you may incur because our vlunteer staff hasn't found time to make it better. To do:
See if can be updated, and link, or decide if should be placed as 'dated' in the Appendices.


An Overview Of TRS2004 Scenario Creation[edit]

The GameScript API (Application Programming Interface) documentation can be found in the "Trainz Railroad Simulator 2004 User Activity Creation Guide" which can be downloaded from Auran's web site. Some familiarity with the concepts and individual functions listed in this document is vital.

The following is a highly simplified overview of what is inherently quite a complicated procedure. To keep things as simple as possible, it omits many details.

Open the relevant layout in Surveyor.

Add any desired trackmarks, triggers and other trackside objects. Trains can be created at trackmarks. Events will be triggered when trains enter triggers. Do not save the changes to the layout.

In the Surveyor menu, invoke the "Export Scene Data" option and choose a suitable name for the new scenario.

Close Surveyor. Once again, do not save the changes to the layout.

A new folder will have been created in C:\Program Files\Auran\TRS2004\World\Custom\scenarios folder with the name that you specified in Surveyor. This newly created folder will contain the files which form the basis for the scenario.

The TSO (trackside object) file contains the details of the modifications to the layout which are individual to this scenario, for example the additional trackmarks and triggers that you added in Surveyor.

Using a text editor, open the scenario's config.txt file. The kuid-table will already include the layout. You need to add the rolling stock assets that the scenario uses, for example: (How!!!)

kuid-table
	{
	testscenario		<kuid:154110:5701376>
	AN_830_Class		<kuid:-1:100737>
	QR_QLX			<kuid:-1:101154>
	}

If you wish, also embellish the description text.

Using a text editor, open the gs (GameScript) file. By default this file contains a daunting amount of coding, almost all of which should be left unmodified. You need to add additional sections of code in the correct places.

In the "create consist specs" section, add coding to specify the rolling stock which makes up each train when it is initially placed on the layout. The following example has one train consisting of an AN830 Class loco pulling one QLX louvre wagon:

KUID[] PlayerTrainKuids = new KUID[ 2 ];
PlayerTrainKuids[ 0 ] = World.FindKUID( "AN_830_Class" );
PlayerTrainKuids[ 1 ] = World.FindKUID("QR_QLX" );

In the "create consists" section, add coding to place the trains at trackmarks. The following example places a train made up of the "PlayerTrainKuids" consist specification at a trackmark named TM01:

Train PlayerTrain = World.CreateTrain( PlayerTrainKuids, "TM01", true );

In the "gameplay" section, above the "scenarioDone = true;" line, add coding to set some initial parameters and perform the scenario's actions. The following is a very simple example which merely allows the user to drive the PlayerTrain and nothing else.

World.SetGameTimeRate( World.TIME_RATE_1X );
World.SetGameTime( 0.875 );	// 9am
World.SetWeather( World.WEATHER_TYPE_CLEAR, World.WEATHER_CHANGEABILITY_NONE );
World.SetCamera( PlayerTrain, World.CAMERA_EXTERNAL );
World.SetCameraAngle( 75, -15, 50 );
PlayerTrain.SetAutopilotMode( Train.CONTROL_MANUAL );
 
while( 1 == 1 )
	{
	Sleep( 0.1 );
	}

In the above example the "while" loop will wait forever until the user exits the scenario. A real scenario would normally complete properly and shut down without user intervention being required.

No compilation is required. Once the gs file is correctly created, the scenario can be run. In practice, there is usually a need for numerous iterations around the editing and testing cycle.

Comparisons to programming languages[edit]

Some Comments Regarding GameScript For People Familiar With Traditional BASIC or Visual BASIC

A few simple examples can be found at the end of this section.

The following applies to GameScript as used to create TRS2004 scenarios. Its use in scriptlets, scripted assets, etc is different in some important respects to what follows here.

For anyone familiar with any form of BASIC, learning GameScript will probably prove quite difficult. This section attempts to list some of the "gotchas" that may confuse beginners.

GameScript does not have a dedicated program editor or IDE (integrated developement environment). Instead, a text editor program such as Notepad or a superior alternative is used to edit programs.

In GameScript, entities such as trains, signals, junctions, etc are regarded as being objects with properties that can be specified and accessed by the program.

GameScript is based on the "C" language. "C" has numerous differences to BASIC, for example:

  • In GameScript, all the coding is held in one file. Because there is no integrated development environment, all the parts of the code are visible when editing.
  • Variables must be declared. They can be declared when first given a value if desired; the syntax is to specify the variable type (int, float, etc), then its name, then a equals sign, then an expression which gives the variable its initial value.
  • The syntax for declaring arrays will seem very strange to BASIC programmers. See the example below.
  • Comment lines start with two forward slashes.
  • Array subscripts are enclosed in square brackets, not round brackets.
  • Groups of dependent statements are enclosed in matching pairs of curly brackets. These include groups of statements in FOR loops, in WHILE loops, and in IF statements. Therefore there are no NEXT, WEND or ENDIF statements in "C".
  • Most statements must have a semi-colon on the end, but not all. Examples of statements which must not have semi-colons include:
    • case
    • default
    • FOR loop headers, WHILE loop headers and IF statement headers where the dependent statements that follow are enclosed in curly brackets.
    • include
    • switch
    • function definition header lines
    • labels (targets for goto statements)
  • Most operations are performed using functions, or statements which have the same syntax as functions. Therefore in many cases parameters must be enclosed in round brackets where none are required in BASIC.
  • Assignment statements take one equals sign, relational expressions in IF statements take two equals signs. Not equals is !=
  • "C" features a large number of obscure methods of incrementing and decrementing variables using two adjacent arithmetical operators. Since these are difficult to remember and therefore open to confusion, they are probably best avoided by beginners. The difference in performance caused by not using these methods is trivial in the extreme compared to the millions of calculations required to generate each screen frame in Trainz.
  • Instead of variables being converted from one type to another with functions such as STR$ and NUM, or automatically as in Visual BASIC, in "C" the <cast> statement is used.
  • Unlike Visual BASIC, GameScript is not inherently event driven. There is no concept of "click on this object to run this little bit of code". However, event handlers (sections of code which are obeyed when an event occurs) can be created. These are particularly useful for handling AI train events, in situations where they can occur asynchronously with the scenario processing and the user's actions. However, GameScript also has the Schedule mechanism for controlling AI trains independently of scenario execution.
  • A function prefixed with the word void does not return a value.
  • In Auran's API documentation, a function with the parameter ( void ) does not take a parameter, but does require the empty pair of round brackets.
  • "C" does not have an exponentiation operator.
  • GameScript uses and and or in complex relational expressions, in the same way as in BASIC. Normal "C" is different. Bitwise Boolean operations are possible but probably best ignored by beginners.
  • GameScript uses true and false for literal Boolean values.
  • GameScript uses + for string concatenation, in the same way as BASIC.
  • Whereas Visual BASIC consistently uses the Object.Property syntax, GameScript only does so to a limited extent. GameScript uses the SetOfFunctions.SpecificFunction syntax extensively (possibly universally). In GameScript, in most cases a property of an object must be specified using a function whose name starts with Set..., and a property of an object must be obtained using a function whose name starts with Get...
  • Whereas in Visual BASIC it is vital to regularly perform a DoEvents statement so as to refresh the screen and prevent Windows locking up, in GameScript there is only a general fairly obvious need to avoid tight loops and insert Sleep functions in such situations. GameScript functions which pause scenario execution while waiting for an event will not lock up Trainz or Windows.
  • Some of the functions in GameScript can take a varying number of parameters, usually with the omitted parameters being given sensible default values.
  • Some of the functions in GameScript operate differently depending on the variable type of the parameters they are supplied with. For example, the function for specifying the camera angles regards its parameters as being in degrees if they are integers but in radians if they are floating point.

As with Visual BASIC, for the beginner there is considerable confusion regarding which aspects are handled by the operating system or the programming language, and which must be handled by the programmer. In Trainz there are the additional complicating possibilities of the user's train and AI trains performing train movements asynchronously with the scenario.

  • Windows and Trainz handle all the hardware aspects of input and output.
  • Trainz will automatically call the main() section of the program when the scenario starts.
  • Once the user's train has been created and control given the user, the user can drive it forwards or backwards as they desire. The scenario needs to react as events occur, such as the user's train entering a trigger or a junction.
  • Trainz will automatically call some other sections of the program when a user train overspeed event occurs, when a collision event occurs, etc. The default coding to handle these events is created when a new scenario is created but with sufficient knowledge it can be modified.
  • There are functions available in GameScript to pause scenario execution at a point in the coding until an event occurs, such as the user's train entering a junction or a trigger.

As with Visual BASIC, in addition to the relatively straightforward core language there is also a need to learn the vast number of objects, their properties and their functions. These are documented in the Auran GameScript API.

An important practical comment: in the Auran GameScript API document, a pair of matching adjacent square brackets may be displayed so closely together as to appear to be an outline box.

In Trainz, objects internally pass messages between themselves. These internal messages are not seen by the user. GameScript coding can generate internal messages and also detect and receive internal messages. Each internal message has four properties: its source, its destination, its major (i.e. its major message type) and its minor (i.e. its minor message type). While this message passing concept can be ignored by the beginner, it is often featured in the Auran documentation and therefore worthy of mention here.

One final vital piece of advice: start with something really, really simple. Making a train appear on a track is in itself a very considerable achievement for someone starting to learn GameScript.

Example #1: IF Statement

//Equivalent to IF A=10 THEN...
if (a==10)
	{
	//dependent statements go here
	}

Example #2: FOR Loop

// Equivalent to FOR N=1 TO 5 STEP 1
for (n=1; n<=5; n=n+1)
	{
	//statements within the loop go here
	}

Example #3: WHILE Loop

while (a<50)
	{
	//statements within the loop go here
	}

Example #4: Variable declaration and initialisation

int x=8;

Example #5: Declare an array

//Equivalent to DIM A(12) - possible subscript values will run from 0 to 12
float[] A = new float[ 13 ];

Example #6: Define a user-defined function

int Cube(x)
	{
	//local variable declarations go here
	//function statements go here
	return (x*x*x);
	}