using System; using System.Collections.Generic; using OpenBveApi.Runtime; namespace OpenbveFcmbTrainPlugin { /// <summary>Represents a train that is simulated by this plugin.</summary> internal class Train { /// <summary>Represents the driver's handles.</summary> internal class DriverHandles { internal int Reverser; internal int PowerNotch; internal int BrakeNotch; } /// <summary>The train panel variables.</summary> internal int[] Panel; /// <summary>The specifications of the train.</summary> internal VehicleSpecs Specs { get; private set; } /// <summary>The current state of the train.</summary> internal VehicleState State { get; private set; } /// <summary>The current state of the train doors.</summary> internal DoorStates DoorState { get; private set; } /// <summary>The previous state of the train doors.</summary> internal DoorStates PreviousDoorState { get; private set; } /// <summary>The latest initialization mode of the train.</summary> internal InitializationModes InitializationMode { get; private set; } /// <summary>The devices equipped in the train.</summary> private List<Device> Devices; /// <summary>The physical handles of the train.</summary> internal DriverHandles PhysicalHandles { get; private set; } /// <summary>Whether the train's vigilance device is overridden.</summary> internal bool VigilanceOverride; /// <summary>Whether the train is using a continuous protection system instead of an intermittent protection system.</summary> internal bool ContinuousProtection; /// <summary>The service brake notch for ATC.</summary> internal int ServiceBrakeNotch { get; private set; } /// <summary>The current acceleration of the train.</summary> internal double Acceleration { get; private set; } /// <summary>The time when acceleration was calculated.</summary> private Time AccelerationTime = new Time(0); /// <summary>The speed when acceleration was calculated.</summary> private Speed AccelerationSpeed = new Speed(0); /// <summary>Creates a new train with the device configuration provided.</summary> /// <param name="panel">The array of panel variables.</pa internal Train(int[] panel) { Specs = new VehicleSpecs(0, BrakeTypes.ElectromagneticStraightAirBrake, 0, false, 0); State = new VehicleState(0.0, new Speed(0.0), 0.0, 0.0, 0.0, 0.0, 0.0); Panel = panel; PhysicalHandles = new DriverHandles(); Devices = new List<Device>(); Devices.Add(new Doors(false, 5, 15, 10)); Devices.Add(new Deadman(5.0, false)); Devices.Add(new TrainStop()); Devices.Add(new AtcBombardier(30, 60, 20, 500)); } /// <summary>Is called when the train should initialize.</summary> /// <param name="mode">The initialization mode.</param> internal void Initialize(InitializationModes mode) { InitializationMode = mode; } /// <summary>Is called after loading to inform the plugin about the specifications of the train.</summary> /// <param name="specs">The specifications of the train.</param> internal void SetVehicleSpecs(VehicleSpecs specs) { Specs = specs; // Set the service brake notch for ATC ServiceBrakeNotch = specs.BrakeNotches > 1 ? specs.BrakeNotches - 1 : 1; } /// <summary>Is called every frame.</summary> /// <param name="data">The data.</param> /// <param name="route">The route data.</param> internal void Elapse(ElapseData data, Route route) { State = data.Vehicle; // Reset data to be passed to the simulator data.DoorInterlockState = DoorInterlockStates.Unlocked; data.Handles.PowerNotch = data.Handles.PowerNotch; data.Handles.BrakeNotch = data.Handles.BrakeNotch; // Calculate acceleration if (OpenbveFcmbTrainPlugin.Initializing) { AccelerationTime = data.TotalTime; } if (data.TotalTime.Milliseconds - AccelerationTime.Milliseconds > 200) { Acceleration = Math.Round((State.Speed.MetersPerSecond - AccelerationSpeed.MetersPerSecond) / (data.TotalTime.Seconds - AccelerationTime.Seconds), 4); AccelerationTime = data.TotalTime; AccelerationSpeed = State.Speed; } // Retrieve data from all devices foreach (Device dev in Devices) { dev.Update(this, route, OpenbveFcmbTrainPlugin.Initializing, data.ElapsedTime); data.DoorInterlockState |= dev.RequestedDoorInterlock; if (dev.RequestedPowerNotch != -1) data.Handles.PowerNotch = dev.RequestedPowerNotch; if (dev.RequestedBrakeNotch != -1) data.Handles.BrakeNotch = dev.RequestedBrakeNotch; } } /// <summary>Is called when the driver changes the reverser.</summary> /// <param name="reverser">The new reverser position.</param> internal void SetReverser(int reverser) { PhysicalHandles.Reverser = reverser; } /// <summary>Is called when the driver changes the power notch.</summary> /// <param name="powerNotch">The new power notch.</param> internal void SetPower(int powerNotch) { PhysicalHandles.PowerNotch = powerNotch; } /// <summary>Is called when the driver changes the brake notch.</summary> /// <param name="brakeNotch">The new brake notch.</param> internal void SetBrake(int brakeNotch) { PhysicalHandles.BrakeNotch = brakeNotch; } /// <summary>Is called when a key is pressed.</summary> /// <param name="key">The key.</param> internal void KeyDown(VirtualKeys key) { foreach (Device dev in Devices) { dev.KeyChange(key, true, this); } } /// <summary>Is called when a key is released.</summary> /// <param name="key">The key.</param> internal void KeyUp(VirtualKeys key) { foreach (Device dev in Devices) { dev.KeyChange(key, false, this); } } /// <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 void DoorChange(DoorStates oldState, DoorStates newState) { PreviousDoorState = oldState; DoorState = newState; foreach (Device dev in Devices) { dev.DoorChange(oldState, 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 void HornBlow(HornTypes type) { } /// <summary>Is called to inform about signals.</summary> /// <param name="signal">The signal data.</param> internal void SetSignal(SignalData[] signal) { } /// <summary>Is called when a beacon is passed.</summary> /// <param name="beacon">The beacon data.</param> internal void SetBeacon(BeaconData beacon) { foreach (Device dev in Devices) { dev.SetBeacon(beacon); } } /// <summary>Is called when the plugin should perform the AI.</summary> /// <param name="data">The AI data.</param> /// <param name="route">The route data.</param> internal void PerformAI(AIData data, Route route) { foreach (Device dev in Devices) { dev.PerformAI(data, this, route); } } } }