125 lines
No EOL
5.2 KiB
C#
125 lines
No EOL
5.2 KiB
C#
using System;
|
|
using OpenBveApi.Runtime;
|
|
|
|
namespace OpenbveFcmbTrainPlugin
|
|
{
|
|
/// <summary>A deadman switch device to stop the train if the driver does not periodically acknowledge it.</summary>
|
|
internal class Deadman : Device
|
|
{
|
|
/// <summary>Represents the state of the device.</summary>
|
|
private enum DeviceStates
|
|
{
|
|
/// <summary>The device is inactive.</summary>
|
|
Inactive,
|
|
/// <summary>The device is active.</summary>
|
|
Active,
|
|
/// <summary>The device is in emergency state.</summary>
|
|
Emergency,
|
|
}
|
|
|
|
/// <summary>The current state of the device.</summary>
|
|
private DeviceStates DeviceState;
|
|
|
|
/// <summary>The counter. This starts at zero and counts up until the brake delay time is reached.</summary>
|
|
private double Counter;
|
|
|
|
/// <summary>The delay time until the service brake is applied, in seconds.</summary>
|
|
private double BrakeDelay = 5.0;
|
|
|
|
/// <summary>Whether the train must be completely stopped to release the brakes.</summary>
|
|
private bool FullReset;
|
|
|
|
/// <summary>Creates an instance of the Deadman device.</summary>
|
|
/// <param name="brakeDelay">The delay before the brakes are applied, in seconds.</param>
|
|
/// <param name="fullReset">Whether the train must be completely stopped to release the brakes.</param>
|
|
internal Deadman(double brakeDelay, bool fullReset)
|
|
{
|
|
BrakeDelay = brakeDelay;
|
|
FullReset = fullReset;
|
|
}
|
|
|
|
/// <summary>Is called when the device state should be updated.</summary>
|
|
/// <param name="train">The current train.</param>
|
|
/// <param name="route">The current route.</param>
|
|
/// <param name="init">Whether the device should initialize.</param>
|
|
/// <param name="elapsedTime">The time elapsed since the previous call.</param>
|
|
internal override void Update(Train train, Route route, bool init, Time elapsedTime)
|
|
{
|
|
if (train.VigilanceOverride)
|
|
{
|
|
// The train wants to override vigilance devices, so the device is inactive
|
|
DeviceState = DeviceStates.Inactive;
|
|
}
|
|
|
|
switch (DeviceState)
|
|
{
|
|
case DeviceStates.Active:
|
|
// The device is active, update the counter every frame
|
|
Counter += elapsedTime.Seconds;
|
|
RequestedBrakeNotch = -1;
|
|
if (Counter > BrakeDelay)
|
|
{
|
|
// Switch to emergency mode when the counter reaches the brake delay time
|
|
DeviceState = DeviceStates.Emergency;
|
|
}
|
|
break;
|
|
case DeviceStates.Inactive:
|
|
// The device is being overridden, release the brakes
|
|
RequestedBrakeNotch = -1;
|
|
if (!train.VigilanceOverride)
|
|
{
|
|
// If the device is no longer overridden, it should be active again
|
|
DeviceState = DeviceStates.Active;
|
|
}
|
|
break;
|
|
case DeviceStates.Emergency:
|
|
// Apply the brakes when the device is in emergency mode
|
|
RequestedBrakeNotch = train.Specs.BrakeNotches;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/// <summary>Is called when the state of a key changes.</summary>
|
|
/// <param name="key">The key.</param>
|
|
/// <param name="pressed">Whether the key is pressed or released.</param>
|
|
/// <param name="train">The current train.</param>
|
|
internal override void KeyChange(VirtualKeys key, bool pressed, Train train)
|
|
{
|
|
double speed = train.State.Speed.KilometersPerHour;
|
|
bool stopped = speed < 0.05;
|
|
|
|
if (pressed)
|
|
{
|
|
switch (key)
|
|
{
|
|
case VirtualKeys.S:
|
|
if (DeviceState == DeviceStates.Active || (DeviceState == DeviceStates.Emergency & !FullReset))
|
|
{
|
|
// Reset the counter if the delay time has not been exceeded or if a full reset is not required
|
|
Counter = 0;
|
|
DeviceState = DeviceStates.Active;
|
|
}
|
|
else if (DeviceState == DeviceStates.Emergency && stopped)
|
|
{
|
|
// Reset the counter after the train has stopped
|
|
Counter = 0;
|
|
DeviceState = DeviceStates.Active;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>Is called when the plugin should perform the AI.</summary>
|
|
/// <param name="data">The AI data.</param>
|
|
/// <param name="train">The current train.</param>
|
|
/// <param name="route">The current route.</param>
|
|
internal override void PerformAI(AIData data, Train train, Route route)
|
|
{
|
|
if (DeviceState != DeviceStates.Inactive)
|
|
{
|
|
KeyChange(VirtualKeys.S, true, train);
|
|
}
|
|
}
|
|
}
|
|
} |