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;
}
}
}