using System.Collections.Generic; using OpenBveApi.Runtime; namespace OpenbveFcmbTrainPlugin { internal class Route { /// Represents the state of the current station. internal enum StationStates { /// The train has not arrived at the station yet. Pending = 0, /// The train has arrived at the station. Arrived = 1, /// The train is ready to depart. Completed = 2, } /// The state of the current station. internal StationStates StationState { get; private set; } = StationStates.Arrived; /// The list of stations in the route. internal List Stations; /// The current station in the route. internal Station CurrentStation; /// The next station in the route. internal Station NextStation; /// The current state of the train doors. private DoorStates DoorState; /// The previous state of the train doors. private DoorStates PreviousDoorState; /// Is called every frame. /// The data passed to the plugin. internal void Elapse(ElapseData data) { if (OpenbveFcmbTrainPlugin.Initializing) { // Get the list of stations and set the current station Stations = data.Stations; UpdateStationData(data.Vehicle.Location); } if (StationState == StationStates.Completed && data.Vehicle.Location > CurrentStation.StopPosition + CurrentStation.ForwardTolerance) { // The train is heading for the next station StationState = StationStates.Pending; UpdateStationData(data.Vehicle.Location); } if (StationState == StationStates.Pending && data.Vehicle.Location > CurrentStation.StopPosition + CurrentStation.ForwardTolerance + 100) { // The train has passed the station without stopping UpdateStationData(data.Vehicle.Location); } // Update station status after closing the doors if (StationState == StationStates.Arrived && DoorState == DoorStates.None) { // The train is ready to leave the station StationState = StationStates.Completed; } // Check if the train is at a station where the doors should open bool ArrivedDoorStop = (PreviousDoorState == DoorStates.None && DoorState != DoorStates.None && (CurrentStation.OpenLeftDoors || CurrentStation.OpenRightDoors)); // Check if the train is at a station where the doors should not open bool ArrivedNoDoorStop = (DoorState == DoorStates.None && !CurrentStation.OpenLeftDoors && !CurrentStation.OpenRightDoors); if (StationState == StationStates.Pending && (ArrivedDoorStop || ArrivedNoDoorStop) && data.Vehicle.Speed.KilometersPerHour < 0.05 && data.Vehicle.Location >= CurrentStation.DefaultTrackPosition) { // The train has arrived at the station StationState = StationStates.Arrived; } } /// Is called when the state of the doors changes. /// The old state of the doors. /// The new state of the doors. internal void DoorChange(DoorStates oldState, DoorStates newState) { PreviousDoorState = oldState; DoorState = newState; } /// Updates the data for the current and next station. /// The current location of the train. internal void UpdateStationData(double location) { // Calculate the index of the current station double position = location; int currentIndex = 0; if (Stations.Count > 1) { while (currentIndex > 0 && (Stations[currentIndex].StopPosition + Stations[currentIndex].ForwardTolerance > position || !Stations[currentIndex].PlayerStops())) { // Detects the station index when driving or jumping backwards currentIndex--; } while (currentIndex < Stations.Count - 1 && (Stations[currentIndex].StopPosition + Stations[currentIndex].ForwardTolerance <= position || !Stations[currentIndex].PlayerStops())) { // Detects the station index when driving or jumping forwards currentIndex++; } } CurrentStation = Stations[currentIndex]; NextStation = currentIndex < Stations.Count - 1 ? Stations[currentIndex + 1] : null; } } }