KIND MOSignal

From TrainzOnline
(Difference between revisions)
Jump to: navigation, search
m (Custom Logic)
 
m (1 revision)

Revision as of 23:59, 3 February 2010

Warning: This page is a work in progress and any details or metrics included here may be subject to change as TS2009 development continues.

Classics 3 introduced an updated Signalling system, which is being extended further for TS2009.

Config entries specific to signals are:

kind mosignal
type Trackside
function TrackSignal
trainz-build 2.8
distant 0
home 0
repeater 0
always-controlled 0
double-blocking 0
overlap 183
overlap-track-circuited 1
signals {
	1 {
		light					2
		speed					6.71
	}
	4 {
		light					1
	}
	7 {
		light					1
		flash					1
		flash-offset				0
	}
	8 {
		light					0
	}
}
lights {
	0 {
		corona					"corona_green.tga"
	}
	1 {
		corona					"corona_yellow.tga"
	}
	2 {
		corona					"corona_red.tga"
	}
}


Notes on the default signalling logic

The signalling system now knows about, and uses, a lot more states than it did previously. This means you have to be a lot more careful of including the correct states in your signals than you did before.

If a signal is supposed to be permissive, include state '1' rather than state '0'. The Autopilot will now treat it as a permissive signal, and drive past it, queueing up behind the train in the next section.

A distant signal should not include state '0' or '1' at all.

A fixed distant can be made by specifying 'distant 1' and including only state '4'. All trains approaching (whether the line ahead is clear or not) will slow down when approaching it.

A repeater should not show state '0' - use state '1' for this instead, otherwise the Autopilot will stop at the repeater, and not at the signal it is repeating.

Some signalling systems (such as cab signalling systems or automatic train operation systems) use two danger indications in rear of a train, as they cannot prevent trains from passing the start of a block, only stop them once they have entered. To reproduce this behaviour, include both state '0' and state '1' in your signal, and use the double-blocking tag. This will give a (permissive) safety block, with an absolute stop indication at the end of it, which should produce the correct behaviour for both the human driver and the Autopilot.

If you want a particular state, but don't have a light to use for it, use "light -1". This is enough to make the state valid, but not use a light for that state.

If you don't specify any states at all, the signal is assumed to be a Pre-v1.3 style signal, which can display Stop, Caution and Proceed via the attachments a.red, a.orange, and a.green. This behaviour is deprecated - so please don't rely on it. It's main use at present appears to be buffer stops and fixed distant boards, which don't actually have the attachment points anyway. I suggest taking advantage of the 'light -1' behaviour to add specific relevant states to these kind of signals. (Fixed buffer stops should have state 0 only, fixed distants state 4 only, and the 'distant 1' tag).

Custom Logic

Signals can implement custom logic in script, should the improved default logic not be adequate for the signalling system being modelled. Make your signal script a subclass of 'Signal' like this:

include "signal.gs"

class MyCustomLogicSignal isclass Signal {

Remember to call inherited(); in your Init() method: (THIS IS IMPORTANT!)

  void Init(void) {
    inherited();

and then override the function 'DetermineUpdatedState' like this:

  Soup DetermineUpdatedState(void) {
    Soup sigSoup = inherited();
    
    // your code goes here ...
    
  }

to implement custom logic, and/or the function 'ApplyUpdatedState' like this:

  void ApplyUpdatedState(Soup sigSoup) {
    inherited(sigSoup);
    
    // your code goes here ...
    
  }

to implement custom state display.

Note: You do not need to override both functions. You can override only one if that is all you need to do. I expect a lot of people will want to override 'ApplyUpdatedState' but not need to override 'DetermineUpdatedState'.

The soup that DetermineUpdatedState needs to return contains two records - the integer tag "state" set to one of the signal display states, and the string tag "reason" set to the reason string to use. Default strings are available in Trainz - these are called up by name (starting with a dollar sign) - e.g. "$signal_nextblockbusy_lbl". If none of the default strings are appropriate, you can load a string from the asset's string table in the usual way and pass that in directly.

The soup that you get back from inherited(); will have the values that the default logic thinks you should use, so you can implement specific cases and allow the "default" values through if those cases are not hit.

ApplyUpdatedState takes a soup in the same format (though it only cares about the state, not the reason), and from that, sets up the visual representation of the signal as required. This is very useful for animated signals (e.g. semaphores).

HEALTH WARNING: It is VERY easy to totally destroy the performance of Trainz using these functions. In Classics 3, they are called twice a second for every signal in the map, so they need to be very fast and efficient.

FUTURE BUG WARNING: Do NOT rely on the half second interval between updates. TS2009 does not call signals every half a second. It calls them when it believes they might want to change based on what they queried via GSTrackSearch in their DetermineUpdatedState phase. This could result in intervals of minutes at a time without an update. (This does not, however, mean you can be any less efficient - signals may still be called up to twice a second).

SECOND HEALTH WARNING: Do NOT make a KIND Scenery-trackside object a subclass of 'Signal' in script. This will cause script errors. The correct TrainzScript class for a Scenery-Trackside object is 'Trackside'.

Categories

Personal tools