diff --git a/src/pbs.cpp b/src/pbs.cpp index 39af9f5051..837624c63a 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -550,6 +550,8 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra /* Exit signal */ const int end_offset = start_offset + (TILE_SIZE * length) /* + ((DiagDirToDiagTrackBits(GetTunnelBridgeDirection(end)) & GetTunnelBridgeTrackBits(end)) ? 16 : 8)*/; lookahead->AddSignal(signal_speed, end_offset, z); + + lookahead->SetNextExtendPositionIfUnset(); } else { update_z(tile, trackdir, false); if (length > 1) { @@ -591,6 +593,7 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra uint16 signal_speed = GetRailTypeInfo(rt)->max_speed; if (signal_speed == 0 || (speed_restriction != 0 && speed_restriction < signal_speed)) signal_speed = speed_restriction; lookahead->AddSignal(signal_speed, 0, z); + lookahead->SetNextExtendPositionIfUnset(); } } @@ -662,6 +665,18 @@ static Vehicle *FindTrainOnTrackEnum(Vehicle *v, void *data) return nullptr; } +void TrainReservationLookAhead::SetNextExtendPosition() +{ + int32 threshold = this->current_position + 24; + for (const TrainReservationLookAheadItem &item : this->items) { + if (item.type == TRLIT_SIGNAL && item.start > threshold) { + this->next_extend_position = item.start - 24; + return; + } + } + this->next_extend_position = this->current_position; +} + bool ValidateLookAhead(const Train *v) { TileIndex tile = v->lookahead->reservation_end_tile; @@ -846,6 +861,7 @@ void TryCreateLookAheadForTrainInTunnelBridge(Train *t) t->lookahead->reservation_end_trackdir = GetTunnelBridgeEntranceTrackdir(t->tile); t->lookahead->reservation_end_z = t->z_pos; t->lookahead->current_position = 0; + t->lookahead->next_extend_position = 0; t->lookahead->tunnel_bridge_reserved_tiles = DistanceManhattan(t->tile, TileVirtXY(t->x_pos, t->y_pos)); t->lookahead->reservation_end_position = GetTileMarginInFrontOfTrain(t); t->lookahead->flags = 0; @@ -874,6 +890,8 @@ void TryCreateLookAheadForTrainInTunnelBridge(Train *t) /* Exit signal */ const int end_offset = TILE_SIZE * length; t->lookahead->AddSignal(signal_speed, end_offset, z); + + t->lookahead->SetNextExtendPositionIfUnset(); } FillLookAheadCurveDataFromTrainPosition(t); @@ -897,6 +915,7 @@ void FillTrainReservationLookAhead(Train *v) if (v->lookahead == nullptr) { v->lookahead.reset(new TrainReservationLookAhead()); v->lookahead->current_position = 0; + v->lookahead->next_extend_position = 0; /* Special case, if called from TrainController, * v->tile, v->track and v->direction can be updated to the new tile, diff --git a/src/pbs.h b/src/pbs.h index 6a2309edcc..50d69027e5 100644 --- a/src/pbs.h +++ b/src/pbs.h @@ -83,6 +83,7 @@ struct TrainReservationLookAhead { Trackdir reservation_end_trackdir; ///< The reserved trackdir on the end tile. int32 current_position; ///< Current position of the train on the reservation int32 reservation_end_position; ///< Position of the end of the reservation + int32 next_extend_position; ///< Next position to try extending the reservation at the sighting distance of the next mid-reservation signal int16 reservation_end_z; ///< The z coordinate of the reservation end int16 tunnel_bridge_reserved_tiles; ///< How many tiles a reservation into the tunnel/bridge currently extends into the wormhole uint16 flags; ///< Flags (TrainReservationLookAheadFlags) @@ -131,6 +132,13 @@ struct TrainReservationLookAhead { int end = this->RealEndPosition(); this->items.push_back({ end + offset, end + offset, z_pos, target_speed, TRLIT_CURVE_SPEED }); } + + void SetNextExtendPosition(); + + void SetNextExtendPositionIfUnset() + { + if (this->next_extend_position <= this->current_position) this->SetNextExtendPosition(); + } }; /** Flags for FollowTrainReservation */ @@ -146,6 +154,8 @@ PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res = null void ApplyAvailableFreeTunnelBridgeTiles(TrainReservationLookAhead *lookahead, int free_tiles, TileIndex tile, TileIndex end); void TryCreateLookAheadForTrainInTunnelBridge(Train *t); void FillTrainReservationLookAhead(Train *v); +void SetLookAheadNextExtendPosition(Train *v); +void SetLookAheadNextExtendPositionIfUnset(Train *v); bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg = false); bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg = false, PBSWaitingPositionRestrictedSignalInfo *restricted_signal_info = nullptr); diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 7d0964523d..4affa30050 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -3934,6 +3934,14 @@ bool AfterLoadGame() UpdateAllBlockSignals(); } + if (!SlXvIsFeaturePresent(XSLFI_REALISTIC_TRAIN_BRAKING, 5) && _settings_game.vehicle.train_braking_model == TBM_REALISTIC) { + for (Train *t : Train::Iterate()) { + if (t->lookahead != nullptr) { + t->lookahead->SetNextExtendPosition(); + } + } + } + if (SlXvIsFeatureMissing(XSLFI_INFLATION_FIXED_DATES)) { _settings_game.economy.inflation_fixed_dates = !IsSavegameVersionBefore(SLV_GS_INDUSTRY_CONTROL); } diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index edbfca7679..f23bc4223a 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -147,7 +147,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_ANIMATED_TILE_EXTRA, XSCF_NULL, 1, 1, "animated_tile_extra", nullptr, nullptr, nullptr }, { XSLFI_NEWGRF_INFO_EXTRA, XSCF_NULL, 1, 1, "newgrf_info_extra", nullptr, nullptr, nullptr }, { XSLFI_INDUSTRY_CARGO_ADJ, XSCF_IGNORABLE_UNKNOWN, 1, 1, "industry_cargo_adj", nullptr, nullptr, nullptr }, - { XSLFI_REALISTIC_TRAIN_BRAKING,XSCF_NULL, 4, 4, "realistic_train_braking", nullptr, nullptr, "VLKA" }, + { XSLFI_REALISTIC_TRAIN_BRAKING,XSCF_NULL, 5, 5, "realistic_train_braking", nullptr, nullptr, "VLKA" }, { XSLFI_INFLATION_FIXED_DATES, XSCF_IGNORABLE_ALL, 1, 1, "inflation_fixed_dates", nullptr, nullptr, nullptr }, { XSLFI_WATER_FLOODING, XSCF_NULL, 2, 2, "water_flooding", nullptr, nullptr, nullptr }, { XSLFI_MORE_HOUSES, XSCF_NULL, 2, 2, "more_houses", nullptr, nullptr, nullptr }, diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 7da2831ee7..0c4de0e50d 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -1390,6 +1390,7 @@ const SaveLoadTable GetVehicleLookAheadDescription() SLE_VAR(TrainReservationLookAhead, tunnel_bridge_reserved_tiles, SLE_INT16), SLE_VAR(TrainReservationLookAhead, flags, SLE_UINT16), SLE_VAR(TrainReservationLookAhead, speed_restriction, SLE_UINT16), + SLE_CONDVAR_X(TrainReservationLookAhead, next_extend_position, SLE_INT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_REALISTIC_TRAIN_BRAKING, 5)), }; return _vehicle_look_ahead_desc; diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h index 1aa94fa6f6..d135133005 100644 --- a/src/table/newgrf_debug_data.h +++ b/src/table/newgrf_debug_data.h @@ -209,7 +209,10 @@ class NIHVehicle : public NIHelper { } }; - seprintf(buffer, lastof(buffer), " Position: current: %d, z: %d, end: %d, remaining: %d", l.current_position, stats.z_pos, l.reservation_end_position, l.reservation_end_position - l.current_position); + b = buffer + seprintf(buffer, lastof(buffer), " Position: current: %d, z: %d, end: %d, remaining: %d", l.current_position, stats.z_pos, l.reservation_end_position, l.reservation_end_position - l.current_position); + if (l.next_extend_position > l.current_position) { + b += seprintf(b, lastof(buffer), ", next extend position: %d (dist: %d)", l.next_extend_position, l.next_extend_position - l.current_position); + } print(buffer); b = buffer + seprintf(buffer, lastof(buffer), " Reservation ends at %X (%u x %u), trackdir: %02X, z: %d", diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 6b720c4d26..e2b92fc582 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -975,6 +975,7 @@ static void AdvanceLookAheadPosition(Train *v) const int32 old_position = v->lookahead->current_position; v->lookahead->current_position = 0; v->lookahead->reservation_end_position -= old_position; + v->lookahead->next_extend_position -= old_position; for (TrainReservationLookAheadItem &item : v->lookahead->items) { item.start -= old_position; item.end -= old_position; @@ -998,6 +999,11 @@ static void AdvanceLookAheadPosition(Train *v) } v->lookahead->items.pop_front(); } + + if (v->lookahead->current_position == v->lookahead->next_extend_position) { + TryLongReserveChooseTrainTrackFromReservationEnd(v, true); + v->lookahead->SetNextExtendPositionIfUnset(); + } } /**