Signal Debugging

Introduction

When you're scripting a signal, particularly if it's as complex as the ones referenced in the Advanced Signal Scripting section, it's often useful to be able to see exactly what your script is doing in the game to ensure that it's behaving as you expected it to.

Using Logmate

The tool used to get that information from the signal scripts while the game is running is called LogMate. You can activate LogMate by right-clicking on Train Simulator in your Steam Game Library and select Properties and then click on Set Launch Options, adding the following text into the text entry box:

-LogMate -SetLogFilters="Script Manager"

When you next start up Train Simulator it will automatically launch LogMate, and enable its script debug channel. Any error messages generated by your scripts (for example, if the game code tries to call a function that doesn't exist in your script) will appear in LogMate.

Debug Messages

To get more useful information from scripts, you can add debug messages to them. For example, say you want to know which line is connected when the OnJunctionStateChange function runs. You can do this by adding the following line to the end of the function:

Print( ( "DEBUG: OnJunctionStateChange - connected link = " .. gConnectedLink ) )

The Print function prints whatever you put inside its brackets in LogMate's script channel. In this case, you are outputting the name of the function and the value of gConnectedLink. Anything inside the brackets is displayed in LogMate exactly as you typed it. The .. after that tells the Print function to add whatever comes next to the end of the preceding text - this is called "concatenation".

Notice that there are two pairs of brackets around the text you are outputting - this is necessary when you are creating a message by concatenating two or more pieces of text. If you were just outputting a simple preset string (for example, "Hello world"), you would only need one pair of brackets.

In this case, concatenation adds gConnectedLink to the end of your message. Because it is outside of quote marks, this doesn't output "gConnectedLink" - it outputs the current value of the variable gConnectedLink. So if link 1 is now connected, the message that appears in LogMate would look like this:

DEBUG: OnJunctionStateChange - connected link = 1

Or, to be more precise, it would look something like this -

Trace C:\Dev\RailSim\Code\DLLs\ScriptManager\cScriptState.cpp : 734 = ID: railnetwork\signals\uk semaphore\lattice_posts\b lattice combsig_hd 2t.xml long: -2.376435, lat: 51.382504 DEBUG: OnJunctionStateChange - connected link = 1

Don't worry about the "trace" - the useful information is everything after it says 734. The ID is the filename of the blueprint used by the signal that outputted the message, so you know exactly what type of signal each debug message was generated by. The long and lat give the precise position of the signal in the world, so you can quickly locate the signal that outputted the message. And finally, there's the debug message itself. If you look at the main window of LogMate rather than the Script Manager window, you'll see a time stamp at the start of each line, so you can see when the debug message was outputted.

Debug messages can be incredibly useful and can output a lot of information in a single line. For example, say you want to check if a message is reaching a signal. You can do that by adding this line to the top of that signal's OnSignalMessage function:

Print (("DEBUG: OnSignalMessage - message = " .. message .. ", parameter = " .. parameter .. "direction = " .. direction .. ", linkIndex = " .. linkIndex))

Multiple text strings and variable values are concatenated here. Anything between a pair of quote marks is outputted as is (to make it clearer, that plain text is highlighted in red). For everything else, the game fills in the value of the specified variable. So in this case, the debug output would look something like this:

DEBUG: OnSignalMessage - message = 13, parameter = , direction = 1, linkIndex = 1

If you look up this message value in Common Signal Script.lua, you'll find that message 13 is SIGNAL_CLEARED. So you know that this signal has received an all-clear from the next signal up the line beyond link 1.

This kind of information can be incredibly useful when you're trying to figure out why a signal isn't working as you expected it to. However, outputting lots of Print messages to LogMate slows the game down, so you may not want to leave them in. On the other hand, going through your scripts and commenting out all your debug messages, and then having to comment them back in again if you want to do some more debugging later, can be incredibly tedious. So the Common Signal Script file includes a handy function called DebugPrint. Here's what that looks like:

function DebugPrint( message )
     if (DEBUG) then
          Print( message )
     end
end

All this does is check a global variable called DEBUG. If DEBUG is true, the message is Printed. If DEBUG is false, it isn't. You can now switch your script's debug output on and off simply by changing the value of the DEBUG variable in your script and re-exporting it.

If you look at the signal scripts, you'll see that they contain a lot of DebugPrints, so that you can see exactly what the signal is doing at each step of every function - which link is connected, how many trains are in its occupancy table, which messages it's receiving etc. All of that information can be accessed simply by setting DEBUG to true in the script of the signal type(s) you want to check.

Signal Validation Tool

If your signal isn't working, it isn't necessarily a problem with the signal script - it could be the way the signal has been placed in the route. Luckily some of the most common errors can be picked up by the Signal Validation Tool. To activate the SVT, add the following to the launch options for Train Simulator:

-ValidateSignals

You'll also need to modify the log filters to allow the SVT output to appear in LogMate:

-SetLogFilters="Script Manager,Signals"

The next time you run the game, it will search through all the signals in whatever route you load and check that their links are correctly placed. If everything is correct, you won't get any output in LogMate. But if it finds anything it suspects might be an error, it will output a message in the Signals window in LogMate.

These are the errors that the SVT outputs:

Signal link found when junction expected

The SVT searched forwards from the signal's link 0 and found another link beyond it with no junction between them. Occasionally this is intentional, but usually, it means the link it mentions needs to be moved a bit further out. The error also tells you the longitude and latitude of the link that it thinks is misplaced.

If you want to be sure that your link is in the right place you can check it by clicking on the Linear Object Tool icon in the editor. When you do this, all the junctions in the game will be indicated by red triangles.

1 unprotected exit: 1 routes found from...

The SVT searched forwards from one of the signal's links and found a line which doesn't have another link belonging to that signal on it. The error message tells you which link the unprotected line was found beyond, and the longitude and latitude of that link.

Sometimes this is intentional. For example, you may not have put a link on that route because you don't want trains going in this direction to ever go down that line (for example, if the line is abandoned or is only for trains going in the other direction). And occasionally this error seems to pop up when there's nothing obviously wrong with the link placement. But it's always worth checking them out, to be safe.

Unprotected junction

The SVT found a junction that doesn't appear to be protected by a signal. The first longitude and latitude is the position of the junction that's unprotected. The second set of coordinates is the position of the signal link which the junction is beyond. You often get a lot of these in a route, and a single missing or misplaced link can result in several unprotected junction errors for the same signal.

As with the unprotected exit error though, this isn't always a problem - the junction might be on a route that you don't want to put a link on. But it's usually worth quickly checking through these errors, in case one of them is a genuine issue.