include "locomotive.gs" include "asset.gs" /* Script for loco lights control Author: Dave Renshaw (eldavo) Copyright Dave Renshaw 2004, 2006. All rights reserved. You may freely use this script as the basis for other works made available from the Auran download station as long as you acknowledge the author and original copyright. For "payware" items a license payment is required for each asset that uses this script or is derived from it. For the terms of this license a derived work that contains 50% or more of the original script. Visit ElDavo's Railway Emporium website for more information and payment instructions. (http://eldavos.co.uk) This script is designed to control 2 red tail lights, 3 white marker lights and 2 headlamps on each end of a locomotive. The lights will adapt based on the direction of travel and what is coupled to the loco. Only one of the headlamps is ever illuminated and is controlled by the driver via the 'L' key. The headlamp illumination is designed to meet UK group standards so that during the day the righthand lamp is lit while during the hours of darkness the lefthand lamp is lit. The coronas to use should be defined in the kuid-table as "corona_red" and "corona-white" of the config.txt. The attachment points on the front of the loco should be configured as below: marker_at | V --------------------- / o \ / \ | | | | | | | | | | | | | | | | | | | o O o o O o | --------------------------- ^ ^ ^ ^ ^ ^ | | | | | | marker_a0 | | | | marker_a1 head_a0 | | head_a1 tail_a0 tail_a1 When travelling forward the marker lights marker_a0, marker_a1, and marker_at will be illuminated and, if the headlight is on, either head_a0 (daytime) or head_a1 will also be lit using the "corona_white" asset. When travelling backwards tail_a0 and tail_a1 will be lit using the asset named "corona_red". Rear attachment points are marker_b0, marker_b1, marker_bt, tail_b0, tail_b1, head_b0 and head_b1. The lighting configuration is all controlled by the SetLights method. The attachments are defined in the config.txt as effects in the mesh-table like so: effects { tail_a0 { kind corona att a.taila0 object-size 0.075 directional 1 } tail_a1 { kind corona att a.taila1 object-size 0.075 directional 1 } tail_b0 { kind corona att a.tailb0 object-size 0.075 directional 1 } tail_b1 { kind corona att a.tailb1 object-size 0.075 directional 1 } head_a0 { kind corona att a.heada0 object-size 0.11 directional 1 } head_a1 { kind corona att a.heada1 object-size 0.18 directional 1 } marker_at { kind corona att a.markerat object-size 0.09 directional 1 } marker_a0 { kind corona att a.markera0 object-size 0.075 directional 1 } marker_a1 { kind corona att a.markera1 object-size 0.075 directional 1 } head_b0 { kind corona att a.headb0 object-size 0.11 directional 1 } head_b1 { kind corona att a.headb1 object-size 0.18 directional 1 } marker_bt { kind corona att a.markerbt object-size 0.09 directional 1 } marker_b0 { kind corona att a.markerb0 object-size 0.075 directional 1 } marker_b1 { kind corona att a.markerb1 object-size 0.075 directional 1 } } */ class LightUp isclass Locomotive { // We have to first define the methods within the script class... // // These methods handle the different things we want to control void SetLights(); // // These are handlers that listen for messages from the scripting environment and other objects void TrainHandler(Message msg); void CouplingHandler(Message msg); // // Finally a method that runs as a thread and checks the state of things periodically thread void ControlMonitor(); // Define a flag to turn debugging information on and off. Set this to "true" to enable output of debug info. bool debug = true; // bool debug = false; // // The train we are currently part of Train currentTrain; // Generally useful stuff // Asset red; Asset white; // The "init" method is called whenever a new vehicle of this type is created // void Init(void) { if (debug) {Interface.Log("LightUp.Init() [v1.0] my name is '"+GetName()+"' and id is '"+GetId()+"'");} // We always call our superclass (Locomotive) init method to ensure all the behaviour we wish to // inherit from it has been correctly initialised. inherited(); red = me.GetAsset().FindAsset("corona_red"); if (red == null) { Interface.Log("class67.Init() - can't find corona asset 'corona_red'!"); return; } white = me.GetAsset().FindAsset("corona_white"); if (red == null) { Interface.Log("class67.Init() - can't find corona asset 'corona_white'!"); return; } // Listen for a few interesting messages.. // AddHandler(me, "Train", null, "TrainHandler"); AddHandler(me, "Vehicle", null, "CouplingHandler"); currentTrain = me.GetMyTrain(); // if we have a train object we will sniff it for events... if (currentTrain!= null) { if (debug) {Interface.Log("LightUp.Init() - Train object is not null");} me.Sniff(currentTrain, "Train", "StartedMoving", true); } // Set up the initial state of everything... SetLights(); // Kick off a monitoring thread... ControlMonitor(); } // We have a handler for train messages so we can see when the train starts moving and adjust the // various settings void TrainHandler(Message msg) { if (debug) { Interface.Log("LightUp.TrainHandler(major='"+msg.major+"' minor='"+msg.minor+"'"); if (msg.src == null) { Interface.Log(" src='null')"); } else { GameObject srco = cast msg.src; Interface.Log(" src='"+srco.GetName()+"')"); } Interface.Log(" me='"+me.GetName()+"'"); } if (msg.minor == "StartedMoving") { SetLights(); } } // We have a handler for vehicle messages so we can see when we are coupled and uncoupled and can adjust the // various settings void CouplingHandler(Message msg) { if (debug) { Interface.Log("LightUp.CouplingHandler(major='"+msg.major+"' minor='"+msg.minor+"'"); if (msg.src == null) { Interface.Log(" src='null')"); } else { GameObject srco = cast msg.src; Interface.Log(" src='"+srco.GetName()+"')"); } Interface.Log(" me='"+me.GetName()+"'"); } if (msg.minor == "Coupled" or msg.minor == "Collided") { if (msg.src == me) { // Adjust the train sniffer to ensure we are watching the right one... if (currentTrain != null) { me.Sniff(currentTrain, "Train", "StartedMoving", false); } currentTrain = me.GetMyTrain(); if (currentTrain != null) { me.Sniff(currentTrain, "Train", "StartedMoving", true); } SetLights(); } } else if (msg.minor == "Decoupled") { // Adjust the train sniffer to ensure we are watching the right one... if (currentTrain != null) { me.Sniff(currentTrain, "Train", "StartedMoving", false); } currentTrain = me.GetMyTrain(); if (currentTrain != null) { me.Sniff(currentTrain, "Train", "StartedMoving", true); } SetLights(); } } thread void ControlMonitor() { if (debug) {Interface.Log("LightUp.ControlMonitor()");} // the state of the current module int oldModule = World.GetCurrentModule(); // the state of the headlight float oldheadlight = 0.0; while (true) { // Have we changed modules? int newModule = World.GetCurrentModule(); if (newModule != oldModule) { if (debug) {Interface.Log("LightUp.ControlMonitor() - change module from "+oldModule+" to "+newModule);} if (newModule == World.DRIVER_MODULE) { SetLights(); } oldModule = newModule; } if (newModule == World.DRIVER_MODULE) { // what's the state of the headlight? float headlight = me.GetEngineSetting("headlight"); if (headlight != oldheadlight) { // looks like the headlight has been turned on or off... me.SetLights(); oldheadlight = headlight; } } Sleep(5); } } void SetLights() { if (debug) {Interface.Log("LightUp.SetLights()");} // turn off all the lights // turn headlights and markers off at A end me.SetFXCoronaTexture("marker_a0", null); me.SetFXCoronaTexture("marker_a1", null); me.SetFXCoronaTexture("marker_at", null); me.SetFXCoronaTexture("head_a0", null); me.SetFXCoronaTexture("head_a1", null); // turn headlights and markers off at B end me.SetFXCoronaTexture("marker_b0", null); me.SetFXCoronaTexture("marker_b1", null); me.SetFXCoronaTexture("marker_bt", null); me.SetFXCoronaTexture("head_b0", null); me.SetFXCoronaTexture("head_b1", null); // turn off all tail lights me.SetFXCoronaTexture("tail_a0", null); me.SetFXCoronaTexture("tail_a1", null); me.SetFXCoronaTexture("tail_b0", null); me.SetFXCoronaTexture("tail_b1", null); // if we are not in Driver or Surveyor then display a default light pattern... if (debug) {Interface.Log("LightUp.SetLights() current module="+World.GetCurrentModule());} if (World.GetCurrentModule() != World.DRIVER_MODULE) { if (debug) {Interface.Log("LightUp.SetLights - Not in Driver. Setting default light pattern");} me.SetFXCoronaTexture("head_a0", white); me.SetFXCoronaTexture("head_a1", white); me.SetFXCoronaTexture("marker_a0", white); me.SetFXCoronaTexture("marker_a1", white); me.SetFXCoronaTexture("marker_at", white); me.SetFXCoronaTexture("tail_b0", red); me.SetFXCoronaTexture("tail_b1", red); return; } // which way round are we? float reverser = me.GetEngineSetting("reverser"); if (debug) { Interface.Log("LightUp.SetLights() reverser = "+reverser); Interface.Log("LightUp.SetLights() me.GetDirectionRelativeToTrain() = "+me.GetDirectionRelativeToTrain()); } float time = World.GetGameTime(); if (debug) {Interface.Log("LightUp.SetLights() time = "+time);} bool night = (time > 0.25 and time < 0.75); float headlight = me.GetEngineSetting("headlight"); if (debug) {Interface.Log("LightUp.SetLights() headlight = "+headlight);} Train t = me.GetMyTrain(); Vehicle[] vs = t.GetVehicles(); // are we on the front of the train? if (vs[0] == me) { if (debug) {Interface.Log("LightUp.SetLights() On the front");} // are we facing the same direction as the train? if (me.GetDirectionRelativeToTrain()) { // Yes. The A end is at the front of the train. // Are we going forward or backward? if (reverser >= 1.0) { // So we are at the front going forward // turn markers on at A end me.SetFXCoronaTexture("marker_a0", white); me.SetFXCoronaTexture("marker_a1", white); me.SetFXCoronaTexture("marker_at", white); if (headlight > 0.0) { if (night) { me.SetFXCoronaTexture("head_a1", white); } else { me.SetFXCoronaTexture("head_a0", white); } } } else { // turn tail lights on at A end me.SetFXCoronaTexture("tail_a0", red); me.SetFXCoronaTexture("tail_a1", red); } } else { // We are back to front compared with the train // Is the loco going forward or backward? if (reverser >= 1.0) { // So we are at the front going backwards // turn markers on at B end me.SetFXCoronaTexture("marker_b0", white); me.SetFXCoronaTexture("marker_b1", white); me.SetFXCoronaTexture("marker_bt", white); if (headlight > 0.0) { if (night) { me.SetFXCoronaTexture("head_b1", white); } else { me.SetFXCoronaTexture("head_b0", white); } } } else { // turn tail lights on at B end me.SetFXCoronaTexture("tail_b0", red); me.SetFXCoronaTexture("tail_b1", red); } } } // are we on the end of the train? if (vs[vs.size()-1] == me) { if (debug) {Interface.Log("LightUp.SetLights() On the back");} // Yup. // are we facing the same direction as the train? if (me.GetDirectionRelativeToTrain()) { // Yes, Are we going forward or backward? if (reverser >= 1.0) { // turn tail lights on at B end me.SetFXCoronaTexture("tail_b0", red); me.SetFXCoronaTexture("tail_b1", red); } else { // So we are at the back going backwards // turn markers on at B end me.SetFXCoronaTexture("marker_b0", white); me.SetFXCoronaTexture("marker_b1", white); me.SetFXCoronaTexture("marker_bt", white); if (headlight > 0.0) { if (night) { me.SetFXCoronaTexture("head_b1", white); } else { me.SetFXCoronaTexture("head_b0", white); } } } } else { // No. Are we going forward or backward? if (reverser >= 1.0) { // So we are at the back going forwards // turn tail lights on at A end me.SetFXCoronaTexture("tail_a0", red); me.SetFXCoronaTexture("tail_a1", red); } else { // turn markers on at A end me.SetFXCoronaTexture("marker_a0", white); me.SetFXCoronaTexture("marker_a1", white); me.SetFXCoronaTexture("marker_at", white); if (headlight > 0.0) { if (night) { me.SetFXCoronaTexture("head_a1", white); } else { me.SetFXCoronaTexture("head_a0", white); } } } } } } };