From 0b4b9dd76429f247a13a165e6841ffc334345e49 Mon Sep 17 00:00:00 2001 From: smatz Date: Fri, 17 Jul 2009 13:54:06 +0000 Subject: [PATCH] (svn r16857) -Fix [FS#3036](r16652): crash when train partially in depot crashed --- src/saveload/afterload.cpp | 13 ++---------- src/train.h | 1 + src/train_cmd.cpp | 42 +++++++++++++++++++++++++------------- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index a26ef0e6b1..7879af4e7f 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -1708,18 +1708,9 @@ bool AfterLoadGame() /* Reserve all tracks trains are currently on. */ if (CheckSavegameVersion(101)) { - Train *t; + const Train *t; FOR_ALL_TRAINS(t) { - switch (t->track) { - case TRACK_BIT_WORMHOLE: - TryReserveRailTrack(t->tile, DiagDirToDiagTrack(GetTunnelBridgeDirection(t->tile))); - break; - case TRACK_BIT_DEPOT: - break; - default: - TryReserveRailTrack(t->tile, TrackBitsToTrack(t->track)); - break; - } + if (t->First() == t) t->ReserveTrackUnderConsist(); } } diff --git a/src/train.h b/src/train.h index aba89633d5..8dca09f965 100644 --- a/src/train.h +++ b/src/train.h @@ -134,6 +134,7 @@ struct Train : public SpecializedVehicle { TileIndex GetOrderStationLocation(StationID station); bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse); + void ReserveTrackUnderConsist() const; /** * enum to handle train subtypes diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 3a4dde6a9c..3319f34034 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -3470,6 +3470,24 @@ static bool TrainMovedChangeSignals(TileIndex tile, DiagDirection dir) return false; } +/** + * Tries to reserve track under whole train consist + */ +void Train::ReserveTrackUnderConsist() const +{ + for (const Train *u = this; u != NULL; u = u->Next()) { + switch (u->track) { + case TRACK_BIT_WORMHOLE: + TryReserveRailTrack(u->tile, DiagDirToDiagTrack(GetTunnelBridgeDirection(u->tile))); + break; + case TRACK_BIT_DEPOT: + break; + default: + TryReserveRailTrack(u->tile, TrackBitsToTrack(u->track)); + break; + } + } +} static void SetVehicleCrashed(Train *v) { @@ -3532,24 +3550,20 @@ static uint CountPassengersInTrain(const Train *v) */ static uint TrainCrashed(Train *v) { - /* Try to re-reserve track under already crashed train too */ - for (const Train *u = v; u != NULL; u = u->Next()) { - TrackBits trackbits = u->track; - if (trackbits == TRACK_BIT_WORMHOLE) { - /* Vehicle is inside a wormhole, v->track contains no useful value then. */ - trackbits = DiagDirToDiagTrackBits(GetTunnelBridgeDirection(u->tile)); - } - TryReserveRailTrack(u->tile, TrackBitsToTrack(trackbits)); - } + uint num = 0; /* do not crash train twice */ - if (v->vehstatus & VS_CRASHED) return 0; + if (!(v->vehstatus & VS_CRASHED)) { + /* two drivers + passengers */ + num = 2 + CountPassengersInTrain(v); - /* two drivers + passengers */ - uint num = 2 + CountPassengersInTrain(v); + SetVehicleCrashed(v); + AI::NewEvent(v->owner, new AIEventVehicleCrashed(v->index, v->tile, AIEventVehicleCrashed::CRASH_TRAIN)); + } - SetVehicleCrashed(v); - AI::NewEvent(v->owner, new AIEventVehicleCrashed(v->index, v->tile, AIEventVehicleCrashed::CRASH_TRAIN)); + /* Try to re-reserve track under already crashed train too. + * SetVehicleCrashed() clears the reservation! */ + v->ReserveTrackUnderConsist(); return num; }