changeset 8305:1e1e16a1129c draft

(svn r11870) -Fix: slow down train when approaching tile we can't enter in more cases (tunnel/bridge/depot from wrong direction, competitor's track, wrong railtype) -Fix: do not make crossing red when we can't enter it in any case
author smatz <smatz@openttd.org>
date Wed, 16 Jan 2008 00:33:28 +0000
parents c697a0fd25be
children ea2c123b3655
files src/train_cmd.cpp
diffstat 1 files changed, 80 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -3250,47 +3250,17 @@
 	225, 210, 195, 180, 165, 150, 135, 120, 105, 90, 75, 60, 45, 30, 15, 15
 };
 
+
 /**
- * Checks for line end. Also, bars crossing at next tile if needed
+ * Train is approaching line end, slow down and possibly reverse
  *
- * @param v vehicle we are checking
- * @return true iff we do NOT have to reverse
+ * @param v front train engine
+ * @param signal not line end, just a red signal
+ * @return true iff we did NOT have to reverse
  */
-static bool TrainCheckIfLineEnds(Vehicle *v)
+static bool TrainApproachingLineEnd(Vehicle *v, bool signal)
 {
-	int t = v->breakdown_ctr;
-	if (t > 1) {
-		v->vehstatus |= VS_TRAIN_SLOWING;
-
-		uint16 break_speed = _breakdown_speeds[GB(~t, 4, 4)];
-		if (break_speed < v->cur_speed) v->cur_speed = break_speed;
-	} else {
-		v->vehstatus &= ~VS_TRAIN_SLOWING;
-	}
-
-	if (v->u.rail.track == TRACK_BIT_WORMHOLE) return true; // exit if inside a tunnel
-	if (v->u.rail.track == TRACK_BIT_DEPOT) return true; // exit if inside a depot
-
-	TileIndex tile = v->tile;
-
-	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
-		DiagDirection dir = GetTunnelBridgeDirection(tile);
-		if (DiagDirToDir(dir) == v->direction) return true;
-	}
-
-	if (IsTileType(tile, MP_RAILWAY) && GetRailTileType(tile) == RAIL_TILE_DEPOT) {
-		DiagDirection dir = ReverseDiagDir(GetRailDepotDirection(tile));
-		if (DiagDirToDir(dir) == v->direction) return true;
-	}
-
-	/* Determine the non-diagonal direction in which we will exit this tile */
-	DiagDirection dir = TrainExitDir(v->direction, v->u.rail.track);
-	/* Calculate next tile */
-	tile += TileOffsByDiagDir(dir);
-	// determine the track status on the next tile.
-	uint32 ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & _reachable_tracks[dir];
-
-	/* Calc position within the current tile ?? */
+	/* Calc position within the current tile */
 	uint x = v->x_pos & 0xF;
 	uint y = v->y_pos & 0xF;
 
@@ -3305,29 +3275,9 @@
 		default: break;
 	}
 
-	if (GB(ts, 0, 16) != 0) {
-		/* If we approach a rail-piece which we can't enter, or the back of a depot, don't enter it! */
-		if (x + 4 >= TILE_SIZE &&
-				(!CheckCompatibleRail(v, tile) ||
-				(IsTileDepotType(tile, TRANSPORT_RAIL) &&
-				GetRailDepotDirection(tile) == dir))) {
-			v->cur_speed = 0;
-			ReverseTrainDirection(v);
-			return false;
-		}
-		if ((ts &= (ts >> 16)) == 0) {
-			/* make a rail/road crossing red
-			 * do not make crossing red behind depot the train is entering */
-			if (IsLevelCrossingTile(tile) && (!IsTileDepotType(v->tile, TRANSPORT_RAIL) || GetRailDepotDirection(v->tile) == dir)) {
-				if (!IsCrossingBarred(tile)) {
-					BarCrossing(tile);
-					SndPlayVehicleFx(SND_0E_LEVEL_CROSSING, v);
-					MarkTileDirtyByTile(tile);
-				}
-			}
-			return true;
-		}
-	} else if (x + 4 >= TILE_SIZE) {
+	/* do not reverse when approaching red signal */
+	if (!signal && x + 4 >= TILE_SIZE) {
+		/* we are too near the tile end, reverse now */
 		v->cur_speed = 0;
 		ReverseTrainDirection(v);
 		return false;
@@ -3342,6 +3292,76 @@
 	return true;
 }
 
+
+/**
+ * Checks for line end. Also, bars crossing at next tile if needed
+ *
+ * @param v vehicle we are checking
+ * @return true iff we did NOT have to reverse
+ */
+static bool TrainCheckIfLineEnds(Vehicle *v)
+{
+	/* First, handle broken down train */
+
+	int t = v->breakdown_ctr;
+	if (t > 1) {
+		v->vehstatus |= VS_TRAIN_SLOWING;
+
+		uint16 break_speed = _breakdown_speeds[GB(~t, 4, 4)];
+		if (break_speed < v->cur_speed) v->cur_speed = break_speed;
+	} else {
+		v->vehstatus &= ~VS_TRAIN_SLOWING;
+	}
+
+	/* Exit if inside a tunnel/bridge or a depot */
+	if (v->u.rail.track == TRACK_BIT_WORMHOLE || v->u.rail.track == TRACK_BIT_DEPOT) return true;
+
+	TileIndex tile = v->tile;
+
+	/* entering a tunnel/bridge? */
+	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
+		DiagDirection dir = GetTunnelBridgeDirection(tile);
+		if (DiagDirToDir(dir) == v->direction) return true;
+	}
+
+	/* entering a depot? */
+	if (IsTileDepotType(tile, TRANSPORT_RAIL)) {
+		DiagDirection dir = ReverseDiagDir(GetRailDepotDirection(tile));
+		if (DiagDirToDir(dir) == v->direction) return true;
+	}
+
+	/* Determine the non-diagonal direction in which we will exit this tile */
+	DiagDirection dir = TrainExitDir(v->direction, v->u.rail.track);
+	/* Calculate next tile */
+	tile += TileOffsByDiagDir(dir);
+
+	/* Determine the track status on the next tile */
+	uint32 ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & _reachable_tracks[dir];
+
+	/* We are sure the train is not entering a depot, it is detected above */
+
+	/* no suitable trackbits at all || wrong railtype || not our track ||
+	 *   tunnel/bridge from opposite side || depot from opposite side */
+	if (GB(ts, 0, 16) == 0 || !CheckCompatibleRail(v, tile) || GetTileOwner(tile) != v->owner ||
+			(IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeDirection(tile) != dir) ||
+			(IsTileDepotType(tile, TRANSPORT_RAIL) && GetRailDepotDirection(tile) == dir) ) {
+		return TrainApproachingLineEnd(v, false);
+	}
+
+	/* approaching red signal */
+	if ((ts & (ts >> 16)) != 0) return TrainApproachingLineEnd(v, true);
+
+	/* approaching a rail/road crossing? then make it red */
+	if (IsLevelCrossingTile(tile) && !IsCrossingBarred(tile)) {
+		BarCrossing(tile);
+		SndPlayVehicleFx(SND_0E_LEVEL_CROSSING, v);
+		MarkTileDirtyByTile(tile);
+	}
+
+	return true;
+}
+
+
 static void TrainLocoHandler(Vehicle *v, bool mode)
 {
 	/* train has crashed? */