diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -1107,7 +1107,7 @@ static bool CanBuildTramTrackOnTile(Comp return ret.Succeeded(); } -static bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev) +bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev) { if (v->overtaking != 0) { if (IsTileType(v->tile, MP_STATION)) { @@ -1417,17 +1417,12 @@ again: v->direction = new_dir; if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) v->cur_speed -= v->cur_speed >> 2; - /* Delay the vehicle in curves by making it require one or two additional frames per curve. + /* Delay the vehicle in curves by making it require one additional frame per turning direction (two in total). * A vehicle has to spend at least 9 frames on a tile, so the following articulated part can follow. * (The following part may only be one tile behind, and the front part is moved before the following ones.) - * The short (inner) curve has 8 frames, this elongates it to 9 or 10. - * - * The difference between 9 and 10 is arbitrary, and completely bollocks (i.e. a bug). - * Unifying this requires a complicated savegame conversion. */ - if (old_dir != v->state) { - v->UpdateInclination(false, true); - return true; - } + * The short (inner) curve has 8 frames, this elongates it to 10. */ + v->UpdateInclination(false, true); + return true; } /* If the vehicle is in a normal road stop and the frame equals the stop frame OR diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -2832,6 +2832,64 @@ bool AfterLoadGame() } } + if (IsSavegameVersionBefore(188)) { + /* Fix articulated road vehicles. + * Some curves were shorter than other curves. + * Now they have the same length, but that means that trailing articulated parts will + * take longer to go through the curve than the parts in front which already left the courve. + * So, make articulated parts catch up. */ + RoadVehicle *v; + bool roadside = _settings_game.vehicle.road_side == 1; + SmallVector skip_frames; + FOR_ALL_ROADVEHICLES(v) { + if (!v->IsFrontEngine()) continue; + skip_frames.Clear(); + TileIndex prev_tile = v->tile; + uint prev_tile_skip = 0; + uint cur_skip = 0; + for (RoadVehicle *u = v; u != NULL; u = u->Next()) { + if (u->tile != prev_tile) { + prev_tile_skip = cur_skip; + prev_tile = u->tile; + } else { + cur_skip = prev_tile_skip; + } + + uint *this_skip = skip_frames.Append(); + *this_skip = prev_tile_skip; + + /* The following 3 curves now take longer than before */ + switch (u->state) { + case 2: + cur_skip++; + if (u->frame <= (roadside ? 9 : 5)) *this_skip = cur_skip; + break; + + case 4: + cur_skip++; + if (u->frame <= (roadside ? 5 : 9)) *this_skip = cur_skip; + break; + + case 5: + cur_skip++; + if (u->frame <= (roadside ? 4 : 2)) *this_skip = cur_skip; + break; + + default: + break; + } + } + while (cur_skip > skip_frames[0]) { + RoadVehicle *u = v; + RoadVehicle *prev = NULL; + for (uint *it = skip_frames.Begin(); it != skip_frames.End(); ++it, prev = u, u = u->Next()) { + extern bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev); + if (*it >= cur_skip) IndividualRoadVehicleController(u, prev); + } + cur_skip--; + } + } + } /* Station acceptance is some kind of cache */ diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -253,8 +253,9 @@ * 185 25620 * 186 25833 * 187 25899 + * 188 26169 */ -extern const uint16 SAVEGAME_VERSION = 187; ///< Current savegame version of OpenTTD. +extern const uint16 SAVEGAME_VERSION = 188; ///< Current savegame version of OpenTTD. SavegameType _savegame_type; ///< type of savegame we are loading