diff options
author | frosch <frosch@openttd.org> | 2008-08-03 19:04:11 +0000 |
---|---|---|
committer | frosch <frosch@openttd.org> | 2008-08-03 19:04:11 +0000 |
commit | 8644a8915eaa8a1f79f0b7169bf526650029201e (patch) | |
tree | a8105d87eee8a661743f95231f61e649efd761eb | |
parent | a5913396f0809c530175a96b6c6d3dba52598ca3 (diff) | |
download | openttd-8644a8915eaa8a1f79f0b7169bf526650029201e.tar.xz |
(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.
-rw-r--r-- | src/train_cmd.cpp | 43 |
1 files changed, 34 insertions, 9 deletions
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 42c7806be..5db19dcd9 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -3834,6 +3834,20 @@ reverse_train_direction: 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 @@ static void DeleteLastWagon(Vehicle *v) 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 @@ static void DeleteLastWagon(Vehicle *v) 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); } } |