//
// lights.gs
//
// Class: VehicleLight
include "locomotive.gs"
class lights isclass Locomotive //If we are a loco our class must be derived from
{ //Locomotive else from Vehicle
thread void DirectionMonitor(void);
thread void VehicleMonitor(void);
Vehicle GetLastCar(void);
bool CheckLastCar(void);
bool CheckFirstCar(void);
void SetTailLights(bool direction);
bool isLastCar, isFirstCar;
//The Init function is called when the object is created
public void Init(void)
{
Train mytrain = me.GetMyTrain();
Sniff(mytrain, "Train", "", true);
inherited(); //Calls the Init function of the parent Class (Vehicle)
isLastCar = false;
isFirstCar = false;
SetTailLights(true);
isLastCar = CheckLastCar(); //Upon creation we check if we are the last car in a consist
isFirstCar = CheckFirstCar(); //or the first car, because we could get the last car if direction changed
if (isLastCar or isFirstCar)
DirectionMonitor(); //If we are the last car in a consist, start the DirectionMonitor thread
else //If not set the effects to the defined state for not beeing the last car
SetTailLights(GetFacingRelativeToTrain());
VehicleMonitor(); //Start the Couple Monitor anyways
}
//The Direction Monitor checks every x seconds, in which direction our Vehicle is facing
thread void DirectionMonitor(void) //Check
{
bool direction;
while(isLastCar or isFirstCar) //Run just as long as we are the last car in a consist
{
direction = GetFacingRelativeToTrain();
SetTailLights(direction); //Set the Tail Light effect as depending to our direction
isLastCar = CheckLastCar();
isFirstCar = CheckFirstCar();
Sleep(5); //Sleep for x seconds
}
direction = GetFacingRelativeToTrain();
SetTailLights(direction); //Before we exit, we want to make sure the tail light is set to a
//defined state (ie we are no longer the last car in our consist)
}
//Monitoring the couple events. If a couple event happens, we check if we are now / are no longer
//the last car in the consist
//TODO: do some improvements (fine tuning)
thread void VehicleMonitor(void)
{
Message msg;
wait()
{
on "Vehicle", "Coupled":
{
isLastCar = CheckLastCar();
isFirstCar = CheckFirstCar();
if(isLastCar or isFirstCar)
DirectionMonitor();
continue;
}
on "Vehicle", "Decoupled":
{
isLastCar = CheckLastCar();
isFirstCar = CheckFirstCar();
if(isLastCar or isFirstCar)
DirectionMonitor();
continue;
}
on "Vehicle", "BadCouple":
{
isLastCar = CheckLastCar();
isFirstCar = CheckFirstCar();
if(isLastCar or isFirstCar)
DirectionMonitor();
continue;
}
on "Vehicle", "Derailed", msg:
{
if(msg.src == me)
{
isLastCar = false;
isFirstCar = false;
break;
//For example: switch of the lights after derailment and exit Couple Monitor for this car
}
continue;
}
on "Train", "StartedMoving":
{
isLastCar = CheckLastCar();
isFirstCar = CheckFirstCar();
if(isLastCar or isFirstCar)
DirectionMonitor();
continue;
}
}
}
// GetLastCar Determines the last car of a consist
//Thanks to Diego Lorenzo, who created the GetLastCar Function
Vehicle GetLastCar(void)
{
Train consist;
Vehicle[] cars;
Vehicle firstcar, lastcar = null;
int i;
consist = me.GetMyTrain();
if (!consist)
return cast<Vehicle>me;
cars = consist.GetVehicles();
i = cars.size();
firstcar = cast<Vehicle> consist.GetFrontmostLocomotive();
if (firstcar) //if a train consists only of Waggons, there is no FrontLoco, we want to be on the safe side ;)
{
if(cars[i-1] == firstcar)
lastcar = cars[0];
else
lastcar = cars[i-1];
}
return lastcar;
}
//CheckLastCar - checks if me is the last car in my train and returns true or false
bool CheckLastCar(void)
{
bool ret;
Vehicle lastcar = GetLastCar();
if (me == lastcar)
ret = true;
else
ret = false;
return ret;
}
bool CheckFirstCar(void)
{
Train consist;
Vehicle firstcar;
bool ret;
consist = me.GetMyTrain();
if (!consist)
return true;
firstcar = cast<Vehicle> consist.GetFrontmostLocomotive();
if (me == firstcar)
ret = true;
else
ret = false;
return ret;
}
//SetTailLights - this function handles the Effects (coronas, attached meshes, etc);
void SetTailLights(bool direction)
{
KUID coronatextureRED = GetAsset().LookupKUIDTable(7);
KUID coronatextureWHT = GetAsset().LookupKUIDTable(8);
Asset coronared = World.FindAsset(coronatextureRED);
Asset coronawht = World.FindAsset(coronatextureWHT);
if (isLastCar)
{
if (direction)
{
SetFXCoronaTexture("0",coronared);
SetFXCoronaTexture("1",coronared);
SetFXCoronaTexture("2",null);
SetFXCoronaTexture("3",null);
}
else
{
SetFXCoronaTexture("0",null);
SetFXCoronaTexture("1",null);
SetFXCoronaTexture("2",coronared);
SetFXCoronaTexture("3",coronared);
}
}
else
{
SetFXCoronaTexture("0",null);
SetFXCoronaTexture("1",null);
SetFXCoronaTexture("2",null);
SetFXCoronaTexture("3",null);
}
if (isFirstCar)
{
if (direction)
{
SetFXCoronaTexture("4",null);
SetFXCoronaTexture("5",null);
SetFXCoronaTexture("6",null);
SetFXCoronaTexture("7",coronawht);
SetFXCoronaTexture("8",coronawht);
SetFXCoronaTexture("9",coronawht);
SetFXCoronaTexture("10",null);
SetFXCoronaTexture("11",null);
}
else
{
SetFXCoronaTexture("4",coronawht);
SetFXCoronaTexture("5",coronawht);
SetFXCoronaTexture("6",coronawht);
SetFXCoronaTexture("7",null);
SetFXCoronaTexture("8",null);
SetFXCoronaTexture("9",null);
SetFXCoronaTexture("10",null);
SetFXCoronaTexture("11",null);
}
}
else
{
SetFXCoronaTexture("4",null);
SetFXCoronaTexture("5",null);
SetFXCoronaTexture("6",null);
SetFXCoronaTexture("7",null);
SetFXCoronaTexture("8",null);
SetFXCoronaTexture("9",null);
SetFXCoronaTexture("10",null);
SetFXCoronaTexture("11",null);
}
}
};