Пример #1
0
 /// <summary>Called when the plugin is loaded.</summary>
 /// <param name="host">The host that loaded the plugin.</param>
 /// <param name="fileSystem"></param>
 /// <param name="Options"></param>
 /// <param name="trainManagerReference"></param>
 public override void Load(HostInterface host, FileSystem fileSystem, BaseOptions Options, object trainManagerReference)
 {
     CurrentHost    = host;
     FileSystem     = fileSystem;
     CurrentOptions = Options;
     if (trainManagerReference is TrainManagerBase)
     {
         TrainManager = (TrainManagerBase)trainManagerReference;
     }
 }
Пример #2
0
        /// <summary>Is called once a frame to update the station state for the train</summary>
        /// <param name="TimeElapsed">The frame time elapsed</param>
        private void UpdateStation(double TimeElapsed)
        {
            if (Station >= 0)
            {
                int    i = Station;
                int    n = TrainManagerBase.CurrentRoute.Stations[Station].GetStopIndex(NumberOfCars);
                double tf, tb;
                if (n >= 0)
                {
                    double p0 = Cars[0].FrontAxle.Follower.TrackPosition - Cars[0].FrontAxle.Position + 0.5 * Cars[0].Length;
                    double p1 = TrainManagerBase.CurrentRoute.Stations[i].Stops[n].TrackPosition;
                    tf = TrainManagerBase.CurrentRoute.Stations[i].Stops[n].ForwardTolerance;
                    tb = TrainManagerBase.CurrentRoute.Stations[i].Stops[n].BackwardTolerance;
                    StationDistanceToStopPoint = p1 - p0;
                }
                else
                {
                    StationDistanceToStopPoint = 0.0;
                    tf = 5.0;
                    tb = 5.0;
                }

                if (StationState == TrainStopState.Pending)
                {
                    StationDepartureSoundPlayed = false;
                    if (TrainManagerBase.CurrentRoute.Stations[i].StopsHere(this))
                    {
                        StationDepartureSoundPlayed = false;
                        //Check whether all doors are controlled by the driver
                        if (Specs.DoorOpenMode != DoorMode.Manual)
                        {
                            //Check that we are not moving
                            if (Math.Abs(CurrentSpeed) < 0.1 / 3.6 &
                                Math.Abs(Specs.CurrentAverageAcceleration) < 0.1 / 3.6)
                            {
                                AttemptToOpenDoors(TrainManagerBase.CurrentRoute.Stations[i], tb, tf);
                            }
                        }

                        // detect arrival
                        if (CurrentSpeed > -0.277777777777778 & CurrentSpeed < 0.277777777777778)
                        {
                            bool left, right;
                            if (TrainManagerBase.CurrentRoute.Stations[i].OpenLeftDoors)
                            {
                                left = false;
                                for (int j = 0; j < Cars.Length; j++)
                                {
                                    if (Cars[j].Doors[0].AnticipatedOpen)
                                    {
                                        left = true;
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                left = true;
                            }

                            if (TrainManagerBase.CurrentRoute.Stations[i].OpenRightDoors)
                            {
                                right = false;
                                for (int j = 0; j < Cars.Length; j++)
                                {
                                    if (Cars[j].Doors[1].AnticipatedOpen)
                                    {
                                        right = true;
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                right = true;
                            }

                            if (left & right)
                            {
                                // arrival
                                StationState = TrainStopState.Boarding;
                                SafetySystems.StationAdjust.Lit = false;
                                Specs.DoorClosureAttempted      = false;
                                SafetySystems.PassAlarm.Halt();
                                SoundBuffer buffer = (SoundBuffer)TrainManagerBase.CurrentRoute.Stations[i].ArrivalSoundBuffer;
                                if (buffer != null)
                                {
                                    OpenBveApi.Math.Vector3 pos = TrainManagerBase.CurrentRoute.Stations[i].SoundOrigin;
                                    TrainManagerBase.currentHost.PlaySound(buffer, 1.0, 1.0, pos, null, false);
                                }

                                StationArrivalTime   = TrainManagerBase.CurrentRoute.SecondsSinceMidnight;
                                StationDepartureTime = TrainManagerBase.CurrentRoute.Stations[i].DepartureTime - TimetableDelta;
                                if (StationDepartureTime - TrainManagerBase.CurrentRoute.SecondsSinceMidnight < TrainManagerBase.CurrentRoute.Stations[i].StopTime)
                                {
                                    StationDepartureTime = TrainManagerBase.CurrentRoute.SecondsSinceMidnight + TrainManagerBase.CurrentRoute.Stations[i].StopTime;
                                }

                                Passengers.PassengerRatio = TrainManagerBase.CurrentRoute.Stations[i].PassengerRatio;
                                TrainManagerBase.UpdateTrainMassFromPassengerRatio(this);
                                if (IsPlayerTrain)
                                {
                                    double early = 0.0;
                                    if (TrainManagerBase.CurrentRoute.Stations[i].ArrivalTime >= 0.0)
                                    {
                                        early = (TrainManagerBase.CurrentRoute.Stations[i].ArrivalTime - TimetableDelta) - StationArrivalTime;
                                    }

                                    string s;
                                    if (early < -1.0)
                                    {
                                        s = Translations.GetInterfaceString("message_station_arrival_late");
                                    }
                                    else if (early > 1.0)
                                    {
                                        s = Translations.GetInterfaceString("message_station_arrival_early");
                                    }
                                    else
                                    {
                                        s = Translations.GetInterfaceString("message_station_arrival");
                                    }

                                    System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
                                    TimeSpan a = TimeSpan.FromSeconds(Math.Abs(early));
                                    string   b = a.Hours.ToString("00", Culture) + ":" + a.Minutes.ToString("00", Culture) + ":" + a.Seconds.ToString("00", Culture);
                                    if (StationDistanceToStopPoint < -0.1)
                                    {
                                        s += Translations.GetInterfaceString("message_delimiter") + Translations.GetInterfaceString("message_station_overrun");
                                    }
                                    else if (StationDistanceToStopPoint > 0.1)
                                    {
                                        s += Translations.GetInterfaceString("message_delimiter") + Translations.GetInterfaceString("message_station_underrun");
                                    }

                                    double d = Math.Abs(StationDistanceToStopPoint);
                                    string c = d.ToString("0.0", Culture);
                                    if (TrainManagerBase.CurrentRoute.Stations[i].Type == StationType.Terminal)
                                    {
                                        s += Translations.GetInterfaceString("message_delimiter") + Translations.GetInterfaceString("message_station_terminal");
                                    }

                                    s = s.Replace("[name]", TrainManagerBase.CurrentRoute.Stations[i].Name);
                                    s = s.Replace("[time]", b);
                                    s = s.Replace("[difference]", c);
                                    TrainManagerBase.currentHost.AddMessage(s, MessageDependency.StationArrival, GameMode.Normal, MessageColor.White, TrainManagerBase.CurrentRoute.SecondsSinceMidnight + 10.0, null);
                                    if (TrainManagerBase.CurrentRoute.Stations[i].Type == StationType.Normal)
                                    {
                                        s = Translations.GetInterfaceString("message_station_deadline");
                                        TrainManagerBase.currentHost.AddMessage(s, MessageDependency.StationDeparture, GameMode.Normal, MessageColor.White, double.PositiveInfinity, null);
                                    }

                                    TrainManagerBase.currentHost.UpdateCustomTimetable(TrainManagerBase.CurrentRoute.Stations[i].TimetableDaytimeTexture, TrainManagerBase.CurrentRoute.Stations[i].TimetableNighttimeTexture);
                                }

                                // schedule door locks (passengers stuck between the doors)
                                for (int j = 0; j < Cars.Length; j++)
                                {
                                    for (int k = 0; k < Cars[j].Doors.Length; k++)
                                    {
                                        Cars[j].Doors[k].DoorLockDuration = 0.0;
                                        if (TrainManagerBase.CurrentRoute.Stations[i].OpenLeftDoors & Cars[j].Doors[k].Direction == -1 | TrainManagerBase.CurrentRoute.Stations[i].OpenRightDoors & Cars[j].Doors[k].Direction == 1)
                                        {
                                            double p = 0.005 * TrainManagerBase.CurrentRoute.Stations[i].PassengerRatio * TrainManagerBase.CurrentRoute.Stations[i].PassengerRatio * TrainManagerBase.CurrentRoute.Stations[i].PassengerRatio * TrainManagerBase.CurrentRoute.Stations[i].PassengerRatio;
                                            if (TrainManagerBase.RandomNumberGenerator.NextDouble() < p)
                                            {
                                                /*
                                                 * -- door lock at state --
                                                 * minimum: 0.2 (nearly closed)
                                                 * maximum: 0.8 (nearly opened)
                                                 * */
                                                Cars[j].Doors[k].DoorLockState = 0.2 + 0.6 * TrainManagerBase.RandomNumberGenerator.NextDouble();

                                                /* -- waiting time --
                                                 * minimum: 2.9 s
                                                 * maximum: 40.0 s
                                                 * average: 7.6 s
                                                 * */
                                                p = TrainManagerBase.RandomNumberGenerator.NextDouble();
                                                Cars[j].Doors[k].DoorLockDuration = (50.0 - 10.0 * p) / (17.0 - 16.0 * p);
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                if (SafetySystems.StationAdjust != null)
                                {
                                    SafetySystems.StationAdjust.Update(tb, tf);
                                }
                            }
                        }
                    }
                }
                else if (StationState == TrainStopState.Boarding)
                {
                    for (int j = 0; j < Cars.Length; j++)
                    {
                        if (Cars[j].GetDoorsState(TrainManagerBase.CurrentRoute.Stations[i].OpenLeftDoors, TrainManagerBase.CurrentRoute.Stations[i].OpenRightDoors) == (TrainDoorState.Opened | TrainDoorState.AllOpened))
                        {
                            //Check whether all doors are controlled by the driver, and whether this is a non-standard station type
                            //e.g. Change ends
                            if (Specs.DoorCloseMode != DoorMode.Manual & TrainManagerBase.CurrentRoute.Stations[i].Type == StationType.Normal)
                            {
                                AttemptToCloseDoors();

                                if (Specs.DoorClosureAttempted)
                                {
                                    if (TrainManagerBase.CurrentRoute.Stations[i].OpenLeftDoors && !Cars[j].Doors[0].AnticipatedReopen && TrainManagerBase.RandomNumberGenerator.NextDouble() < TrainManagerBase.CurrentRoute.Stations[i].ReopenDoor)
                                    {
                                        Cars[j].Doors[0].ReopenLimit           = TrainManagerBase.RandomNumberGenerator.Next(1, TrainManagerBase.CurrentRoute.Stations[i].ReopenStationLimit);
                                        Cars[j].Doors[0].ReopenCounter         = 0;
                                        Cars[j].Doors[0].InterferingObjectRate = TrainManagerBase.RandomNumberGenerator.Next(1, TrainManagerBase.CurrentRoute.Stations[i].MaxInterferingObjectRate) * 0.01;
                                        if (Cars[j].Doors[0].InterferingObjectRate * Cars[j].Doors[0].Width >= Cars[j].Doors[0].MaxTolerance)
                                        {
                                            Cars[j].Doors[0].AnticipatedReopen = true;
                                        }
                                    }

                                    if (TrainManagerBase.CurrentRoute.Stations[i].OpenRightDoors && !Cars[j].Doors[1].AnticipatedReopen && TrainManagerBase.RandomNumberGenerator.NextDouble() < TrainManagerBase.CurrentRoute.Stations[i].ReopenDoor)
                                    {
                                        Cars[j].Doors[1].ReopenLimit           = TrainManagerBase.RandomNumberGenerator.Next(1, TrainManagerBase.CurrentRoute.Stations[i].ReopenStationLimit);
                                        Cars[j].Doors[1].ReopenCounter         = 0;
                                        Cars[j].Doors[1].InterferingObjectRate = TrainManagerBase.RandomNumberGenerator.Next(1, TrainManagerBase.CurrentRoute.Stations[i].MaxInterferingObjectRate) * 0.01;
                                        if (Cars[j].Doors[1].InterferingObjectRate * Cars[j].Doors[1].Width >= Cars[j].Doors[1].MaxTolerance)
                                        {
                                            Cars[j].Doors[1].AnticipatedReopen = true;
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // detect departure
                    bool left, right;
                    if (!TrainManagerBase.CurrentRoute.Stations[i].OpenLeftDoors & !TrainManagerBase.CurrentRoute.Stations[i].OpenRightDoors)
                    {
                        left  = true;
                        right = true;
                    }
                    else
                    {
                        if (TrainManagerBase.CurrentRoute.Stations[i].OpenLeftDoors)
                        {
                            left = false;
                            for (int j = 0; j < Cars.Length; j++)
                            {
                                for (int k = 0; k < Cars[j].Doors.Length; k++)
                                {
                                    if (Cars[j].Doors[k].State != 0.0)
                                    {
                                        left = true;
                                        break;
                                    }
                                }

                                if (left)
                                {
                                    break;
                                }
                            }
                        }
                        else
                        {
                            left = false;
                        }

                        if (TrainManagerBase.CurrentRoute.Stations[i].OpenRightDoors)
                        {
                            right = false;
                            for (int j = 0; j < Cars.Length; j++)
                            {
                                for (int k = 0; k < Cars[j].Doors.Length; k++)
                                {
                                    if (Cars[j].Doors[k].State != 0.0)
                                    {
                                        right = true;
                                        break;
                                    }
                                }

                                if (right)
                                {
                                    break;
                                }
                            }
                        }
                        else
                        {
                            right = false;
                        }
                    }

                    // departure sound
                    if (!StationDepartureSoundPlayed)
                    {
                        SoundBuffer buffer = (SoundBuffer)TrainManagerBase.CurrentRoute.Stations[i].DepartureSoundBuffer;
                        if (buffer != null)
                        {
                            if (TrainManagerBase.CurrentRoute.SecondsSinceMidnight >= StationDepartureTime - buffer.Duration)
                            {
                                if (TrainManagerBase.currentHost.SimulationState == SimulationState.Running)
                                {
                                    TrainManagerBase.currentHost.PlaySound(buffer, 1.0, 1.0, TrainManagerBase.CurrentRoute.Stations[i].SoundOrigin, null, false);
                                    StationDepartureSoundPlayed = true;
                                }
                            }
                        }
                    }

                    for (int j = 0; j < Cars.Length; j++)
                    {
                        if (Cars[j].Doors[0].AnticipatedReopen && Cars[j].Doors[0].State == Cars[j].Doors[0].InterferingObjectRate)
                        {
                            if (Cars[j].Doors[0].NextReopenTime == 0.0)
                            {
                                Cars[j].Doors[0].NextReopenTime = TrainManagerBase.CurrentRoute.SecondsSinceMidnight + TrainManagerBase.CurrentRoute.Stations[i].InterferenceInDoor;
                            }
                            else if (Cars[j].Doors[0].ReopenCounter < Cars[j].Doors[0].ReopenLimit)
                            {
                                if (TrainManagerBase.CurrentRoute.SecondsSinceMidnight >= Cars[j].Doors[0].NextReopenTime)
                                {
                                    Cars[j].OpenDoors(true, false);
                                }
                            }
                            else
                            {
                                Cars[j].Doors[0].AnticipatedReopen = false;
                            }
                        }

                        if (Cars[j].Doors[1].AnticipatedReopen && Cars[j].Doors[1].State == Cars[j].Doors[1].InterferingObjectRate)
                        {
                            if (Cars[j].Doors[1].NextReopenTime == 0.0)
                            {
                                Cars[j].Doors[1].NextReopenTime = TrainManagerBase.CurrentRoute.SecondsSinceMidnight + TrainManagerBase.CurrentRoute.Stations[i].InterferenceInDoor;
                            }
                            else if (Cars[j].Doors[1].ReopenCounter < Cars[j].Doors[1].ReopenLimit)
                            {
                                if (TrainManagerBase.CurrentRoute.SecondsSinceMidnight >= Cars[j].Doors[1].NextReopenTime)
                                {
                                    Cars[j].OpenDoors(false, true);
                                }
                            }
                            else
                            {
                                Cars[j].Doors[1].AnticipatedReopen = false;
                            }
                        }
                    }

                    TrainDoorState doorState = GetDoorsState(TrainManagerBase.CurrentRoute.Stations[i].OpenLeftDoors, TrainManagerBase.CurrentRoute.Stations[i].OpenRightDoors);
                    if (left | right)
                    {
                        /*
                         * Assume that passengers only board at a scheduled stop
                         * If the player has opened the doors somewhere else (lineside?)
                         * then passengers should not be boarding
                         */
                        if (doorState != TrainDoorState.AllClosed && TrainManagerBase.CurrentOptions.LoadingSway)
                        {
                            // passengers boarding
                            for (int j = 0; j < Cars.Length; j++)
                            {
                                if (!Cars[j].EnableLoadingSway)
                                {
                                    continue;
                                }
                                double r = 2.0 * TrainManagerBase.CurrentRoute.Stations[i].PassengerRatio * TimeElapsed;
                                if (r >= TrainManagerBase.RandomNumberGenerator.NextDouble())
                                {
                                    int d =
                                        (int)Math.Floor(TrainManagerBase.RandomNumberGenerator.NextDouble() * Cars[j].Doors.Length);
                                    if (Cars[j].Doors[d].State == 1.0)
                                    {
                                        Cars[j].Specs.RollShakeDirection += Cars[j].Doors[d].Direction;
                                    }
                                }
                            }
                        }
                    }

                    if (Specs.DoorCloseMode == DoorMode.Manual || doorState == TrainDoorState.None || doorState == (TrainDoorState.Closed | TrainDoorState.AllClosed) || (TrainManagerBase.CurrentRoute.Stations[Station].Type == StationType.ChangeEnds || TrainManagerBase.CurrentRoute.Stations[Station].Type == StationType.Jump))
                    {
                        if (left | right)
                        {
                            // departure message
                            if (TrainManagerBase.CurrentRoute.SecondsSinceMidnight > StationDepartureTime && (TrainManagerBase.CurrentRoute.Stations[i].Type != StationType.Terminal || IsPlayerTrain == false))
                            {
                                StationState = TrainStopState.Completed;
                                switch (TrainManagerBase.CurrentRoute.Stations[i].Type)
                                {
                                case StationType.Normal:
                                    if (!IsPlayerTrain)
                                    {
                                        break;                                                 // Only trigger messages for the player train
                                    }
                                    if (!TrainManagerBase.CurrentRoute.Stations[i].OpenLeftDoors & !TrainManagerBase.CurrentRoute.Stations[i].OpenRightDoors | Specs.DoorCloseMode != DoorMode.Manual)
                                    {
                                        TrainManagerBase.currentHost.AddMessage(Translations.GetInterfaceString("message_station_depart"), MessageDependency.None, GameMode.Normal, MessageColor.White, TrainManagerBase.CurrentRoute.SecondsSinceMidnight + 5.0, null);
                                    }
                                    else
                                    {
                                        TrainManagerBase.currentHost.AddMessage(Translations.GetInterfaceString("message_station_depart_closedoors"), MessageDependency.None, GameMode.Normal, MessageColor.White, TrainManagerBase.CurrentRoute.SecondsSinceMidnight + 5.0, null);
                                    }

                                    break;

                                case StationType.ChangeEnds:
                                    // Change ends always jumps to the NEXT station
                                    Jump(i + 1);
                                    break;

                                case StationType.Jump:
                                    // Jumps to an arbritrary station as defined in the routefile
                                    Jump(TrainManagerBase.CurrentRoute.Stations[i].JumpIndex);
                                    break;
                                }
                            }
                        }
                        else
                        {
                            StationState = TrainStopState.Completed;
                            if (IsPlayerTrain & TrainManagerBase.CurrentRoute.Stations[i].Type == StationType.Normal)
                            {
                                TrainManagerBase.currentHost.AddMessage(Translations.GetInterfaceString("message_station_depart"), MessageDependency.None, GameMode.Normal, MessageColor.White, TrainManagerBase.CurrentRoute.SecondsSinceMidnight + 5.0, null);
                            }
                        }
                    }
                }
            }
            else
            {
                if (StationState != TrainStopState.Jumping)
                {
                    StationState = TrainStopState.Pending;
                }
            }

            // automatically close doors
            if (Specs.DoorCloseMode != DoorMode.Manual & !Specs.DoorClosureAttempted)
            {
                if (Station == -1 | StationState == TrainStopState.Completed)
                {
                    if ((GetDoorsState(true, true) & TrainDoorState.AllClosed) == 0)
                    {
                        CloseDoors(true, true);
                        Specs.DoorClosureAttempted = true;
                    }
                }
            }
        }