First devices
This commit is contained in:
parent
51ef0ececc
commit
8d9c08276a
8 changed files with 539 additions and 21 deletions
111
src/Devices/Deadman.cs
Normal file
111
src/Devices/Deadman.cs
Normal file
|
@ -0,0 +1,111 @@
|
|||
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 = false;
|
||||
|
||||
/// <summary>Is called when the device state should be updated.</summary>
|
||||
/// <param name="train">The current train.</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, 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)
|
||||
{
|
||||
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 & Math.Abs(train.State.Speed.KilometersPerHour) < 0.01)
|
||||
{
|
||||
// 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>
|
||||
internal override void PerformAI(AIData data, Train train)
|
||||
{
|
||||
if (DeviceState != DeviceStates.Inactive)
|
||||
{
|
||||
KeyChange(VirtualKeys.S, true, train);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
64
src/Devices/Device.cs
Normal file
64
src/Devices/Device.cs
Normal file
|
@ -0,0 +1,64 @@
|
|||
using OpenBveApi.Runtime;
|
||||
|
||||
namespace OpenbveFcmbTrainPlugin
|
||||
{
|
||||
/// <summary>Represents an abstract device.</summary>
|
||||
internal abstract class Device
|
||||
{
|
||||
|
||||
/// <summary>The power notch requested by the device.</summary>
|
||||
internal int RequestedPowerNotch = -1;
|
||||
|
||||
/// <summary>The brake notch requested by the device.</summary>
|
||||
internal int RequestedBrakeNotch = -1;
|
||||
|
||||
/// <summary>The door interlock requested by the device.</summary>
|
||||
internal DoorInterlockStates RequestedDoorInterlock;
|
||||
|
||||
/// <summary>Is called when the device state should be updated.</summary>
|
||||
/// <param name="train">The current train.</param>
|
||||
/// <param name="init">Whether the device should initialize.</param>
|
||||
/// <param name="elapsedTime">The time elapsed since the previous call.</param>
|
||||
internal virtual void Update(Train train, bool init, Time elapsedTime) { }
|
||||
|
||||
/// <summary>Is called when the driver changes the reverser.</summary>
|
||||
/// <param name="reverser">The new reverser position.</param>
|
||||
internal virtual void SetReverser(int reverser) { }
|
||||
|
||||
/// <summary>Is called when the driver changes the power notch.</summary>
|
||||
/// <param name="powerNotch">The new power notch.</param>
|
||||
internal virtual void SetPower(int powerNotch) { }
|
||||
|
||||
/// <summary>Is called when the driver changes the brake notch.</summary>
|
||||
/// <param name="brakeNotch">The new brake notch.</param>
|
||||
internal virtual void SetBrake(int brakeNotch) { }
|
||||
|
||||
/// <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 virtual void KeyChange(VirtualKeys key, bool pressed, Train train) { }
|
||||
|
||||
/// <summary>Is called when the state of the doors changes.</summary>
|
||||
/// <param name="oldState">The old state of the doors.</param>
|
||||
/// <param name="newState">The new state of the doors.</param>
|
||||
internal virtual void DoorChange(DoorStates oldState, DoorStates newState) { }
|
||||
|
||||
/// <summary>Is called when a horn is played or when the music horn is stopped.</summary>
|
||||
/// <param name="type">The type of horn.</param>
|
||||
internal virtual void HornBlow(HornTypes type) { }
|
||||
|
||||
/// <summary>Is called to inform about signals.</summary>
|
||||
/// <param name="signal">The signal data.</param>
|
||||
internal virtual void SetSignal(SignalData[] signal) { }
|
||||
|
||||
/// <summary>Is called when a beacon is passed.</summary>
|
||||
/// <param name="beacon">The beacon data.</param>
|
||||
internal virtual void SetBeacon(BeaconData beacon) { }
|
||||
|
||||
/// <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>
|
||||
internal virtual void PerformAI(AIData data, Train train) { }
|
||||
}
|
||||
}
|
167
src/Devices/Doors.cs
Normal file
167
src/Devices/Doors.cs
Normal file
|
@ -0,0 +1,167 @@
|
|||
using System;
|
||||
using OpenBveApi.Runtime;
|
||||
|
||||
namespace OpenbveFcmbTrainPlugin
|
||||
{
|
||||
/// <summary>A device controlling the door operation.</summary>
|
||||
internal class Doors : Device
|
||||
{
|
||||
/// <summary>Whether the left doors are closing.</summary>
|
||||
private bool LeftDoorsClosing;
|
||||
|
||||
/// <summary>Whether the right doors are closing.</summary>
|
||||
private bool RightDoorsClosing;
|
||||
|
||||
/// <summary>Is called when the device state should be updated.</summary>
|
||||
/// <param name="train">The current train.</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, bool init, Time elapsedTime)
|
||||
{
|
||||
if (init)
|
||||
{
|
||||
// Set the selection state of the doors during initialization
|
||||
switch (train.DoorState)
|
||||
{
|
||||
case DoorStates.None:
|
||||
RequestedDoorInterlock = DoorInterlockStates.Locked;
|
||||
break;
|
||||
case DoorStates.Both:
|
||||
RequestedDoorInterlock = DoorInterlockStates.Unlocked;
|
||||
break;
|
||||
case DoorStates.Left:
|
||||
case DoorStates.Right:
|
||||
RequestedDoorInterlock = (DoorInterlockStates)train.DoorState;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cut power when the doors are open
|
||||
RequestedPowerNotch = (train.DoorState != DoorStates.None) ? 0 : -1;
|
||||
|
||||
// Update panel variables for door selection state
|
||||
train.Panel[50] = (RequestedDoorInterlock == DoorInterlockStates.Left || RequestedDoorInterlock == DoorInterlockStates.Unlocked) ? 1 : 0;
|
||||
train.Panel[51] = (RequestedDoorInterlock == DoorInterlockStates.Right || RequestedDoorInterlock == DoorInterlockStates.Unlocked) ? 1 : 0;
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
if (pressed)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case VirtualKeys.G:
|
||||
// Change the selection state of the left doors
|
||||
if (!OpenbveFcmbTrainPlugin.KeysPressed[(int)key])
|
||||
{
|
||||
// Button active only if the doors are not open
|
||||
if ((train.DoorState & DoorStates.Left) == 0 || LeftDoorsClosing)
|
||||
{
|
||||
switch (RequestedDoorInterlock)
|
||||
{
|
||||
case DoorInterlockStates.Locked:
|
||||
RequestedDoorInterlock = DoorInterlockStates.Left;
|
||||
break;
|
||||
case DoorInterlockStates.Left:
|
||||
RequestedDoorInterlock = DoorInterlockStates.Locked;
|
||||
break;
|
||||
case DoorInterlockStates.Right:
|
||||
RequestedDoorInterlock = DoorInterlockStates.Unlocked;
|
||||
break;
|
||||
case DoorInterlockStates.Unlocked:
|
||||
RequestedDoorInterlock = DoorInterlockStates.Right;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case VirtualKeys.H:
|
||||
// Change the selection state of the right doors
|
||||
if (!OpenbveFcmbTrainPlugin.KeysPressed[(int)key])
|
||||
{
|
||||
// Button active only if the doors are not open
|
||||
if ((train.DoorState & DoorStates.Right) == 0 || RightDoorsClosing)
|
||||
{
|
||||
switch (RequestedDoorInterlock)
|
||||
{
|
||||
case DoorInterlockStates.Locked:
|
||||
RequestedDoorInterlock = DoorInterlockStates.Right;
|
||||
break;
|
||||
case DoorInterlockStates.Left:
|
||||
RequestedDoorInterlock = DoorInterlockStates.Unlocked;
|
||||
break;
|
||||
case DoorInterlockStates.Right:
|
||||
RequestedDoorInterlock = DoorInterlockStates.Locked;
|
||||
break;
|
||||
case DoorInterlockStates.Unlocked:
|
||||
RequestedDoorInterlock = DoorInterlockStates.Left;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case VirtualKeys.LeftDoors:
|
||||
if (!OpenbveFcmbTrainPlugin.KeysPressed[(int)key])
|
||||
{
|
||||
// Unselect doors automatically when closing
|
||||
if ((train.DoorState & DoorStates.Left) > 0 && (RequestedDoorInterlock == DoorInterlockStates.Left || RequestedDoorInterlock == DoorInterlockStates.Unlocked))
|
||||
{
|
||||
LeftDoorsClosing = true;
|
||||
RequestedDoorInterlock = RequestedDoorInterlock == DoorInterlockStates.Left ? DoorInterlockStates.Locked : DoorInterlockStates.Right;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case VirtualKeys.RightDoors:
|
||||
if (!OpenbveFcmbTrainPlugin.KeysPressed[(int)key])
|
||||
{
|
||||
// Unselect doors automatically when closing
|
||||
if ((train.DoorState & DoorStates.Right) > 0 && (RequestedDoorInterlock == DoorInterlockStates.Right || RequestedDoorInterlock == DoorInterlockStates.Unlocked))
|
||||
{
|
||||
RightDoorsClosing = true;
|
||||
RequestedDoorInterlock = RequestedDoorInterlock == DoorInterlockStates.Right ? DoorInterlockStates.Locked : DoorInterlockStates. Left;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
// TODO: OpenBVE does not trigger virtual buttons when the AI driver is active, needs changes to main program
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Is called when the state of the doors changes.</summary>
|
||||
/// <param name="oldState">The old state of the doors.</param>
|
||||
/// <param name="newState">The new state of the doors.</param>
|
||||
internal override void DoorChange(DoorStates oldState, DoorStates newState)
|
||||
{
|
||||
LeftDoorsClosing = false;
|
||||
RightDoorsClosing = false;
|
||||
}
|
||||
|
||||
/// <summary>Is called when the device should perform the AI.</summary>
|
||||
/// <param name="data">The AI data.</param>
|
||||
/// <param name="train">The current train.</param>
|
||||
internal override void PerformAI(AIData data, Train train)
|
||||
{
|
||||
//// Select the correct doors for the current station
|
||||
//if (Stations.State != Stations.StationStates.Completed)
|
||||
//{
|
||||
// if (((Stations.Current.OpenLeftDoors && !LeftDoorsSelected) || (!Stations.Current.OpenLeftDoors && LeftDoorsSelected)) && !LeftDoorsClosing)
|
||||
// {
|
||||
// // Select or unselect the doors on the left.
|
||||
// KeyDown(VirtualKeys.G);
|
||||
// data.Response = AIResponse.Short;
|
||||
// }
|
||||
// if (((Stations.Current.OpenRightDoors && !RightDoorsSelected) || (!Stations.Current.OpenRightDoors && RightDoorsSelected)) && !RightDoorsClosing)
|
||||
// {
|
||||
// // Select or unselect the doors on the right.
|
||||
// KeyDown(VirtualKeys.H);
|
||||
// data.Response = AIResponse.Short;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
10
src/Devices/TrainStop.cs
Normal file
10
src/Devices/TrainStop.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
|
||||
namespace OpenbveFcmbTrainPlugin
|
||||
{
|
||||
/// <summary>A train stop device to stop the train if a stop signal is passed.</summary>
|
||||
internal class TrainStop : Device
|
||||
{
|
||||
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue