Sometimes you have a .GeoPcDx file and you want to write a script for it. If you deal with default signals, your starting point will be the default scripts. But there is also the following method.
You copy the .GeoPcDx to a safe place outside the RW folder hierarchy.
Append .bin to the extension.
Apply serz.exe to it, creating a file with .GeoPcDx.xml at the end.
View it using Notepad or any other editor.
Search for transformname, you will see something like this:
<transformname>
<e type="cDeltaString">Mod_hd_3asp</e>
<e type="cDeltaString">Mod_hd3_Red</e>
<e type="cDeltaString">Mod_hd3_green</e>
<e type="cDeltaString">Mod_hd3_orange</e>
</transformname>
Clearly, you need to use you imagination to guess what is what, and clearly, it is not such a challenge.
You can use RW-Tools for the conversion, I believe.
In the above example,
Call ( "ActivateNode", "Mod_hd3_Red", 0)
will switch off the red light.
Showing posts with label RW Signals. Show all posts
Showing posts with label RW Signals. Show all posts
Cloning a signal
Since this gets asked so often, here is my base recipe to signal adaptation. The basic idea is to make a copy of a signal, and of the associated Lua script, so you are free to modify it without influencing default content.
Major uses are modifications of aspects, adding links, adding yard entries, changing the way a signal clears for the train, etc. etc.
Be sure to put a backup of the files in a safe place. Since your copy still lives in the Kuju folder, it may or may not look like default stuff to Steam and get lost on some update in the future.
You can as well transfer the copies into another folder, under your Provider and Product name, but you need to take care about changing the references in the .bin file. Basically, this is just the path part of the script name. It is not hard to do, but make this changes only after you established that the basic cloning process worked well.
Major uses are modifications of aspects, adding links, adding yard entries, changing the way a signal clears for the train, etc. etc.
- Locate a signal that comes close to what you want.
- Find the .bin file under Assets\Kuju\RailSimulator\RailNetwork\signals.
- Make a copy of this file and give it a meaningful name, e.g., by appending "new" to the name.
- Open it in RW-Tools or apply serz.exe to convert it to .xml.
- Append "new" or similar to all the names in the various languages.
- Find <_script> a bit down the file. The second line after that contains the name of the Lua script which needs to be duplicated, too. Note the name, then append "new" or similar. In case the name has an extension (.lua), you need to insert the "new" before that, of course.
- Save and close the file. If you used serz.exe before, you use it on the .xml now to create the corresponding .bin.
- Find the Lua file referenced above and duplicate it. Append "new" or whatever you appended in the .bin file, to make the file name look exactly like it is in the .bin file.
- Open the Lua file and edit it in which ever way you wish. This strongly depends on what you want and can be any of a dozen small modifications, to be discussed separately.
- Save and close the Lua file.
- Start RW. You should find the "new" version next to the original.
Be sure to put a backup of the files in a safe place. Since your copy still lives in the Kuju folder, it may or may not look like default stuff to Steam and get lost on some update in the future.
You can as well transfer the copies into another folder, under your Provider and Product name, but you need to take care about changing the references in the .bin file. Basically, this is just the path part of the script name. It is not hard to do, but make this changes only after you established that the basic cloning process worked well.
Quick guide to your first signal
I recently beat up a terse (by my standards) guide to getting a simple signal into RW, which now has been validated.
http://forums.uktrainsim.com/viewtopic.php?f=309&t=104090
I link to the forum so you have the context and understand the example. Clearly, the recipe works for many light configurations. The only thing your signal must have is 3 aspects: "stop", "expect stop at next signa"l and "clear here and no stop at next signal".
The thread also contains some discussion on the graphical aspects, including the light glow. Discussion on that is still going on as I write this, but scripting issues are all settled.
http://forums.uktrainsim.com/viewtopic.php?f=309&t=104090
I link to the forum so you have the context and understand the example. Clearly, the recipe works for many light configurations. The only thing your signal must have is 3 aspects: "stop", "expect stop at next signa"l and "clear here and no stop at next signal".
The thread also contains some discussion on the graphical aspects, including the light glow. Discussion on that is still going on as I write this, but scripting issues are all settled.
Messages sent to signals on coupling
I just found out that the track occupation management of the game must have improved at some point in the past, without leaving any trace in any documentation.
On game start-up, “initialise to blocked” is sent once per consist, which means that a signal protecting 3 groups of wagons gets 3 messages.
When you couple up wagons, all the signals which protected that group and the train coupling to it first get an "occupation decrement" message from the system, faking their exit from the block. Then, all the signals protecting the joint train get an "occupation increment" message, faking their entry into the block from the far side.
Track links currently under one of the involved vehicles get the message with parameter "DoNotForward", which means that this message is just for that link, in contrast to the normal messages which need to be forwarded on remote links (numbered 1 and bigger).
These things put together mean that occupation management by the default scripts is far better than it seems by looking at scripts and documentation. Not only is the system aware of multiple groups of wagons on the same track initially, it also does the right thing in the advent of coupling and uncoupling by magically increasing and decreasing the consist count correctly.
The fact that also driverless consists send the "prepare for train" message is a little let-down as I see it currently, because it results in even more unnecessarily cleared signals.
On game start-up, “initialise to blocked” is sent once per consist, which means that a signal protecting 3 groups of wagons gets 3 messages.
When you couple up wagons, all the signals which protected that group and the train coupling to it first get an "occupation decrement" message from the system, faking their exit from the block. Then, all the signals protecting the joint train get an "occupation increment" message, faking their entry into the block from the far side.
Track links currently under one of the involved vehicles get the message with parameter "DoNotForward", which means that this message is just for that link, in contrast to the normal messages which need to be forwarded on remote links (numbered 1 and bigger).
These things put together mean that occupation management by the default scripts is far better than it seems by looking at scripts and documentation. Not only is the system aware of multiple groups of wagons on the same track initially, it also does the right thing in the advent of coupling and uncoupling by magically increasing and decreasing the consist count correctly.
The fact that also driverless consists send the "prepare for train" message is a little let-down as I see it currently, because it results in even more unnecessarily cleared signals.
Signals and their interaction with the game
I has been said before that signals are route decorations. In the following, I wrap up their relation to trains, F3 display and map, based on recent tests confirming old knowledge.
Signals' awareness of trains
On game start-up, a message is sent to the next signal ahead of consist, to tell it “prepare for coming train”. Also, for each consist, a message is sent to the next signal on either end saying “initialise to blocked”, meaning “protect this train”.
Note that both messages may end up at signals which are not stopping signals. It is the responsibility of the scripter to pass them on to where they can be acted upon. (For example, distants and AWS ramps cannot protect anything on their own.)
Signals' awareness of editing
When you enter scenario editor (not just world editor), all signals receive message 0 - RESET_SIGNAL_STATE. After that, they receive the same messages as after game start-up. On exiting the scenario editor, the same thing happens again.
In contrast, on game start-up, function Initialise is called very early and the above messages are then received.
This means, that signal scripts should call Initialise when they receive the RESET_SIGNAL_STATE message. This was the case for KRS, but for RW, the call was commented out and I have not got around why. Maybe because it only cures half of the problem as explained in the next paragraph.
The bad new is that in route editing mode in world editor, you can move around signals and their links (and also add and remove some) and in this case, the signals are not reset. Therefore, even with careful programming, the signals cannot adapt to the new situation after this type of modification.
F3 and map
Signals explicitly set the colour to show in the map, choosing from red, yellow, green and invisible without any requirement to correlate this with the aspect shown by the 3D shape.
The F3 display shows the same colour. For invisible signals, it shows the colour of the next signal and on also the distance to that one. Only signals classified as stop signals in the blueprint are considered here.
The distance shown in F3 refers to link 0 while the position shown in the map is that of the signal shape.
Player trains and signals
Signals may send messages to trains within 100m of their links. Note that there is no need to synchronise them with an aspect shown. For example, the TPWS ramp does not show any aspect but sends nasty messages.
I am pretty certain that when the player hits TAB, the request goes to the dispatcher who decides whether he would run an AI train into the next block, and this determines acception or denial of passing the signal at red. For sure, the signals (currently) are not even informed about the whole action, let alone asked.
AIs awareness of signals and trains
AI organises the route in blocks delimited by the link 0s or the stop signals. It only sees engines with driver icons. If one of them is inside a block, no AI train will go there, even if that engine would be located well behind the final target of the AI train.
AI trains do not receive messages sent by signals. They are not bothered by anything else the signals do, either.
As a consequence, on a correctly signalled route, signals will protect wagons and unmanned engines against player trains, but AI will plough through.
On a balance, you will not be able to lure AI into an occupied track by call-on signals and the like. You need to insert an invisible block signal beyond the marker where you want the AI to go.
Interestingly enough, this is only for the direction of the AI train. If you put a train just behind the signal for the AI, up to which it goes, this other train could proceed to the destination place of the AI train without violating any signal. But AI does not care about such issues.
One thing it worries about is when another train is straddling a link of a junction signal which the AI has to pass. Then, the AI train slows down and as soon as it passed link 0 of that junction, it speeds up again. Move the other train off the link, but still not separated by any signal from where it could collide with the AI train, and the AI does not hesitate anymore.
The AI ignores the signals, what should I do?
Despite all the frustrating signals I made above, I must say that a big number of signals would actually work in practice, if they were the right versions in the right place, had their links set up correctly and if the game was reloaded after modifications of route or scenario.
So, if you find a signal still shows a stop aspect while the AI train passes it, and if this signal is meant to be a bog standard signal, no permissive stop or call-on or approach from red, check the following.
From link 0, follow the route of the train to the next stop signal.
(*) It is pretty like that the route is set for AI trains, but at least for player trains, automatic trailing switches set against them do not end the game, but certainly they do cause the signal protecting them to show stop. So maybe there are situations in which you can change some switch before an AI train without the dispatcher setting it back immediately (or locking it in the first place). I only did one experiments and there, the dispatcher always set it back whenever I set it for my train.
Note: Modified sentence on Prepare For Train (message is also sent for driverless consists).
See also this follow up.
Signals' awareness of trains
On game start-up, a message is sent to the next signal ahead of consist, to tell it “prepare for coming train”. Also, for each consist, a message is sent to the next signal on either end saying “initialise to blocked”, meaning “protect this train”.
Note that both messages may end up at signals which are not stopping signals. It is the responsibility of the scripter to pass them on to where they can be acted upon. (For example, distants and AWS ramps cannot protect anything on their own.)
Signals' awareness of editing
When you enter scenario editor (not just world editor), all signals receive message 0 - RESET_SIGNAL_STATE. After that, they receive the same messages as after game start-up. On exiting the scenario editor, the same thing happens again.
In contrast, on game start-up, function Initialise is called very early and the above messages are then received.
This means, that signal scripts should call Initialise when they receive the RESET_SIGNAL_STATE message. This was the case for KRS, but for RW, the call was commented out and I have not got around why. Maybe because it only cures half of the problem as explained in the next paragraph.
The bad new is that in route editing mode in world editor, you can move around signals and their links (and also add and remove some) and in this case, the signals are not reset. Therefore, even with careful programming, the signals cannot adapt to the new situation after this type of modification.
F3 and map
Signals explicitly set the colour to show in the map, choosing from red, yellow, green and invisible without any requirement to correlate this with the aspect shown by the 3D shape.
The F3 display shows the same colour. For invisible signals, it shows the colour of the next signal and on also the distance to that one. Only signals classified as stop signals in the blueprint are considered here.
The distance shown in F3 refers to link 0 while the position shown in the map is that of the signal shape.
Player trains and signals
Signals may send messages to trains within 100m of their links. Note that there is no need to synchronise them with an aspect shown. For example, the TPWS ramp does not show any aspect but sends nasty messages.
I am pretty certain that when the player hits TAB, the request goes to the dispatcher who decides whether he would run an AI train into the next block, and this determines acception or denial of passing the signal at red. For sure, the signals (currently) are not even informed about the whole action, let alone asked.
AIs awareness of signals and trains
AI organises the route in blocks delimited by the link 0s or the stop signals. It only sees engines with driver icons. If one of them is inside a block, no AI train will go there, even if that engine would be located well behind the final target of the AI train.
AI trains do not receive messages sent by signals. They are not bothered by anything else the signals do, either.
As a consequence, on a correctly signalled route, signals will protect wagons and unmanned engines against player trains, but AI will plough through.
On a balance, you will not be able to lure AI into an occupied track by call-on signals and the like. You need to insert an invisible block signal beyond the marker where you want the AI to go.
Interestingly enough, this is only for the direction of the AI train. If you put a train just behind the signal for the AI, up to which it goes, this other train could proceed to the destination place of the AI train without violating any signal. But AI does not care about such issues.
One thing it worries about is when another train is straddling a link of a junction signal which the AI has to pass. Then, the AI train slows down and as soon as it passed link 0 of that junction, it speeds up again. Move the other train off the link, but still not separated by any signal from where it could collide with the AI train, and the AI does not hesitate anymore.
The AI ignores the signals, what should I do?
Despite all the frustrating signals I made above, I must say that a big number of signals would actually work in practice, if they were the right versions in the right place, had their links set up correctly and if the game was reloaded after modifications of route or scenario.
So, if you find a signal still shows a stop aspect while the AI train passes it, and if this signal is meant to be a bog standard signal, no permissive stop or call-on or approach from red, check the following.
From link 0, follow the route of the train to the next stop signal.
- If the signal has several links, then are all the switches between link 0 and the far link through which the train passed set? (*)
- So you find switches or crossings, those should have been protected.
- So you find a consist without a driver, add one or remove the consist. AI limitation, not signal issue.
- So you find a stop signal for the same direction before any of the above, check the XML file of the “bad“ signal to see whether this is classified as stopping signal.
- Did you see the signal work on other occasions (i.e., did you witness all aspects being displayed under plausible circumstances, in another location). If yes, I forgot something on this list. If not, it is time to look into the script. If you are lucky, the name of some light is wrong and the signal died while trying to switch it on or off. Otherwise, err, you are not so lucky.
(*) It is pretty like that the route is set for AI trains, but at least for player trains, automatic trailing switches set against them do not end the game, but certainly they do cause the signal protecting them to show stop. So maybe there are situations in which you can change some switch before an AI train without the dispatcher setting it back immediately (or locking it in the first place). I only did one experiments and there, the dispatcher always set it back whenever I set it for my train.
Note: Modified sentence on Prepare For Train (message is also sent for driverless consists).
See also this follow up.
Sending several values in one message
Until recently, I maintained that modulo nor string functions would work, although Dave told me otherwise. I just did not get around testing it. Now I did and I found that both the string and the integer method work. These are the details:
The string method
You fix the number of digits (or otherwise characters) that every part will occupy. To piece the parameter together, you use the string concatenation operator “..” (two dots). To decompose the parameter by the receiver, you use the substring method.
string.sub(text, first character, last character)
Characters are counted from one. Note that the last argument is the index of the last character to include, not the first one not included nor the length of the substring.
I always add 0 to such terms to make sure that Lua stores them as numbers, not strings. I believe that I had bad results one time from comparing strings containing digits with numbers.
The integer method
After determining the maximum value of each component, you multiply the parts. For simplicity, lets use 99 as a maximum value for A, B, and C. So the parameter is
A * 10000 + B * 100 + C
On the receiving side, you use the modulo operation together with integer division to separate the parts. The way I found to be working in this Lua implementation is this.
A = math.floor( parameter / 10000)
B = math.mod(math.floor( parameter / 100), 100)
C = math.mod(parameter, 100)
In plain text, B is gained by first stripping off the two digits on the right using math.floor and division (because the division alone yields a real number) and then stripping off the two digits on the left by using math.mod.
Comparison
The main limitation of the numeric method is that numbers are represented as 31-bit bases which means that the maximum number you can represent without getting rounding phenomena is 2,000,000,000. If you need more digits, you are better off with the string method.
I believe that the numeric calculations are faster than string operations, but this is just a believe.
I did not test the string formatting function. Instead, I add a number to the result from the numeric method which is just a bit bigger. That way, I can be sure about the string format, with very simple calculation steps. In the above example, I would add 1,000,000, giving 1AABBCC where AA etc are the digits for A etc, so you can always get them by doing
A = string.sub(parameter, 2, 3) + 0
Impact
For the communication from the signals to the engine, this is good news, of course. Now, we need a standardisation body to keep the formats of different contributions compatible.
For the inter-signal communication, I am not so sure of the gain of composite messages over a series of simple messages (with ready-to-use parameters). All I observe regarding timing and delays is that either you run LogMate and accept the occasional hanging, or you don't run it and there is no hanging or jerking.
The string method
You fix the number of digits (or otherwise characters) that every part will occupy. To piece the parameter together, you use the string concatenation operator “..” (two dots). To decompose the parameter by the receiver, you use the substring method.
string.sub(text, first character, last character)
Characters are counted from one. Note that the last argument is the index of the last character to include, not the first one not included nor the length of the substring.
I always add 0 to such terms to make sure that Lua stores them as numbers, not strings. I believe that I had bad results one time from comparing strings containing digits with numbers.
The integer method
After determining the maximum value of each component, you multiply the parts. For simplicity, lets use 99 as a maximum value for A, B, and C. So the parameter is
A * 10000 + B * 100 + C
On the receiving side, you use the modulo operation together with integer division to separate the parts. The way I found to be working in this Lua implementation is this.
A = math.floor( parameter / 10000)
B = math.mod(math.floor( parameter / 100), 100)
C = math.mod(parameter, 100)
In plain text, B is gained by first stripping off the two digits on the right using math.floor and division (because the division alone yields a real number) and then stripping off the two digits on the left by using math.mod.
Comparison
The main limitation of the numeric method is that numbers are represented as 31-bit bases which means that the maximum number you can represent without getting rounding phenomena is 2,000,000,000. If you need more digits, you are better off with the string method.
I believe that the numeric calculations are faster than string operations, but this is just a believe.
I did not test the string formatting function. Instead, I add a number to the result from the numeric method which is just a bit bigger. That way, I can be sure about the string format, with very simple calculation steps. In the above example, I would add 1,000,000, giving 1AABBCC where AA etc are the digits for A etc, so you can always get them by doing
A = string.sub(parameter, 2, 3) + 0
Impact
For the communication from the signals to the engine, this is good news, of course. Now, we need a standardisation body to keep the formats of different contributions compatible.
For the inter-signal communication, I am not so sure of the gain of composite messages over a series of simple messages (with ready-to-use parameters). All I observe regarding timing and delays is that either you run LogMate and accept the occasional hanging, or you don't run it and there is no hanging or jerking.
The dark side of the --include statement, continued
Another nice feature of --include is that the blueprint editor is too stupid to understand dependencies. Normally, if A contains the line
--include=B
and you change B, then A is updated by any decent compiler. However, the blueprint editor only copies over B from the Source folder to the Asset folder and does not compile the file A again, although that contains a now outdated copy of B.
The only workaround is to save A anew even if you did not change it, every time you save B. Pretty boring if you have lots of 'A's, which is the normal situation.
In practice, I debug the file in the Asset folder until I am satisfied (or tired), and then copy it back to the source folder. However, this is risky (click the Export button in the blueprint editor once an your debugging work is lost). And if your project is made up of a set of files, splitting the merged file after debugging is another tedious working step.
The other disadvantage of editing the copy in the Asset folder is that syntax errors lead to program crashes (of KRS or RW). In contrast, if you make an error in the Source folder, the blueprint editor may tell you about it on exporting, if you are lucky.
--include=B
and you change B, then A is updated by any decent compiler. However, the blueprint editor only copies over B from the Source folder to the Asset folder and does not compile the file A again, although that contains a now outdated copy of B.
The only workaround is to save A anew even if you did not change it, every time you save B. Pretty boring if you have lots of 'A's, which is the normal situation.
In practice, I debug the file in the Asset folder until I am satisfied (or tired), and then copy it back to the source folder. However, this is risky (click the Export button in the blueprint editor once an your debugging work is lost). And if your project is made up of a set of files, splitting the merged file after debugging is another tedious working step.
The other disadvantage of editing the copy in the Asset folder is that syntax errors lead to program crashes (of KRS or RW). In contrast, if you make an error in the Source folder, the blueprint editor may tell you about it on exporting, if you are lucky.
How to compose signals
Signals are often made up of components. There are three different ways to implement this in RW. Things to consider are
For the degree of perfection, I mostly think of self-shadowing and support structures for the optional parts. If the signal is all black, you don't worry too much about the shadows, but many countries paint their signals in more or less light grey. For the fingers, there is some chance that two neighbouring ones are mounted together in one panel, which will make a noticeable difference from two separate fingers.
Some people argue that only the front perspective from a moving train would be important. But even if you say you are only driving, you might be driving a shunting engine which might halt near a signal, and certainly it will pass many signals in reverse direction at slow speed. So the shape details of signals are not generally useless.
Regarding the ease of use for the route builder, one has to weigh two different aspects.
Only in bigger teams, the following roles in the creation process need to distinguished.
Ways to implement signal combinations
1) Creation of all combinations in the 3D modelling programme. This has the large advantage that you can achieve perfect appearance by having correct self-shadowing of the combined shape. You can also easily adjust for deviations of certain combinations, like neighbouring fingers being paired.
The disadvantages are that the configuration work is done in the 3D programme, i.e., you need a script running inside this programme to create the combinations (before you apply the fine tuning); and you end up with a long list of items. It is also worth noting that only someone owning the source files of the assets can use this method.
2) Combining the signals in blueprints. You can do this by using the Asset Editor or by writing a little script which creates the combined blueprints. The advantage is that you get the combination work out of the 3D programme. The disadvantage is obviously the combination of no self-shadowing with the bloated signal list.
3) Combination in the world editor. By supplying all signal parts as separate signals in terms of asset categorisation and blueprints, you arrive with 3 + 6 "signals" in the list, of which 6 only make sense as part of another signal. (The fingers make only sense if mounted to heads.)
This vast advantage has to balance a list of disadvantages. There is no self-shadowing. The scripts are bit more complicated since the coordination between the head and the fingers is now performed via messages between them. And most importantly, the user has to perform several placement actions per signal.
This latter problem is eased by the fact that the complex combinations of signals are rare and the simple signals are frequently used. Also, frequent combinations could be implemented as under item 2 above, alongside the freely combinable part library.
Signalling assistants
Clearly, the user needs assistance in all three cases, not only to ease the work, but also to suggest combinations which are prototypical and warn of such which would not be used in the prototype.
In any case, one would define snap points for each signal and specify what could be snapped there. Then, the user only needs to select what to use, and no where to place it (except for deciding between two or three alternative locations, in case there are some).
For (1), such a tool would be implemented in the 3D programme. For (2), a separate tool, maybe with a GUI presenting a preview of the aspect, would create blueprints. For (3), it would modify the tracks.xml file which is difficult. At the same time, this latter case is the only one where the user can be consulted with respect to signal distance, too. In countries with speed signalling and strict rules for signal distance, this is an important aspect. Also, this is the only way to put an end to misplaced links and forgotten paths and switches.
Conclusion
If a signalling scheme knows many combinations, option 3 is the more feasible one, otherwise option 1 provides better look and nearly the same disadvantages as option 2.
Parsing and modifying tracks.xml might seem a bit far out from today, but it is a precondition for more comprehensive route builder support.
- the number of combinations
- the degree of perfection of the signal appearance
- the ease of use for the route builder
- the roles in the creation process.
For the degree of perfection, I mostly think of self-shadowing and support structures for the optional parts. If the signal is all black, you don't worry too much about the shadows, but many countries paint their signals in more or less light grey. For the fingers, there is some chance that two neighbouring ones are mounted together in one panel, which will make a noticeable difference from two separate fingers.
Some people argue that only the front perspective from a moving train would be important. But even if you say you are only driving, you might be driving a shunting engine which might halt near a signal, and certainly it will pass many signals in reverse direction at slow speed. So the shape details of signals are not generally useless.
Regarding the ease of use for the route builder, one has to weigh two different aspects.
- Effort to position the signal combination
- Length of the signal item list
Only in bigger teams, the following roles in the creation process need to distinguished.
- 3D artist creating the shape, knowing enough about signalling to get the shape and the colours right
- Scripter, knowing enough of signalling to get the control logic right
- Configurer, not necessarily a programmer, but someone who knows how to set up a load of configuration files in finite time.
Ways to implement signal combinations
1) Creation of all combinations in the 3D modelling programme. This has the large advantage that you can achieve perfect appearance by having correct self-shadowing of the combined shape. You can also easily adjust for deviations of certain combinations, like neighbouring fingers being paired.
The disadvantages are that the configuration work is done in the 3D programme, i.e., you need a script running inside this programme to create the combinations (before you apply the fine tuning); and you end up with a long list of items. It is also worth noting that only someone owning the source files of the assets can use this method.
2) Combining the signals in blueprints. You can do this by using the Asset Editor or by writing a little script which creates the combined blueprints. The advantage is that you get the combination work out of the 3D programme. The disadvantage is obviously the combination of no self-shadowing with the bloated signal list.
3) Combination in the world editor. By supplying all signal parts as separate signals in terms of asset categorisation and blueprints, you arrive with 3 + 6 "signals" in the list, of which 6 only make sense as part of another signal. (The fingers make only sense if mounted to heads.)
This vast advantage has to balance a list of disadvantages. There is no self-shadowing. The scripts are bit more complicated since the coordination between the head and the fingers is now performed via messages between them. And most importantly, the user has to perform several placement actions per signal.
This latter problem is eased by the fact that the complex combinations of signals are rare and the simple signals are frequently used. Also, frequent combinations could be implemented as under item 2 above, alongside the freely combinable part library.
Signalling assistants
Clearly, the user needs assistance in all three cases, not only to ease the work, but also to suggest combinations which are prototypical and warn of such which would not be used in the prototype.
In any case, one would define snap points for each signal and specify what could be snapped there. Then, the user only needs to select what to use, and no where to place it (except for deciding between two or three alternative locations, in case there are some).
For (1), such a tool would be implemented in the 3D programme. For (2), a separate tool, maybe with a GUI presenting a preview of the aspect, would create blueprints. For (3), it would modify the tracks.xml file which is difficult. At the same time, this latter case is the only one where the user can be consulted with respect to signal distance, too. In countries with speed signalling and strict rules for signal distance, this is an important aspect. Also, this is the only way to put an end to misplaced links and forgotten paths and switches.
Conclusion
If a signalling scheme knows many combinations, option 3 is the more feasible one, otherwise option 1 provides better look and nearly the same disadvantages as option 2.
Parsing and modifying tracks.xml might seem a bit far out from today, but it is a precondition for more comprehensive route builder support.
Signals and speed limits
The Wiki says "Signal scripts can receive speed limit information and make use of it, but they cannot define a speed limit themselves." The more detailed story is this.
Signals cannot alter the track property speed limit (actually a pair of speed limits, for passenger and freight traffic). This speed limit is what you see in the F3 display.
Currently, signals can query the track property speed limit only when the train is no more than 100m from them. Then, it is too late to change the signal aspect, but time is right to query the train speed (they can do that), and compare these two speeds.
Alternatively, a signal can always compare the train speed against some value defined in the script logic (like 40 km/h for German Hp2).
While the signal cannot modify the F3 display, it can send the train a signal (while it is within 100m). This typically is an "overspeed message" which leads to applying the emergency brakes. It will also be communicated as such in the logfile, to contrast it from overrun signals etc.
Showing dynamic speed limits is not a problem by itself. I.e., you can show 70 km/h for one route and 40 km/h for another and nothing for the straight track. But the information what to show needs to be encoded in the signal script which potentially leads to loads of signal variants.
Signals cannot alter the track property speed limit (actually a pair of speed limits, for passenger and freight traffic). This speed limit is what you see in the F3 display.
Currently, signals can query the track property speed limit only when the train is no more than 100m from them. Then, it is too late to change the signal aspect, but time is right to query the train speed (they can do that), and compare these two speeds.
Alternatively, a signal can always compare the train speed against some value defined in the script logic (like 40 km/h for German Hp2).
While the signal cannot modify the F3 display, it can send the train a signal (while it is within 100m). This typically is an "overspeed message" which leads to applying the emergency brakes. It will also be communicated as such in the logfile, to contrast it from overrun signals etc.
Showing dynamic speed limits is not a problem by itself. I.e., you can show 70 km/h for one route and 40 km/h for another and nothing for the straight track. But the information what to show needs to be encoded in the signal script which potentially leads to loads of signal variants.
ERTMS, ECTS, PZB, LZB, etc
The current state in RW is this.
The resulting situation is this.
Pointwise transmission: The default signals implement a simplified version PZB which just implements the momentary speed check, not the continuous one. They also implemented one TPWS which acts as train stop and speed sensor alternately. Dave (davveb at UKTS) is working on some engine scripts to get us further here.
Continuous transmission: No possible, because signal only talk to trains when they are no more than 100m from the track link. This means that if you were determined to have it now, you would need to place transmitter objects every 200m on the route. RSC are positively aware of the issue, and have a very long list of things to do.
Of course, there is nothing like wireless communication at all in RW, such as ERTMS 2 or US dispatching via radio, or UK electronic token systems. This looks to me like a bit more advanced than the continuous trackbound transmission in terms of software redesign (just my guess).
On a sidenote, RSC announced that wagons can have Lua scripts, too, now, but documentation on the API is not yet available.
Whether we end up with an international standard matching ERTMS or whatever these organisations call themselves today depends on whether someone will implement it. An interesting factor here is also standardisation within the community. If RSC insist on squeezing all the information through this one custom message, we will need some community standard like this unified track pieces database for MSTS.
At the same time, our dreams are limited by the fact that merging of routes is not supported in RW, which means that for long, international routes, building them will be a project of its own (maybe reusing scenery items), and this route will have its own signalling, where you can rule out conflicts between implementations by adapting the scripts.
- You can have pointwise transmission of information from track infrastructure ("signals" in RW) to trains.
- You cannot have continuous transmission of information from track infrastructure to trains.
- What you do with the information in the train depends on the engine script.
- There is only one custom message with one parameter for all forms of information transformation from track to train.
- There is no way to transfer information from train to signals (or other track infrastructure).
The resulting situation is this.
Pointwise transmission: The default signals implement a simplified version PZB which just implements the momentary speed check, not the continuous one. They also implemented one TPWS which acts as train stop and speed sensor alternately. Dave (davveb at UKTS) is working on some engine scripts to get us further here.
Continuous transmission: No possible, because signal only talk to trains when they are no more than 100m from the track link. This means that if you were determined to have it now, you would need to place transmitter objects every 200m on the route. RSC are positively aware of the issue, and have a very long list of things to do.
Of course, there is nothing like wireless communication at all in RW, such as ERTMS 2 or US dispatching via radio, or UK electronic token systems. This looks to me like a bit more advanced than the continuous trackbound transmission in terms of software redesign (just my guess).
On a sidenote, RSC announced that wagons can have Lua scripts, too, now, but documentation on the API is not yet available.
Whether we end up with an international standard matching ERTMS or whatever these organisations call themselves today depends on whether someone will implement it. An interesting factor here is also standardisation within the community. If RSC insist on squeezing all the information through this one custom message, we will need some community standard like this unified track pieces database for MSTS.
At the same time, our dreams are limited by the fact that merging of routes is not supported in RW, which means that for long, international routes, building them will be a project of its own (maybe reusing scenery items), and this route will have its own signalling, where you can rule out conflicts between implementations by adapting the scripts.
Hiding signals in the map
Tired of the mess of bulbs in the map? As long as you can decide which signal class is the more important, here is cheap help.
If you give an argument outside the range of 0 to 2 to the system call Set2DMapSignalState, the signal is not shown, simply. 0, 1, 2 are green, yellow, red respectively. I have not found a way to show anything else for a signal. But at least, I know how to hide these bubbles.
Now if you have 3 stop arms of a semaphore (mounted on separate dolls), you could hide those showing red. Then you have yellow for any arm open with distant arm closed, green for any clear with distant arm also announcing clear, or nothing if all arms show stop. This, of course, is a bit sad, but there are some track diagrams that do work like that. There are others that don't, but better no red than a mess.
Even better if you have a main signal and an auxiliary signal like a call-on arm. Then you can work out their roles redictively, like main signal only shows clear, call-on arm show -- well, yellow? -- when open or red.
If you give an argument outside the range of 0 to 2 to the system call Set2DMapSignalState, the signal is not shown, simply. 0, 1, 2 are green, yellow, red respectively. I have not found a way to show anything else for a signal. But at least, I know how to hide these bubbles.
Now if you have 3 stop arms of a semaphore (mounted on separate dolls), you could hide those showing red. Then you have yellow for any arm open with distant arm closed, green for any clear with distant arm also announcing clear, or nothing if all arms show stop. This, of course, is a bit sad, but there are some track diagrams that do work like that. There are others that don't, but better no red than a mess.
Even better if you have a main signal and an auxiliary signal like a call-on arm. Then you can work out their roles redictively, like main signal only shows clear, call-on arm show -- well, yellow? -- when open or red.
The dark side of the --include statement
We all know that the only way to include shared files in RW Lua scripts is the --include statement. However, this has the nasty behaviour of not including the quoted file where the --include statement is found, but appending it to the end of the current file. This can be very nasty if you use it like this.
Colors.lua:
Main.lua:
This is translated to:
The lovely Lua implementation in RW says nothing about RED being undefined in the second line. It assigns nil to myColour and two lines later, it assigns 2 to RED.
The workaround found by Kuju is this: All signals must define a function Initialise. Now, this function is called after the whole Lua file is read, which means that all the values which you assigned anywhere outside any function are already assigned.
At the same time, you must beware of doing something with the world in Initialise, all you are allowed to do is setting internal values. Sending and receiving messages happens much later. If you want to see how much later, put a Print statement into the Initialise function and the block in Update which is only executed once (after "if gInitialise then").
Back to our problem, the solution now would look like this:
Now, this assignment will only be executed when RED has the value 2.
There is another problem with the --include statement: If one of the included files is missing in the first attempt, and you just add them (or rename them to fit, etc.), the blueprint editor adds the "late" files to the end of the resulting script, irrespective of the order of the --include statements.
You can prevent this from happening by deleting the scripts folder under Assets, then all these files are redone in the correct order. Alternatively, you can strictly separate initial definitions on the top-level from using them in Initialise to set further values. It is a bit tiresome, but then you need not worry about the behaviour of the blueprint editor.
Colors.lua:
WHITE = 1
RED = 2
Main.lua:
--include=Colours.lua
myColour = RED
This is translated to:
--include=Colours.lua
myColour = RED
WHITE = 1
RED = 2
The lovely Lua implementation in RW says nothing about RED being undefined in the second line. It assigns nil to myColour and two lines later, it assigns 2 to RED.
The workaround found by Kuju is this: All signals must define a function Initialise. Now, this function is called after the whole Lua file is read, which means that all the values which you assigned anywhere outside any function are already assigned.
At the same time, you must beware of doing something with the world in Initialise, all you are allowed to do is setting internal values. Sending and receiving messages happens much later. If you want to see how much later, put a Print statement into the Initialise function and the block in Update which is only executed once (after "if gInitialise then").
Back to our problem, the solution now would look like this:
--include=Colours.lua
function Initialise()
myColour = RED
end
Now, this assignment will only be executed when RED has the value 2.
There is another problem with the --include statement: If one of the included files is missing in the first attempt, and you just add them (or rename them to fit, etc.), the blueprint editor adds the "late" files to the end of the resulting script, irrespective of the order of the --include statements.
You can prevent this from happening by deleting the scripts folder under Assets, then all these files are redone in the correct order. Alternatively, you can strictly separate initial definitions on the top-level from using them in Initialise to set further values. It is a bit tiresome, but then you need not worry about the behaviour of the blueprint editor.
Subscribe to:
Comments (Atom)
