diff options
author | michi_cc <michi_cc@openttd.org> | 2011-11-21 20:51:43 +0000 |
---|---|---|
committer | michi_cc <michi_cc@openttd.org> | 2011-11-21 20:51:43 +0000 |
commit | 4d2a9e384ccb83eec9992ad36459f495bfcfe60f (patch) | |
tree | 26d51a4b166e5dfeff2c1e2bbe753b73df80332b /src/saveload | |
parent | 3748cab60876e98e530c514307e303a071498461 (diff) | |
download | openttd-4d2a9e384ccb83eec9992ad36459f495bfcfe60f.tar.xz |
(svn r23290) -Fix [FS#2379,FS#3569]: Change the centre of train vehicles to depend on the vehicle length instead of being fixed at 4/8th of the original vehicle length to make sure shortened vehicles don't block tiles they shouldn't block.
Diffstat (limited to 'src/saveload')
-rw-r--r-- | src/saveload/afterload.cpp | 3 | ||||
-rw-r--r-- | src/saveload/saveload.cpp | 3 | ||||
-rw-r--r-- | src/saveload/saveload_internal.h | 1 | ||||
-rw-r--r-- | src/saveload/vehicle_sl.cpp | 90 |
4 files changed, 94 insertions, 3 deletions
diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 2fc3e0e5e..97f35e6d4 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -2667,6 +2667,9 @@ bool AfterLoadGame() } } + /* The center of train vehicles was changed, fix up spacing. */ + if (IsSavegameVersionBefore(164)) FixupTrainLengths(); + /* When any NewGRF has been changed the availability of some vehicles might * have been changed too. e->company_avail must be set to 0 in that case * which is done by StartupEngines(). */ diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index c2c158824..e74659d66 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -228,8 +228,9 @@ * 161 22567 * 162 22713 * 163 22767 + * 164 23290 */ -extern const uint16 SAVEGAME_VERSION = 163; ///< Current savegame version of OpenTTD. +extern const uint16 SAVEGAME_VERSION = 164; ///< Current savegame version of OpenTTD. SavegameType _savegame_type; ///< type of savegame we are loading diff --git a/src/saveload/saveload_internal.h b/src/saveload/saveload_internal.h index b400861b4..613ff262a 100644 --- a/src/saveload/saveload_internal.h +++ b/src/saveload/saveload_internal.h @@ -27,6 +27,7 @@ void MoveWaypointsToBaseStations(); const SaveLoad *GetBaseStationDescription(); void AfterLoadVehicles(bool part_of_load); +void FixupTrainLengths(); void AfterLoadStations(); void AfterLoadRoadStops(); void AfterLoadLabelMaps(); diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 4dc0a7fe2..1e47094eb 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -249,8 +249,6 @@ void AfterLoadVehicles(bool part_of_load) if (v->Next() != NULL) v->Next()->previous = v; if (v->NextShared() != NULL) v->NextShared()->previous_shared = v; - v->UpdateDeltaXY(v->direction); - if (part_of_load) v->fill_percent_te_id = INVALID_TE_ID; v->first = NULL; if (v->IsGroundVehicle()) v->GetGroundVehicleCache()->first_engine = INVALID_ENGINE; @@ -442,11 +440,99 @@ void AfterLoadVehicles(bool part_of_load) default: break; } + v->UpdateDeltaXY(v->direction); v->coord.left = INVALID_COORD; VehicleMove(v, false); } } +bool TrainController(Train *v, Vehicle *nomove, bool reverse = true); // From train_cmd.cpp +void ReverseTrainDirection(Train *v); +void ReverseTrainSwapVeh(Train *v, int l, int r); + +/** Fixup old train spacing. */ +void FixupTrainLengths() +{ + /* Vehicle center was moved from 4 units behind the front to half the length + * behind the front. Move vehicles so they end up on the same spot. */ + Vehicle *v; + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_TRAIN && v->IsPrimaryVehicle()) { + /* The vehicle center is now more to the front depending on vehicle length, + * so we need to move all vehicles forward to cover the difference to the + * old center, otherwise wagon spacing in trains would be broken upon load. */ + for (Train *u = Train::From(v); u != NULL; u = u->Next()) { + if (u->track == TRACK_BIT_DEPOT || (u->vehstatus & VS_CRASHED)) continue; + + Train *next = u->Next(); + + /* Try to pull the vehicle half its length forward. */ + int diff = (VEHICLE_LENGTH - u->gcache.cached_veh_length) / 2; + int done; + for (done = 0; done < diff; done++) { + if (!TrainController(u, next, false)) break; + } + + if (next != NULL && done < diff && u->IsFrontEngine()) { + /* Pulling the front vehicle forwards failed, we either encountered a dead-end + * or a red signal. To fix this, we try to move the whole train the required + * space backwards and re-do the fix up of the front vehicle. */ + + /* Ignore any signals when backtracking. */ + TrainForceProceeding old_tfp = u->force_proceed; + u->force_proceed = TFP_SIGNAL; + + /* Swap start<>end, start+1<>end-1, ... */ + int r = CountVehiclesInChain(u) - 1; // number of vehicles - 1 + int l = 0; + do ReverseTrainSwapVeh(u, l++, r--); while (l <= r); + + /* We moved the first vehicle which is now the last. Move it back to the + * original position as we will fix up the last vehicle later in the loop. */ + for (int i = 0; i < done; i++) TrainController(u->Last(), NULL); + + /* Move the train backwards to get space for the first vehicle. As the stopping + * distance from a line end is rounded up, move the train one unit more to cater + * for front vehicles with odd lengths. */ + int moved; + for (moved = 0; moved < diff + 1; moved++) { + if (!TrainController(u, NULL, false)) break; + } + + /* Swap start<>end, start+1<>end-1, ... again. */ + r = CountVehiclesInChain(u) - 1; // number of vehicles - 1 + l = 0; + do ReverseTrainSwapVeh(u, l++, r--); while (l <= r); + + u->force_proceed = old_tfp; + + /* Tracks are too short to fix the train length. The player has to fix the + * train in a depot. Bail out so we don't damage the vehicle chain any more. */ + if (moved < diff + 1) break; + + /* Re-do the correction for the first vehicle. */ + for (done = 0; done < diff; done++) TrainController(u, next, false); + + /* We moved one unit more backwards than needed for even-length front vehicles, + * try to move that unit forward again. We don't care if this step fails. */ + TrainController(u, NULL, false); + } + + /* If the next wagon is still in a depot, check if it shouldn't be outside already. */ + if (next != NULL && next->track == TRACK_BIT_DEPOT) { + int d = TicksToLeaveDepot(u); + if (d <= 0) { + /* Next vehicle should have left the depot already, show it and pull forward. */ + next->vehstatus &= ~VS_HIDDEN; + next->track = TrackToTrackBits(GetRailDepotTrack(next->tile)); + for (int i = 0; i >= d; i--) TrainController(next, NULL); + } + } + } + } + } +} + static uint8 _cargo_days; static uint16 _cargo_source; static uint32 _cargo_source_xy; |