diff --git a/src/Devices/Doors.cs b/src/Devices/Doors.cs index 26ed1e4..d943dca 100644 --- a/src/Devices/Doors.cs +++ b/src/Devices/Doors.cs @@ -33,6 +33,21 @@ namespace OpenbveFcmbTrainPlugin /// Whether the AI should trigger the door closing sound. private bool AiTriggerDoorClosingSound; + /// The timeout after which the AI needs to close doors if they become stuck, in seconds. + private double AiDoorStuckTimeout = 10; + + /// The counter for the AI to close doors if they become stuck. + private double AiDoorStuckCounter; + + /// The index of the door closing sound. + private int DoorClosingSoundIndex = 10; + + /// The current time. + private Time CurrentTime = new Time(0); + + /// The time when the doors last opened. + private Time DoorOpenTime = new Time(0); + /// Is called when the device state should be updated. /// The current train. @@ -41,6 +56,9 @@ namespace OpenbveFcmbTrainPlugin /// The time elapsed since the previous call. internal override void Update(Train train, Route route, bool init, Time elapsedTime) { + // Update current time + CurrentTime = route.CurrentTime; + if (init) { if (!RequireDoorClosingSound) @@ -109,8 +127,32 @@ namespace OpenbveFcmbTrainPlugin } // Check if AI needs to trigger the door closing sound - // TODO: check departure time - AiTriggerDoorClosingSound |= (train.DoorState != DoorStates.None && DoorClosingSoundCounter > DoorClosingSoundDuration + DoorClosingSoundTimeout); + if (train.DoorState != DoorStates.None && DoorClosingSoundCounter > DoorClosingSoundDuration + DoorClosingSoundTimeout) + { + if (route.CurrentStation.Type == StationType.Normal || route.CurrentStation.Type == StationType.RequestStop) + { + // The current station is an intermediate stop + if (route.CurrentStation.DepartureTime < 0) + { + // The current station has dwell time, not a specific departure time + // Calculate departure time from the time when the doors opened + AiTriggerDoorClosingSound |= CurrentTime.Seconds >= DoorOpenTime.Seconds + (route.CurrentStation.StopTime - DoorClosingSoundDuration); + } + else + { + // Use departure time - door closing sound duration + AiTriggerDoorClosingSound |= CurrentTime.Seconds >= route.CurrentStation.DepartureTime - DoorClosingSoundDuration; + } + } + else + { + AiTriggerDoorClosingSound = false; + } + } + else + { + AiTriggerDoorClosingSound = false; + } // Update panel variables for door selection state train.Panel[50] = (RequestedDoorInterlock == DoorInterlockStates.Left || RequestedDoorInterlock == DoorInterlockStates.Unlocked) || (((train.DoorState & DoorStates.Left) != 0) && !LeftDoorsClosing) ? 1 : 0; @@ -133,6 +175,10 @@ namespace OpenbveFcmbTrainPlugin // Play the door closing sound and reset timeout DoorClosingSoundCounter = 0; TriggerDoorUnlock = true; + if (!SoundManager.Playing(DoorClosingSoundIndex)) + { + SoundManager.Play(DoorClosingSoundIndex, 1, 1, false); + } } break; case VirtualKeys.G: @@ -189,22 +235,30 @@ namespace OpenbveFcmbTrainPlugin if (!OpenbveFcmbTrainPlugin.KeysPressed[(int)key]) { // Unselect doors automatically when closing - if ((train.DoorState & DoorStates.Left) > 0 && (RequestedDoorInterlock == DoorInterlockStates.Left || RequestedDoorInterlock == DoorInterlockStates.Unlocked)) + if ((train.DoorState & DoorStates.Left) > 0 && !LeftDoorsClosing && (RequestedDoorInterlock == DoorInterlockStates.Left || RequestedDoorInterlock == DoorInterlockStates.Unlocked)) { LeftDoorsClosing = true; RequestedDoorInterlock = RequestedDoorInterlock == DoorInterlockStates.Left ? DoorInterlockStates.Locked : DoorInterlockStates.Right; } + else + { + LeftDoorsClosing = false; + } } 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)) + if ((train.DoorState & DoorStates.Right) > 0 && !RightDoorsClosing && (RequestedDoorInterlock == DoorInterlockStates.Right || RequestedDoorInterlock == DoorInterlockStates.Unlocked)) { RightDoorsClosing = true; RequestedDoorInterlock = RequestedDoorInterlock == DoorInterlockStates.Right ? DoorInterlockStates.Locked : DoorInterlockStates.Left; } + else + { + RightDoorsClosing = false; + } } break; } @@ -246,6 +300,12 @@ namespace OpenbveFcmbTrainPlugin RequestedDoorInterlock = RequestedDoorInterlock == DoorInterlockStates.Right ? DoorInterlockStates.Right : DoorInterlockStates.Locked; } } + + // Set arrival time when doors open + if (oldState == DoorStates.None && newState != DoorStates.None) + { + DoorOpenTime = CurrentTime; + } } /// Is called when the device should perform the AI.