Skip to content

Commit

Permalink
Merge pull request #984 from Csantucci/timetable-player-train-switchi…
Browse files Browse the repository at this point in the history
…ng-official

Player train switching for timetable mode
  • Loading branch information
Csantucci authored Nov 9, 2024
2 parents b9b863c + 0f8122e commit e2338fd
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 21 deletions.
27 changes: 13 additions & 14 deletions Source/Documentation/Manual/driving.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1411,7 +1411,8 @@ Changing the Train Driven by the Player
General
-------

This function only works in activity mode, and allows the player to select
This function works in activity mode as well as in timetable mode,
and allows the player to select
another (existing) train from a list and to start driving it.

This function can be called more than once. A new information window has
Expand Down Expand Up @@ -1453,17 +1454,20 @@ completely appeared on the screen - if it is far away from the player train
this can require several seconds to load the *world* around the train) the
switch of control occurs.

The AI train string now becomes red and is moved to the first position.The
train can be driven, or set to autopilot mode. The former player train
becomes an AI train.
The AI train string now becomes red and is moved to the first position.
In timetable mode the new player train is automatically set to autopilot mode,
while this does not apply to activity mode. However in both timetable and
activity mode the player can switch forth and back to autopilot mode.
The former player train becomes an AI train.

Here is the final situation:

.. image:: images/driving-train-list-3.png
:align: center
:scale: 80%

If the second left-click was performed with the Shift key down, the former
In activity mode only, if the second left-click was performed with the Shift
key down, the former
player train still becomes an AI train, but it is put in a suspended mode
(only if its speed is 0). It won't move until it becomes a player train
again. A suspended train is shown in orange color on the Train List window.
Expand All @@ -1472,7 +1476,8 @@ The new player train can can be switched to manual mode, can also request to
pass signals at danger with the ``<Tab>`` command, and can be moved outside
of its original path. However before switching control to still another train,
the new player train must be returned to the original path or put in suspend
mode; or else it will disappear, as occurs for AI trains running outside their
mode (last is possible only in activity mode); or else it will disappear,
as occurs for AI trains running outside their
path.

The sequence may be restarted to switch to a new train or to switch back to
Expand All @@ -1482,15 +1487,9 @@ Train switching also works in activity mode together with multiplayer mode,
in the sense that the dispatcher player can switch its played train, and
the related information is sent to the client players.

The Train List window is also available in
:ref:`Timetable mode <start-timetable>`. In this case the
names of all trains except the player train are shown in white (they can't
be driven), however with a single click on a train in the window the
external view cameras become linked to that train, as occurs with the Alt-9
command described :ref:`further below <driving-changing-view>`.

Switching to a static train
---------------------------
Switching to a static train (only activity mode)
------------------------------------------------

