From fbfcbe06ec90777a514c42fd928cce2721718891 Mon Sep 17 00:00:00 2001 From: rubidium Date: Wed, 16 Dec 2009 16:23:44 +0000 Subject: [PATCH] (svn r18515) -Change: make it visible when you're to pass the next signal on danger and possible to cancel it -Fix [FS#2891]: when you pass a signal at danger, in a PBS controlled area, don't try to do the 'safe' thing and stop, but continue going; the user wanted the train to pass the signal at danger so (s)he has to suffer the consequences. Ofcourse one can always stop the train manually. --- src/saveload/afterload.cpp | 9 +++++++++ src/train_cmd.cpp | 35 +++++++++++++++++++++++++++++++++-- src/vehicle_gui.cpp | 1 + 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index beba40d2d1..8116b6d17f 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -1967,6 +1967,15 @@ bool AfterLoadGame() } } + /* The behaviour of force_proceed has been changed. Now + * it counts signals instead of some random time out. */ + if (CheckSavegameVersion(131)) { + Train *t; + FOR_ALL_TRAINS(t) { + t->force_proceed = min(t->force_proceed, 1); + } + } + /* Road stops is 'only' updating some caches */ AfterLoadRoadStops(); AfterLoadLabelMaps(); diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 3cd80ed0a1..34d767beca 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1990,6 +1990,9 @@ CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32 ToggleBit(v->flags, VRF_REVERSE_DIRECTION); SetWindowDirty(WC_VEHICLE_DEPOT, v->tile); SetWindowDirty(WC_VEHICLE_DETAILS, v->index); + /* We cancel any 'skip signal at dangers' here */ + v->force_proceed = 0; + SetWindowDirty(WC_VEHICLE_VIEW, v->index); } } else { /* turn the whole train around */ @@ -2007,6 +2010,10 @@ CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32 } } + /* We cancel any 'skip signal at dangers' here */ + v->force_proceed = 0; + SetWindowDirty(WC_VEHICLE_VIEW, v->index); + if (_settings_game.vehicle.train_acceleration_model != TAM_ORIGINAL && v->cur_speed != 0) { ToggleBit(v->flags, VRF_REVERSING); } else { @@ -2033,7 +2040,15 @@ CommandCost CmdForceTrainProceed(TileIndex tile, DoCommandFlag flags, uint32 p1, Train *t = Train::GetIfValid(p1); if (t == NULL || !CheckOwnership(t->owner)) return CMD_ERROR; - if (flags & DC_EXEC) t->force_proceed = 0x50; + if (flags & DC_EXEC) { + /* If we are forced to proceed, cancel that order. + * If we are marked stuck we would want to force the train + * to proceed to the next signal. In the other cases we + * would like to pass the signal at danger and run till the + * next signal we encounter. */ + t->force_proceed = t->force_proceed == 2 ? 0 : HasBit(t->flags, VRF_TRAIN_STUCK) || t->IsInDepot() ? 1 : 2; + SetWindowDirty(WC_VEHICLE_VIEW, t->index); + } return CommandCost(); } @@ -3348,6 +3363,21 @@ static void TrainController(Train *v, Vehicle *nomove) chosen_track = TrackToTrackBits(ChooseTrainTrack(v, gp.new_tile, enterdir, bits, false, NULL, true)); assert(chosen_track & (bits | GetReservedTrackbits(gp.new_tile))); + if (v->force_proceed != 0 && IsPlainRailTile(gp.new_tile) && HasSignals(gp.new_tile)) { + /* For each signal we find decrease the counter by one. + * We start at two, so the first signal we pass decreases + * this to one, then if we reach the next signal it is + * decreased to zero and we won't pass that new signal. */ + Trackdir dir = FindFirstTrackdir(trackdirbits); + if (GetSignalType(gp.new_tile, TrackdirToTrack(dir)) != SIGTYPE_PBS || + !HasSignalOnTrackdir(gp.new_tile, ReverseTrackdir(dir))) { + /* However, we do not want to be stopped by PBS signals + * entered via the back. */ + v->force_proceed--; + SetWindowDirty(WC_VEHICLE_VIEW, v->index); + } + } + /* Check if it's a red signal and that force proceed is not clicked. */ if ((red_signals & chosen_track) && v->force_proceed == 0) { /* In front of a red signal */ @@ -3921,7 +3951,6 @@ static bool TrainLocoHandler(Train *v, bool mode) } if (v->force_proceed != 0) { - v->force_proceed--; ClrBit(v->flags, VRF_TRAIN_STUCK); SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); } @@ -4006,6 +4035,8 @@ static bool TrainLocoHandler(Train *v, bool mode) /* we need to invalidate the widget if we are stopping from 'Stopping 0 km/h' to 'Stopped' */ if (v->cur_speed == 0 && v->tcache.last_speed == 0 && (v->vehstatus & VS_STOPPED)) { + /* If we manually stopped, we're not force-proceeding anymore. */ + v->force_proceed = 0; SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); } diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index a9401784f2..d4cd7212e6 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -1959,6 +1959,7 @@ public: this->SetWidgetDisabledState(VVW_WIDGET_CLONE_VEH, !is_localcompany); if (v->type == VEH_TRAIN) { + this->SetWidgetLoweredState(VVW_WIDGET_FORCE_PROCEED, Train::From(v)->force_proceed == 2); this->SetWidgetDisabledState(VVW_WIDGET_FORCE_PROCEED, !is_localcompany); this->SetWidgetDisabledState(VVW_WIDGET_TURN_AROUND, !is_localcompany); }