changeset 9840:b2082b3c8224 draft

(svn r13983) -Fix (r13953) [YAPP]: Crashed trains can be on different trackbits. Make sure there is still a track reservation when one vehicle is cleaned up.
author frosch <frosch@openttd.org>
date Sun, 03 Aug 2008 19:04:11 +0000
parents 6d9cff756b2f
children 1f45eff04187
files src/train_cmd.cpp
diffstat 1 files changed, 34 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -3834,6 +3834,20 @@
 	ReverseTrainDirection(v);
 }
 
+/** Collect trackbits of all crashed train vehicles on a tile
+ * @param v Vehicle passed from VehicleFromPos()
+ * @param data trackdirbits for the result
+ * @return NULL to not abort VehicleFromPos()
+ */
+static Vehicle *CollectTrackbitsFromCrashedVehiclesEnum(Vehicle *v, void *data)
+{
+	TrackBits *trackbits = (TrackBits *)data;
+
+	if (v->type == VEH_TRAIN && (v->vehstatus & VS_CRASHED) != 0) *trackbits |= v->u.rail.track;
+
+	return NULL;
+}
+
 /**
  * Deletes/Clears the last wagon of a crashed train. It takes the engine of the
  * train, then goes to the last wagon and deletes that. Each call to this function
@@ -3870,19 +3884,30 @@
 
 	MarkSingleVehicleDirty(v);
 
-	/* Clear a possible path reservation */
-	if ((IsFrontEngine(v) && !(v->u.rail.track & TRACK_BIT_DEPOT))
-			|| ((v->u.rail.track & ~TRACK_BIT_MASK) == TRACK_BIT_NONE && (v->tile != u->tile || (u->u.rail.track & ~TRACK_BIT_MASK) != TRACK_BIT_NONE))) {
-		if (HasReservedTracks(v->tile, v->u.rail.track)) UnreserveRailTrack(v->tile, TrackBitsToTrack(v->u.rail.track));
-	}
-
 	/* 'v' shouldn't be accessed after it has been deleted */
-	TrackBits track = v->u.rail.track;
+	TrackBits trackbits = v->u.rail.track;
+	Track track = TrackBitsToTrack(trackbits);
 	TileIndex tile = v->tile;
 	Owner owner = v->owner;
 
 	delete v;
-	v = NULL; // make sure nobody will won't try to read 'v' anymore
+	v = NULL; // make sure nobody will try to read 'v' anymore
+
+	if (HasReservedTracks(tile, trackbits)) {
+		UnreserveRailTrack(tile, track);
+
+		/* If there are still crashed vehicles on the tile, give the track reservation to them */
+		TrackBits remaining_trackbits = TRACK_BIT_NONE;
+		VehicleFromPos(tile, &remaining_trackbits, CollectTrackbitsFromCrashedVehiclesEnum);
+
+		/* It is important that these two are the first in the loop, as reservation cannot deal with every trackbit combination */
+		assert(TRACK_BEGIN == TRACK_X && TRACK_Y == TRACK_BEGIN + 1);
+		for (Track t = TRACK_BEGIN; t < TRACK_END; t++) {
+			if (HasBit(remaining_trackbits, t)) {
+				TryReserveRailTrack(tile, t);
+			}
+		}
+	}
 
 	/* check if the wagon was on a road/rail-crossing */
 	if (IsLevelCrossingTile(tile)) UpdateLevelCrossing(tile);
@@ -3891,7 +3916,7 @@
 	if (IsTileType(tile, MP_TUNNELBRIDGE) || IsRailDepotTile(tile)) {
 		UpdateSignalsOnSegment(tile, INVALID_DIAGDIR, owner);
 	} else {
-		SetSignalsOnBothDir(tile, (Track)(FIND_FIRST_BIT(track)), owner);
+		SetSignalsOnBothDir(tile, track, owner);
 	}
 }