This is an automated message:
A new shop has been established, which allows you to purchase products for "Z" loyalty points, which you can find in your profile or on the top bars. You can find the store under the section Downloads (Top Menu).
class SmartSignal isclass Signal
{
//these are the basic signal types
//01 - n/a
//02 - n/a
//03 - absolute signals with slow approach aspects as the highest aspect
//04 - absolute signal
//05 - permissive signal
//06 - double head diverging signal
//07 - double head converging signal (top head always red)
//08 - triple head speed interlocking signal
//081 - triple head speed interlocking signal with approach aspects as highest
//these are the states that default trainz signalling can understand.
//0 EX_STOP
//1 EX_STOP_THEN_CONTINUE
//4 EX_CAUTION
//7 EX_ADVANCE_CAUTION
//8 EX_PROCEED
//2 EX_CAUTION_LEFT
//3 EX_CAUTION_RIGHT
//9 EX_SLOW
//10 EX_MEDIUM
//11 EX_ADVANCE_CAUTION_LEFT
//12 EX_ADVANCE_CAUTION_RIGHT
//5 EX_PROCEED_LEFT
//6 EX_PROCEED_RIGHT
// so I will take thse and make them more understandable for these scripts, which use the aspect slots but change the names.
// Limited Speed........45mph
// Medium Speed.........30mph
// Slow Speed...........15mph
// Restricted Speed.....15mph
// not used as a visible state
public define int SS_DARK = 25; //!< to turn off lens
// shared states
public define int SS_STOP = 0; //!< Stop incidcation.
public define int SS_STOP_THEN_PROCEED = 1; //!< Permissive Stop indication.
public define int SS_APPROACH = 4; //!< The next signal is red.
public define int SS_ADVANCE_APPROACH = 7; //!< The next signal is yellow.
public define int SS_PROCEED = 8; //!< Proceed.
// 06D and 06
public define int SS_APPROACH_LIMITED = 12; //!< Approach next signal not exceeding Limited Speed.
public define int SS_APPROACH_MEDIUM = 11; //!< Approach next signal not exceeding Medium Speed.
// 06 and 08
public define int SS_LIMITED_CLEAR = 6; //!< Limited speed through turnouts, crossovers, sidings, and power operated switches; then proceed at maximum speed permitted.
public define int SS_MEDIUM_CLEAR = 5; //!< Medium speed through turnouts, crossovers, sidings, and power operated switches; then proceed at maximum speed permitted.
public define int SS_LIMITED_APPROACH = 2; //!< Limited speed through turnouts, crossovers, sidings, and power operated switches; then proceed prepared to stop at next signal.
public define int SS_MEDIUM_APPROACH = 3; //!< Medium speed through turnouts, crossovers, sidings, and power operated switches; then proceed prepared to stop at next signal. Diverging Approach.
// special states
public define int SS_RESTRICTING = 9; //!< Proceed at restricting speed.
public define int SS_SLOW = 10; //!< Proceed at Slow speed.
//B&O 03 CPLs
public define int SS_SLOW_APPROACH = 9; //!<
public define int SS_SLOW_APPROACH_SLOW = 7;
// extended states not understood by default trainz signals... be careful with these.
// 08 signals only.
public define int SS_MED_APPROACH_MEDIUM = 13; //!< Medium speed through turnouts, crossovers, sidings, and power operated switches; then proceed approaching next signal not exceeding Medium Speed.
public define int SS_MED_APPROACH_SLOW = 14; //!< Medium speed through turnouts, crossovers, sidings, and power operated switches; then proceed approaching next signal not exceeding Slow Speed.
public define int SS_APPROACH_RESTRICTING = 15; //!< 06d heads only when placed before 06 or 08
public define int SS_APPROACH_SLOW = 16; //08 B&O
//head angle snap amount
public define int SS_ANGLE_SNAP = 5; //degrees
Display More
public string DescState(int State, StringTable m_textStrings)
{
string desc;
switch (State)
{
case SS_STOP:
desc = m_textStrings.GetString("signal_stop");
break;
case SS_STOP_THEN_PROCEED:
desc = m_textStrings.GetString("signal_stop_proceed");
break;
case SS_LIMITED_APPROACH:
desc = m_textStrings.GetString("signal_limited_approach");
break;
case SS_MEDIUM_APPROACH:
desc = m_textStrings.GetString("signal_medium_approach");
break;
case SS_APPROACH:
desc = m_textStrings.GetString("signal_approach");
break;
case SS_MEDIUM_CLEAR:
desc = m_textStrings.GetString("signal_medium_clear");
break;
case SS_LIMITED_CLEAR:
desc = m_textStrings.GetString("signal_limited_clear");
break;
case SS_ADVANCE_APPROACH:
desc = m_textStrings.GetString("signal_advance_approach");
break;
case SS_PROCEED:
desc = m_textStrings.GetString("signal_clear");
break;
case SS_RESTRICTING:
desc = m_textStrings.GetString("signal_restricting");
break;
case SS_SLOW:
desc = m_textStrings.GetString("signal_slow_clear");
break;
case SS_APPROACH_MEDIUM:
desc = m_textStrings.GetString("signal_approach_medium");
break;
case SS_APPROACH_LIMITED:
desc = m_textStrings.GetString("signal_approach_limited");
break;
case SS_MED_APPROACH_MEDIUM:
desc = m_textStrings.GetString("signal_med_approach_med");
break;
case SS_MED_APPROACH_SLOW:
desc = m_textStrings.GetString("signal_med_approach_slow");
break;
case SS_APPROACH_RESTRICTING:
desc = m_textStrings.GetString("signal_approach_restr");
break;
case SS_APPROACH_SLOW:
desc = m_textStrings.GetString("signal_approach_slow");
break;
default:
desc = m_textStrings.GetString("signal_error");
}
return desc;
}
};
Display More
- sets the rotation of the signal head
- MeshObject a signal is a signal asset
- plovák headDeflection is the deflection angle in degrees
static class SmartSignalCommon
{
public void SetHeadDeflection(MeshObject signal, float headDeflection)
{
float angle = headDeflection * (Math.PI/180);
if(signal.HasMesh("head_1")) {signal.SetMeshOrientation("head_1", 0, 0, angle);}
if(signal.HasMesh("head_2")) {signal.SetMeshOrientation("head_2", 0, 0, angle);}
if(signal.HasMesh("head_3")) {signal.SetMeshOrientation("head_3", 0, 0, angle);}
}
- sets the letters of the signal tables
- p_name: is a mesh board
- p_color: it must be an alphabetical set of textures listing 1-26, 27-36 because the numbers '0' are empty
- p_value: is a letter (only one letter is accepted and the string will be truncated to one letter)
public void SetLetters(MeshObject signal, string p_name, Asset p_color , string p_value)
{
Str.ToUpper(p_value);
if (p_value == "N") signal.SetFXTextureReplacement(p_name,p_color,14);
else if (p_value == "S") signal.SetFXTextureReplacement(p_name,p_color,19);
else if (p_value == "E") signal.SetFXTextureReplacement(p_name,p_color,5);
else if (p_value == "W") signal.SetFXTextureReplacement(p_name,p_color,23);
else if (p_value == "A") signal.SetFXTextureReplacement(p_name,p_color,1);
else if (p_value == "B") signal.SetFXTextureReplacement(p_name,p_color,2);
else if (p_value == "C") signal.SetFXTextureReplacement(p_name,p_color,3);
else if (p_value == "D") signal.SetFXTextureReplacement(p_name,p_color,4);
else if (p_value == "F") signal.SetFXTextureReplacement(p_name,p_color,6);
else if (p_value == "G") signal.SetFXTextureReplacement(p_name,p_color,7);
else if (p_value == "H") signal.SetFXTextureReplacement(p_name,p_color,8);
else if (p_value == "I") signal.SetFXTextureReplacement(p_name,p_color,9);
else if (p_value == "J") signal.SetFXTextureReplacement(p_name,p_color,10);
else if (p_value == "K") signal.SetFXTextureReplacement(p_name,p_color,11);
else if (p_value == "L") signal.SetFXTextureReplacement(p_name,p_color,12);
else if (p_value == "M") signal.SetFXTextureReplacement(p_name,p_color,13);
else if (p_value == "O") signal.SetFXTextureReplacement(p_name,p_color,15);
else if (p_value == "P") signal.SetFXTextureReplacement(p_name,p_color,16);
else if (p_value == "Q") signal.SetFXTextureReplacement(p_name,p_color,17);
else if (p_value == "R") signal.SetFXTextureReplacement(p_name,p_color,18);
else if (p_value == "T") signal.SetFXTextureReplacement(p_name,p_color,20);
else if (p_value == "U") signal.SetFXTextureReplacement(p_name,p_color,21);
else if (p_value == "V") signal.SetFXTextureReplacement(p_name,p_color,22);
else if (p_value == "X") signal.SetFXTextureReplacement(p_name,p_color,24);
else if (p_value == "Y") signal.SetFXTextureReplacement(p_name,p_color,25);
else if (p_value == "Z") signal.SetFXTextureReplacement(p_name,p_color,26);
else if (p_value == "0") signal.SetFXTextureReplacement(p_name,p_color,27);
else if (p_value == "1") signal.SetFXTextureReplacement(p_name,p_color,28);
else if (p_value == "2") signal.SetFXTextureReplacement(p_name,p_color,29);
else if (p_value == "3") signal.SetFXTextureReplacement(p_name,p_color,30);
else if (p_value == "4") signal.SetFXTextureReplacement(p_name,p_color,31);
else if (p_value == "5") signal.SetFXTextureReplacement(p_name,p_color,32);
else if (p_value == "6") signal.SetFXTextureReplacement(p_name,p_color,33);
else if (p_value == "7") signal.SetFXTextureReplacement(p_name,p_color,34);
else if (p_value == "8") signal.SetFXTextureReplacement(p_name,p_color,35);
else if (p_value == "9") signal.SetFXTextureReplacement(p_name,p_color,36);
else signal.SetFXTextureReplacement(p_name,p_color,0);
//Interface.Log(p_name + ": " + p_value);
}
Display More
Basic property types for all SmartSignals in Surveyor
public string SSPropertyTypes(string pID)
{
string result;
if (pID[,6] == "sigNum") result = "string,1,5";
else if (pID[,8] == "powerNum") result = "int,0,9999,1";
else if (pID[,9] == "plateType") result = "list";
else result = "link";
return result;
}
Creates an HTML slider
string GetSliderHTML(string name, int min, int max)
{
// Generate a html slider using a horizontal scroll bar
string html;
html = html + "<a href='live://property/" + name + "'>";
html = html + " <trainz-object id='" + name + "' style=slider horizontal theme=default-slider width=200 height=20 min=" + min + " max=" + max + " page-size=1 draw-line=1 draw-marks=1>";
html = html + " </trainz-object>";
html = html + "</a>";
return html;
}
Basic user interface for all SmartSignals in Surveyor
public string SurveyorHTML(StringTable m_textStrings, Soup properties)
{
Asset SSAsset = World.FindAsset(properties.GetNamedTagAsKUID("SSkuid"));
HTMLBuffer Buffer = HTMLBufferStatic.Construct();
Buffer.Clear();
Buffer.Print("<html><body><font size=3><br>");
string type = properties.GetNamedTag("SignalType");
//--------------------------------signal head angle-----------------------------------
if (properties.GetNamedTagAsBool("showHeadAngleUI",false))
{
Buffer.Print("<p>" + m_textStrings.GetString("cfg_head_angle") + GetSliderHTML("headAngle", -(90 / SmartSignal.SS_ANGLE_SNAP), 90 / SmartSignal.SS_ANGLE_SNAP) + "</p>");
}
//--------------------------------path interface-----------------------------------
if (properties.GetNamedTagAsBool("showPathUI",false))
{
string pathStraight = properties.GetNamedTag("pathStraight");
string pathImg;
KUID kuidImgLeft = SSAsset.LookupKUIDTable("imgLeft");
KUID kuidImgRight = SSAsset.LookupKUIDTable("imgRight");
KUID kuidImgFwd = SSAsset.LookupKUIDTable("imgFwd");
int i;
Buffer.Print("<p>" + m_textStrings.GetString("cfg_define_path") + ": <br>");
for (i = 0; i < pathStraight.size(); i++)
{
if (i > 0) Buffer.Print(" | ");
//determine the icon to display
if (pathStraight[i,i + 1] == "L")
{
pathImg = kuidImgLeft.GetHTMLString();
}
else if (pathStraight[i,i + 1] == "R")
{
pathImg = kuidImgRight.GetHTMLString();
}
else if (pathStraight[i,i + 1] == "F")
{
pathImg = kuidImgFwd.GetHTMLString();
}
//display link
Buffer.Print("<a href=live://property/path" + i + ">");
Buffer.Print("<img kuid='" + pathImg + "' width=32 height=32>");
Buffer.Print("</a>");
}
Buffer.Print("</p><br>");
Buffer.Print("<p>" + m_textStrings.GetString("cfg_edit") + ": <a href=live://property/clear>" + m_textStrings.GetString("cfg_clear") + "</a>");
Buffer.Print(" or <a href=live://property/remove>" + m_textStrings.GetString("cfg_remove") + "</a>");
Buffer.Print(" or <a href=live://property/add>" + m_textStrings.GetString("cfg_add") + "</a>");
Buffer.Print("</p><br>");
}
Display More
Unbound control
if ((type == "06" or type == "06prr") and (properties.GetNamedTagAsBool("showPathUI",false)))
{
Buffer.Print("<p>" + HTMLWindow.CheckBox("live://property/detBond", properties.GetNamedTagAsBool("unbonded",false)) + m_textStrings.GetString("cfg_unbonded") + "</p>");
}
Activate limited speed
if (properties.GetNamedTagAsBool("showPathUI",false) and (!properties.GetNamedTagAsBool("unbonded",false)) and (
type == "06"
or type == "08"
or type == "08-1"))
{
Buffer.Print("<p>" + HTMLWindow.CheckBox("live://property/limited", properties.GetNamedTagAsBool("limitedSpeed",false)) + m_textStrings.GetString("cfg_limited_speed") + "</p>");
}
Show approach or clear
if (properties.GetNamedTagAsBool("showAdvAppUI",false))
{
Buffer.Print("<p>" + HTMLWindow.CheckBox("live://property/advanceApp", properties.GetNamedTagAsBool("advanceApp",false)) + m_textStrings.GetString("cfg_advance_app") + "</p>");
}
Display restrictions
if (properties.GetNamedTagAsBool("showRestrictingUI",false))
{
Buffer.Print("<p>" + HTMLWindow.CheckBox("live://property/restricting", properties.GetNamedTagAsBool("allowRestricting",false)) + m_textStrings.GetString("cfg_restricting") + "</p>");
}
Zoom in on lighting and channel
bool approachLit = properties.GetNamedTagAsBool("approachLit",false);
Buffer.Print("<p>" + HTMLWindow.CheckBox("live://property/approachLit", approachLit) + m_textStrings.GetString("cfg_approach_lit") + "</p>");
if (approachLit)
{
int gChannel = properties.GetNamedTagAsInt("gChannel",0);
Buffer.Print("<p>" + m_textStrings.GetString("cfg_approach_lit_channel") + ": <a href=live://property/powerNum>");
if (gChannel)
{
Buffer.Print(gChannel);
}
else
{
Buffer.Print(m_textStrings.GetString("cfg_none"));
}
Buffer.Print("</a></p>");
}
Display More
Show clearly when idle
if( (type == "03")
or (type == "04")
or (type == "05")
or (type == "06")
or (type == "06D"))
{
Buffer.Print("<p>" + HTMLWindow.CheckBox("live://property/idleClear", properties.GetNamedTagAsBool("idleClear",false)) + m_textStrings.GetString("cfg_idle_clear") + "</p>");
}
Stop type
if (properties.GetNamedTagAsBool("showPRRstop",false))
{
Buffer.Print("<p>" + HTMLWindow.CheckBox("live://property/stopType", properties.GetNamedTagAsBool("stopType",false)) + m_textStrings.GetString("cfg_prr_stop_type") + "</p>");
}
The train orders a light
if (properties.GetNamedTagAsBool("showOrderLightUI",false))
{
bool showLamp = properties.GetNamedTagAsBool("showOrderLight",false);
bool onLeft = properties.GetNamedTagAsBool("ordersLightOnLeft",false);
Buffer.Print("<p>" + HTMLWindow.CheckBox("live://property/orderslight", showLamp)
+ m_textStrings.GetString("cfg_show_orders_light"));
if (showLamp)
{
Buffer.Print(": <a href=live://property/olside>");
if(onLeft)
{
Buffer.Print(m_textStrings.GetString("cfg_left"));
} else {
Buffer.Print(m_textStrings.GetString("cfg_right"));
}
Buffer.Print("</a></p>");
}
}
Display More
Setting the tables and markers for the signal
if (properties.GetNamedTagAsBool("showAbsUI",false))
{
Buffer.Print("<p>" + HTMLWindow.CheckBox("live://property/aplate", properties.GetNamedTagAsBool("aplate",false)) + m_textStrings.GetString("cfg_abslt_plate") + "</p>");
}
if (properties.GetNamedTagAsBool("showGrdUI",false))
{
Buffer.Print("<p>" + HTMLWindow.CheckBox("live://property/gplate", properties.GetNamedTagAsBool("gplate",false)) + m_textStrings.GetString("cfg_grade_plate") + "</p>");
}
if (properties.GetNamedTagAsBool("showRplUI",false))
{
Buffer.Print("<p>" + HTMLWindow.CheckBox("live://property/rplate", properties.GetNamedTagAsBool("rplate",false)) + m_textStrings.GetString("cfg_restr_plate") + "</p>");
}
Display More
Marking
if (properties.GetNamedTagAsBool("showMarkerUI",false))
{
Buffer.Print("<p>" + HTMLWindow.CheckBox("live://property/marker", properties.GetNamedTagAsBool("marker",false)) + m_textStrings.GetString("cfg_marker") + "</p>");
}
Number plate
if (properties.GetNamedTagAsBool("showPlateUI",false))
{
int plateType = properties.GetNamedTagAsInt("plateType");
string plateDesc = properties.GetNamedTag("plateDesc");
Buffer.Print(m_textStrings.GetString("cfg_number_plate_type") + ": <a href=live://property/plateType>");
if (plateType > -1)
{
Buffer.Print(plateDesc);
}
else
{
Buffer.Print(m_textStrings.GetString("cfg_default"));
}
Buffer.Print("</a><br>");
Display More
string myNum = properties.GetNamedTag("number");
Buffer.Print(m_textStrings.GetString("cfg_signal_number") + ": <a href=live://property/sigNum>");
if (myNum != "")
{
Buffer.Print(myNum);
}
else
{
Buffer.Print(m_textStrings.GetString("cfg_none"));
}
Buffer.Print("</a><br>");
}
Display More
Termination of HTML
Buffer.Print("</font></body></html>");
return Buffer.AsString();
}
public string SSGetPropValue(StringTable m_textStrings, Soup properties, string pID)
{
string result;
if (pID[,8] == "powerNum")
{
int gChannel = properties.GetNamedTagAsInt("gChannel",0);
if(gChannel >= 0)
{
result = gChannel;
}
else
result = "";
}
if (pID[,6] == "sigNum")
{
string myNum = properties.GetNamedTag("number");
if (myNum != "")
{
result = myNum;
}
else
result = "";
}
return result;
}
Display More
Basic user interface for all SmartSignals in the controller
public string DriverHTML(StringTable m_textStrings, Soup properties)
{
HTMLBuffer Buffer = HTMLBufferStatic.Construct();
Buffer.Clear();
Buffer.Print("<html><body>");
//can we display restricting override?
if(properties.GetNamedTagAsBool("show_override",false))
{
Buffer.Print("<p>" + HTMLWindow.CheckBox("live://property/restricting", properties.GetNamedTagAsBool("restricting_override",false))
+ m_textStrings.GetString("cfg_toggle_restricting") + "</p>");
}
//can we display train order indicator
if(properties.GetNamedTagAsBool("show_orders_toggle",false))
{
Buffer.Print("<p>" + HTMLWindow.CheckBox("live://property/orders", properties.GetNamedTagAsBool("has_orders",false))
+ m_textStrings.GetString("cfg_toggle_orders") + "</p>");
}
//end html
Buffer.Print("</body></html>");
return Buffer.AsString();
}
Display More
Common logic section of signals
Block distance to the next absolute signal
public float BlockDistance(Signal start)
{
//this returns the block distance to the next absolute signal, and also the junction beyond that one for the opposing trains.
MapObject dMapObject;
GSTrackSearch DGST = start.BeginTrackSearch(true);
int cntr = 0;
float distance = 0;
Signal nextSignal = null;
while(dMapObject = DGST.SearchNext())
{
if(cast<Signal> dMapObject)
{
if(!DGST.GetFacingRelativeToSearchDirection())
{
nextSignal = (cast<Signal> dMapObject);
if (nextSignal.CanDisplayStateEx(1))
{
//Interface.Log("smartsignal.gs: <" + me.GetLocalisedName() + ">: Found intermediate signal.");
}
else
{
// If the next signal is absolute, set this block distance.
//This is the determined block length from the start signal to the next opposite facing absolute signal
distance = DGST.GetDistance();
break;
}
}
}
}
return distance;
}
Display More
- Param: start....The signal to start from
- Param: searchDirection.....Which direction to search. 'False' == behind the signal, 'True' == before the signal.
- Param: numSignalsToCheck.....Number of signal blocks to scan. 0 for any.
- Param: maxDistance.....How far on the track chart to search for a train
It checks if the block is active and returns a reference to the train if found.
The train does not need to move to activate the block.
public Train checkBlockActive(Signal start, bool searchDirection, int numSignalsToCheck, float maxDistance)
{
GSTrackSearch myGST = start.BeginTrackSearch(searchDirection);
MapObject nextMapObject;
int signalCount = 0;
Vehicle theVeh;
while(nextMapObject = myGST.SearchNext())
{
if(myGST.GetDistance() > maxDistance)
{
return null;
}
else if(cast<Signal> nextMapObject)
{
if(!myGST.GetFacingRelativeToSearchDirection())
{
if((numSignalsToCheck > 0) and (++signalCount > numSignalsToCheck))
{
return null;
}
}
}
else if(cast<Vehicle> nextMapObject)
{
theVeh = cast<Vehicle> nextMapObject;
return theVeh.GetMyTrain();
}
}
return null;
}
Display More
Find the closest approaching train for a specific signal
The train must move towards or in the direction of the signal and stop.
public Train TrainMovingTowardSignal(Signal start, bool searchDirection, int numSignalsToCheck, float maxDistance)
{
GSTrackSearch myGST = start.BeginTrackSearch(searchDirection);
MapObject nextMapObject;
Vehicle theVeh;
Train theTrain;
int signalCount;
while(nextMapObject = myGST.SearchNext())
{
if(myGST.GetDistance() > maxDistance)
{
return null;
}
else if(cast<Signal> nextMapObject)
{
if(!myGST.GetFacingRelativeToSearchDirection())
{
if((numSignalsToCheck > 0) and (++signalCount > numSignalsToCheck))
{
return null;
}
}
}
else if(cast<Vehicle> nextMapObject)
{
theVeh = cast<Vehicle> nextMapObject;
theTrain = theVeh.GetMyTrain();
if(!theTrain.TracksideIsInFront(start,(myGST.GetDistance() + 200)))
{
//train is facing away from signal
if(theTrain.GetTrainVelocity() < -0.01) { //if train is backing in my direction
return theTrain;
} else {
return null;
}
} else {
//train is facing signal
if(theTrain.GetTrainVelocity() > -0.01) { //if train is moving forward or facing my direction and stopped.
return theTrain;
} else {
return null;
}
}
}
}
return null;
}
};
Display More
Comments