changeset 13977:bb2258bdc43d draft

(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.
author rubidium <rubidium@openttd.org>
date Wed, 16 Dec 2009 16:23:44 +0000
parents 9e8eabc11352
children fefa1393f0a9
files src/saveload/afterload.cpp src/train_cmd.cpp src/vehicle_gui.cpp
diffstat 3 files changed, 43 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -1967,6 +1967,15 @@
 		}
 	}
 
+	/* 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<byte>(t->force_proceed, 1);
+		}
+	}
+
 	/* Road stops is 'only' updating some caches */
 	AfterLoadRoadStops();
 	AfterLoadLabelMaps();
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -1990,6 +1990,9 @@
 			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 @@
 				}
 			}
 
+			/* 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 @@
 	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 @@
 					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 @@
 	}
 
 	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 @@
 
 	/* 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);
 	}
 
--- a/src/vehicle_gui.cpp
+++ b/src/vehicle_gui.cpp
@@ -1959,6 +1959,7 @@
 		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);
 		}