(svn r16857) -Fix [FS#3036](r16652): crash when train partially in depot crashed

This commit is contained in:
smatz 2009-07-17 13:54:06 +00:00
parent 70472e2d98
commit 0b4b9dd764
3 changed files with 31 additions and 25 deletions

View File

@ -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();
}
}

View File

@ -134,6 +134,7 @@ struct Train : public SpecializedVehicle<Train, VEH_TRAIN> {
TileIndex GetOrderStationLocation(StationID station);
bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
void ReserveTrackUnderConsist() const;
/**
* enum to handle train subtypes

View File

@ -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;
}