In the Train List window the drivable static consists (that is the ones
that have at least an engine provided with a cab) are also listed (in
Expand Down
33 changes: 29 additions & 4 deletions Source/Orts.Simulation/Simulation/Simulator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1921,6 +1921,13 @@ private void StartSwitchPlayerTrain()
var playerTrain = PlayerLocomotive.Train as AITrain;
if (playerTrain != null)
{
if (TimetableMode && playerTrain.ControlMode == Train.TRAIN_CONTROL.MANUAL)
{
Confirmer.Message(ConfirmLevel.Warning, Catalog.GetString("Train can't be switched if in manual mode"));
TrainSwitcher.SuspendOldPlayer = false;
TrainSwitcher.ClickedSelectedAsPlayer = false;
return;
}
if (playerTrain.ControlMode == Train.TRAIN_CONTROL.MANUAL) TrainSwitcher.SuspendOldPlayer = true; // force suspend state to avoid disappearing of train;
if (TrainSwitcher.SuspendOldPlayer &&
(playerTrain.SpeedMpS < -0.025 || playerTrain.SpeedMpS > 0.025 || playerTrain.PresentPosition[0].TCOffset != playerTrain.PreviousPosition[0].TCOffset))
Expand All @@ -1930,14 +1937,14 @@ private void StartSwitchPlayerTrain()
TrainSwitcher.ClickedSelectedAsPlayer = false;
return;
}
if (playerTrain.TrainType == Train.TRAINTYPE.AI_PLAYERDRIVEN)
if (playerTrain.TrainType == Train.TRAINTYPE.AI_PLAYERDRIVEN || !playerTrain.Autopilot)
{
// it must be autopiloted first
playerTrain.SwitchToAutopilotControl();
}
// and now switch!
playerTrain.TrainType = Train.TRAINTYPE.AI;
AI.AITrains.Add(playerTrain);
playerTrain.Autopilot = false;
if (TrainSwitcher.SuspendOldPlayer)
{
playerTrain.MovementState = AITrain.AI_MOVEMENT_STATE.SUSPENDED;
Expand Down Expand Up @@ -2089,6 +2096,18 @@ private void StartSwitchPlayerTrain()
PlayerLocomotive = SetPlayerLocomotive(pathlessPlayerTrain);
if (oldPlayerTrain != null) oldPlayerTrain.LeadLocomotiveIndex = -1;
}
if (TimetableMode)
{
// In timetable mode player train must have number 0
(PlayerLocomotive.Train.Number, oldPlayerTrain.Number) = (oldPlayerTrain.Number, PlayerLocomotive.Train.Number);
var oldPlayerTrainIndex = Trains.IndexOf(oldPlayerTrain);
var playerTrainIndex = Trains.IndexOf(PlayerLocomotive.Train);
(Trains[oldPlayerTrainIndex], Trains[playerTrainIndex]) = (Trains[playerTrainIndex], Trains[oldPlayerTrainIndex]);
var index = AI.AITrains.IndexOf(PlayerLocomotive.Train as AITrain);
(AI.AITrains[0], AI.AITrains[index]) = (AI.AITrains[index], AI.AITrains[0]);
AI.aiListChanged = true;
PlayerLocomotive.Train.Autopilot = true;
}
playerSwitchOngoing = true;
if (MPManager.IsMultiPlayer())
{
Expand All @@ -2107,19 +2126,25 @@ private void CompleteSwitchPlayerTrain()
{
if (PlayerLocomotive.Train.TrainType != Train.TRAINTYPE.STATIC)
{
AI.AITrains.Remove(PlayerLocomotive.Train as AITrain);
if (!TimetableMode)
AI.AITrains.Remove(PlayerLocomotive.Train as AITrain);
if ((PlayerLocomotive.Train as AITrain).MovementState == AITrain.AI_MOVEMENT_STATE.SUSPENDED)
{
PlayerLocomotive.Train.Reinitialize();
(PlayerLocomotive.Train as AITrain).MovementState = Math.Abs(PlayerLocomotive.Train.SpeedMpS) <= MaxStoppedMpS ?
AITrain.AI_MOVEMENT_STATE.INIT : AITrain.AI_MOVEMENT_STATE.BRAKING;
}
(PlayerLocomotive.Train as AITrain).SwitchToPlayerControl();
if (!TimetableMode)
(PlayerLocomotive.Train as AITrain).SwitchToPlayerControl();
else
PlayerLocomotive.Train.DisplayMessage = "";
}
else
{
PlayerLocomotive.Train.CreatePathlessPlayerTrain();
}
var playerLocomotive = PlayerLocomotive as MSTSLocomotive;
playerLocomotive.UsingRearCab = (PlayerLocomotive.Flipped ^ PlayerLocomotive.Train.MUDirection == Direction.Reverse) && (playerLocomotive.HasRearCab || playerLocomotive.HasRear3DCab);
OnPlayerLocomotiveChanged();
playerSwitchOngoing = false;
TrainSwitcher.ClickedSelectedAsPlayer = false;
Expand Down
6 changes: 3 additions & 3 deletions Source/RunActivity/Viewer3D/Popups/TrainListWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ protected override ControlLayout Layout(ControlLayout layout)
line.Add(viewed = new TrainLabel(Owner.TextFontDefault.Height, line.RemainingHeight, Owner.Viewer, thisTrain, "*", LabelAlignment.Right));
viewed.Color = Color.Red;
}
if (Owner.Viewer.Simulator.IsAutopilotMode && !Owner.Viewer.Simulator.TimetableMode)
if (Owner.Viewer.Simulator.IsAutopilotMode)
{
number.Color = thisTrain.IsPlayable ? Color.LightGreen : Color.White;
name.Color = thisTrain.IsPlayable ? Color.LightGreen : Color.White;
Expand All @@ -110,7 +110,7 @@ protected override ControlLayout Layout(ControlLayout layout)
}

// Now list static trains with loco and cab
if (Owner.Viewer.Simulator.IsAutopilotMode && !Owner.Viewer.Simulator.TimetableMode)
if (Owner.Viewer.Simulator.IsAutopilotMode)
{
foreach (var thisTrain in Owner.Viewer.Simulator.Trains)
{
Expand Down Expand Up @@ -181,7 +181,7 @@ void TrainListLabel_Click(Control arg1, Point arg2)
}
if (PickedTrainFromList != null && (PickedTrainFromList == Viewer.SelectedTrain || (PickedTrainFromList.TrainType == Train.TRAINTYPE.AI_INCORPORATED &&
(PickedTrainFromList as AITrain).IncorporatingTrain.IsPathless && (PickedTrainFromList as AITrain).IncorporatingTrain == Viewer.SelectedTrain)) && !PickedTrainFromList.IsActualPlayerTrain &&
Viewer.Simulator.IsAutopilotMode && PickedTrainFromList.IsPlayable && !Viewer.Simulator.TimetableMode)
Viewer.Simulator.IsAutopilotMode && PickedTrainFromList.IsPlayable && !(Viewer.Simulator.TimetableMode && (Viewer.PlayerTrain as AITrain).MovementState == AITrain.AI_MOVEMENT_STATE.AI_STATIC))
{
if (UserInput.IsDown(UserCommand.GameSuspendOldPlayer) && !Viewer.Simulator.TimetableMode)
Viewer.Simulator.TrainSwitcher.SuspendOldPlayer = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,7 @@ void InitSimulator(UserSettings settings, string[] args, string mode, string act
// for resume and replay : set timetable file and selected train info
Simulator.TimetableFileName = System.IO.Path.GetFileNameWithoutExtension(args[0]);
Simulator.PathName = args[1];
Simulator.IsAutopilotMode = true;
}
break;
}
Expand Down

0 comments on commit e2338fd

Please sign in to comment.