Add game setting to limit train lookahead to signal aspect

In realistic braking mode when multi-aspect signalling enabled by GRF
This commit is contained in:
Jonathan G Rennison
2022-06-19 11:54:40 +01:00
parent bdd73a19a1
commit 22caac6529
13 changed files with 118 additions and 16 deletions

View File

@@ -1269,6 +1269,7 @@ STR_CONFIG_SETTING_ORIGINAL :Original
STR_CONFIG_SETTING_REALISTIC :Realistic STR_CONFIG_SETTING_REALISTIC :Realistic
STR_CONFIG_SETTING_TRAIN_BRAKING_REALISTIC :Realistic {PUSH_COLOUR}{RED}(Expert){POP_COLOUR} STR_CONFIG_SETTING_TRAIN_BRAKING_REALISTIC :Realistic {PUSH_COLOUR}{RED}(Expert){POP_COLOUR}
STR_CONFIG_SETTING_TRAIN_BRAKING_ASPECT_LIMITED_ON :On {PUSH_COLOUR}{RED}(Expert, Difficult){POP_COLOUR}
STR_CONFIG_SETTING_REALISTIC_BRAKING_SIGNALS_NOT_ALLOWED :{WHITE}Realistic braking can't be enabled. At least one pre-signal or two-way signal is present. STR_CONFIG_SETTING_REALISTIC_BRAKING_SIGNALS_NOT_ALLOWED :{WHITE}Realistic braking can't be enabled. At least one pre-signal or two-way signal is present.
@@ -1369,6 +1370,8 @@ STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL :Train accelerat
STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL_HELPTEXT :Select the physics model for train acceleration. The "original" model penalises slopes equally for all vehicles. The "realistic" model penalises slopes and curves depending on various properties of the consist, like length and tractive effort STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL_HELPTEXT :Select the physics model for train acceleration. The "original" model penalises slopes equally for all vehicles. The "realistic" model penalises slopes and curves depending on various properties of the consist, like length and tractive effort
STR_CONFIG_SETTING_TRAIN_BRAKING_MODEL :Train braking model: {STRING2} STR_CONFIG_SETTING_TRAIN_BRAKING_MODEL :Train braking model: {STRING2}
STR_CONFIG_SETTING_TRAIN_BRAKING_MODEL_HELPTEXT :Select the physics model for train braking. The "original" model allows trains to stop instantly. In the "realistic" model, trains have a stopping distance and will reserve ahead accordingly, trains cannot stop instantly.{}{}The "realistic" model has many implications for signalling and track layout design, and is therefore an advanced feature which may not be suitable for beginners. In particular pre-signals and two-way signals are not permitted, and PBS is used for all signalling. STR_CONFIG_SETTING_TRAIN_BRAKING_MODEL_HELPTEXT :Select the physics model for train braking. The "original" model allows trains to stop instantly. In the "realistic" model, trains have a stopping distance and will reserve ahead accordingly, trains cannot stop instantly.{}{}The "realistic" model has many implications for signalling and track layout design, and is therefore an advanced feature which may not be suitable for beginners. In particular pre-signals and two-way signals are not permitted, and PBS is used for all signalling.
STR_CONFIG_SETTING_REALISTIC_BRAKING_ASPECT_LIMITED :Realistic train braking is aspect limited: {STRING2}
STR_CONFIG_SETTING_REALISTIC_BRAKING_ASPECT_LIMITED_HELPTEXT :In the realistic train braking model, limit the look-ahead of trains to the aspect of signals (i.e. do not allow reserving and looking ahead an unlimited number of signals).{}This requires a NewGRF which provides multi-aspect signals.{}{}This is an expert setting which will likely increase gameplay difficulty and will require additional thought about signal types and placement.
STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL :Road vehicle acceleration model: {STRING2} STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL :Road vehicle acceleration model: {STRING2}
STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL_HELPTEXT :Select the physics model for road vehicle acceleration. The "original" model penalises slopes equally for all vehicles. The "realistic" model penalises slopes depending on various properties of the engine, for example 'tractive effort' STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL_HELPTEXT :Select the physics model for road vehicle acceleration. The "original" model penalises slopes equally for all vehicles. The "realistic" model penalises slopes depending on various properties of the engine, for example 'tractive effort'

View File

@@ -585,7 +585,7 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
if (signal_speed == 0 || (bridge_speed != 0 && bridge_speed < signal_speed)) signal_speed = bridge_speed; if (signal_speed == 0 || (bridge_speed != 0 && bridge_speed < signal_speed)) signal_speed = bridge_speed;
/* Entrance signal */ /* Entrance signal */
lookahead->AddSignal(signal_speed, 0, z); lookahead->AddSignal(signal_speed, 0, z, 0);
update_z(tile, trackdir, false); update_z(tile, trackdir, false);
@@ -599,7 +599,7 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
int offset = start_offset - TILE_SIZE; int offset = start_offset - TILE_SIZE;
for (int i = 0; i < signals; i++) { for (int i = 0; i < signals; i++) {
offset += TILE_SIZE * spacing; offset += TILE_SIZE * spacing;
lookahead->AddSignal(signal_speed, offset, chunnel ? LookaheadTileHeightForChunnel(length, i * spacing) : z); lookahead->AddSignal(signal_speed, offset, chunnel ? LookaheadTileHeightForChunnel(length, i * spacing) : z, 0);
} }
/* Exit signal */ /* Exit signal */
@@ -613,7 +613,7 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
if (signal_speed == 0 || (bridge_speed != 0 && bridge_speed < signal_speed)) signal_speed = bridge_speed; if (signal_speed == 0 || (bridge_speed != 0 && bridge_speed < signal_speed)) signal_speed = bridge_speed;
} }
lookahead->AddSignal(signal_speed, end_offset, z); lookahead->AddSignal(signal_speed, end_offset, z, 0);
lookahead->SetNextExtendPositionIfUnset(); lookahead->SetNextExtendPositionIfUnset();
} else { } else {
@@ -656,7 +656,11 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
/* Passing through a signal from the front side */ /* Passing through a signal from the front side */
uint16 signal_speed = GetRailTypeInfo(rt)->max_speed; uint16 signal_speed = GetRailTypeInfo(rt)->max_speed;
if (signal_speed == 0 || (speed_restriction != 0 && speed_restriction < signal_speed)) signal_speed = speed_restriction; if (signal_speed == 0 || (speed_restriction != 0 && speed_restriction < signal_speed)) signal_speed = speed_restriction;
lookahead->AddSignal(signal_speed, 0, z); uint16 signal_flags = 0;
if (_non_aspect_inc_style_mask != 0 && HasBit(_non_aspect_inc_style_mask, GetSignalStyle(tile, TrackdirToTrack(trackdir)))) {
SetBit(signal_flags, TRSLAI_NO_ASPECT_INC);
}
lookahead->AddSignal(signal_speed, 0, z, signal_flags);
lookahead->SetNextExtendPositionIfUnset(); lookahead->SetNextExtendPositionIfUnset();
} }
} }
@@ -953,7 +957,7 @@ void TryCreateLookAheadForTrainInTunnelBridge(Train *t)
int offset = -(int)TILE_SIZE; int offset = -(int)TILE_SIZE;
for (int i = 0; i < signals; i++) { for (int i = 0; i < signals; i++) {
offset += TILE_SIZE * spacing; offset += TILE_SIZE * spacing;
t->lookahead->AddSignal(signal_speed, offset, HasBit(t->lookahead->flags, TRLF_CHUNNEL) ? LookaheadTileHeightForChunnel(length, i * spacing) : z); t->lookahead->AddSignal(signal_speed, offset, HasBit(t->lookahead->flags, TRLF_CHUNNEL) ? LookaheadTileHeightForChunnel(length, i * spacing) : z, 0);
} }
/* Exit signal */ /* Exit signal */
@@ -966,7 +970,7 @@ void TryCreateLookAheadForTrainInTunnelBridge(Train *t)
if (signal_speed == 0 || (bridge_speed != 0 && bridge_speed < signal_speed)) signal_speed = bridge_speed; if (signal_speed == 0 || (bridge_speed != 0 && bridge_speed < signal_speed)) signal_speed = bridge_speed;
} }
t->lookahead->AddSignal(signal_speed, end_offset, z); t->lookahead->AddSignal(signal_speed, end_offset, z, 0);
t->lookahead->SetNextExtendPositionIfUnset(); t->lookahead->SetNextExtendPositionIfUnset();
} }
@@ -979,6 +983,37 @@ void TryCreateLookAheadForTrainInTunnelBridge(Train *t)
} }
} }
void SetTrainReservationLookaheadEnd(Train *v)
{
if (_settings_game.vehicle.realistic_braking_aspect_limited != TRBALM_ON || _extra_aspects == 0) {
v->lookahead->lookahead_end_position = v->lookahead->reservation_end_position + 1;
return;
}
int32 threshold = v->lookahead->current_position + 24;
uint8 known_signals_ahead = 1;
for (const TrainReservationLookAheadItem &item : v->lookahead->items) {
if (item.type == TRLIT_SIGNAL) {
if (item.start <= threshold) {
/* Signal is within visual range */
uint8 max_aspect = _extra_aspects + (HasBit(item.data_aux, TRSLAI_NO_ASPECT_INC) ? 1 : 2);
if (max_aspect > known_signals_ahead) known_signals_ahead = max_aspect;
}
if (!HasBit(item.data_aux, TRSLAI_NO_ASPECT_INC)) {
known_signals_ahead--;
if (known_signals_ahead == 0) {
if (item.start > v->lookahead->lookahead_end_position) v->lookahead->lookahead_end_position = item.start;
return;
}
}
}
}
/* Didn't need to stop at a signal along the reservation */
v->lookahead->lookahead_end_position = v->lookahead->reservation_end_position;
if (known_signals_ahead > 1) v->lookahead->lookahead_end_position++;
}
void FillTrainReservationLookAhead(Train *v) void FillTrainReservationLookAhead(Train *v)
{ {
TileIndex tile; TileIndex tile;
@@ -1033,12 +1068,16 @@ void FillTrainReservationLookAhead(Train *v)
} }
if (!(HasAcrossTunnelBridgeReservation(end) && GetTunnelBridgeExitSignalState(end) == SIGNAL_STATE_GREEN && raw_free_tiles == INT_MAX)) { if (!(HasAcrossTunnelBridgeReservation(end) && GetTunnelBridgeExitSignalState(end) == SIGNAL_STATE_GREEN && raw_free_tiles == INT_MAX)) {
/* do not attempt to follow through a signalled tunnel/bridge if it is not empty or the far end is not reserved */ /* do not attempt to follow through a signalled tunnel/bridge if it is not empty or the far end is not reserved */
SetTrainReservationLookaheadEnd(v);
return; return;
} }
} }
} }
if (IsRailDepotTile(tile) && !GetDepotReservationTrackBits(tile)) return; if (IsRailDepotTile(tile) && !GetDepotReservationTrackBits(tile)) {
SetTrainReservationLookaheadEnd(v);
return;
}
FollowReservationFlags flags = FRF_NONE; FollowReservationFlags flags = FRF_NONE;
if (HasBit(v->lookahead->flags, TRLF_TB_EXIT_FREE)) flags |= FRF_TB_EXIT_FREE; if (HasBit(v->lookahead->flags, TRLF_TB_EXIT_FREE)) flags |= FRF_TB_EXIT_FREE;
@@ -1069,6 +1108,8 @@ void FillTrainReservationLookAhead(Train *v)
v->lookahead->reservation_end_tile = res.tile; v->lookahead->reservation_end_tile = res.tile;
v->lookahead->reservation_end_trackdir = res.trackdir; v->lookahead->reservation_end_trackdir = res.trackdir;
SetTrainReservationLookaheadEnd(v);
} }
/** /**

View File

@@ -58,11 +58,16 @@ enum TrainReservationLookAheadItemType : byte {
TRLIT_CURVE_SPEED = 5, ///< Curve speed limit TRLIT_CURVE_SPEED = 5, ///< Curve speed limit
}; };
enum TrainReservationSignalLookAheadItemFlags {
TRSLAI_NO_ASPECT_INC = 0, ///< This signal does not increase the signal aspect (e.g. banner repeater)
};
struct TrainReservationLookAheadItem { struct TrainReservationLookAheadItem {
int32 start; int32 start;
int32 end; int32 end;
int16 z_pos; int16 z_pos;
uint16 data_id; uint16 data_id;
uint16 data_aux;
TrainReservationLookAheadItemType type; TrainReservationLookAheadItemType type;
}; };
@@ -83,6 +88,7 @@ struct TrainReservationLookAhead {
Trackdir reservation_end_trackdir; ///< The reserved trackdir on the end tile. Trackdir reservation_end_trackdir; ///< The reserved trackdir on the end tile.
int32 current_position; ///< Current position of the train on the reservation int32 current_position; ///< Current position of the train on the reservation
int32 reservation_end_position; ///< Position of the end of the reservation int32 reservation_end_position; ///< Position of the end of the reservation
int32 lookahead_end_position; ///< Position of the end of the reservation within the lookahead distance
int32 next_extend_position; ///< Next position to try extending the reservation at the sighting distance of the next mid-reservation signal 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 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 int16 tunnel_bridge_reserved_tiles; ///< How many tiles a reservation into the tunnel/bridge currently extends into the wormhole
@@ -101,38 +107,38 @@ struct TrainReservationLookAhead {
void AddStation(int tiles, StationID id, int16 z_pos) void AddStation(int tiles, StationID id, int16 z_pos)
{ {
int end = this->RealEndPosition(); int end = this->RealEndPosition();
this->items.push_back({ end, end + (((int)TILE_SIZE) * tiles), z_pos, id, TRLIT_STATION }); this->items.push_back({ end, end + (((int)TILE_SIZE) * tiles), z_pos, id, 0, TRLIT_STATION });
} }
void AddReverse(int16 z_pos) void AddReverse(int16 z_pos)
{ {
int end = this->RealEndPosition(); int end = this->RealEndPosition();
this->items.push_back({ end, end, z_pos, 0, TRLIT_REVERSE }); this->items.push_back({ end, end, z_pos, 0, 0, TRLIT_REVERSE });
} }
void AddTrackSpeedLimit(uint16 speed, int offset, int duration, int16 z_pos) void AddTrackSpeedLimit(uint16 speed, int offset, int duration, int16 z_pos)
{ {
int end = this->RealEndPosition(); int end = this->RealEndPosition();
this->items.push_back({ end + offset, end + offset + duration, z_pos, speed, TRLIT_TRACK_SPEED }); this->items.push_back({ end + offset, end + offset + duration, z_pos, speed, 0, TRLIT_TRACK_SPEED });
} }
void AddSpeedRestriction(uint16 speed, int offset, int duration, int16 z_pos) void AddSpeedRestriction(uint16 speed, int offset, int duration, int16 z_pos)
{ {
int end = this->RealEndPosition(); int end = this->RealEndPosition();
this->items.push_back({ end + offset, end + offset + duration, z_pos, speed, TRLIT_SPEED_RESTRICTION }); this->items.push_back({ end + offset, end + offset + duration, z_pos, speed, 0, TRLIT_SPEED_RESTRICTION });
this->speed_restriction = speed; this->speed_restriction = speed;
} }
void AddSignal(uint16 target_speed, int offset, int16 z_pos) void AddSignal(uint16 target_speed, int offset, int16 z_pos, uint16 flags)
{ {
int end = this->RealEndPosition(); int end = this->RealEndPosition();
this->items.push_back({ end + offset, end + offset, z_pos, target_speed, TRLIT_SIGNAL }); this->items.push_back({ end + offset, end + offset, z_pos, target_speed, flags, TRLIT_SIGNAL });
} }
void AddCurveSpeedLimit(uint16 target_speed, int offset, int16 z_pos) void AddCurveSpeedLimit(uint16 target_speed, int offset, int16 z_pos)
{ {
int end = this->RealEndPosition(); int end = this->RealEndPosition();
this->items.push_back({ end + offset, end + offset, z_pos, target_speed, TRLIT_CURVE_SPEED }); this->items.push_back({ end + offset, end + offset, z_pos, target_speed, 0, TRLIT_CURVE_SPEED });
} }
void SetNextExtendPosition(); void SetNextExtendPosition();
@@ -155,6 +161,7 @@ bool ValidateLookAhead(const Train *v);
PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res = nullptr, FollowTrainReservationFlags flags = FTRF_NONE); PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res = nullptr, FollowTrainReservationFlags flags = FTRF_NONE);
void ApplyAvailableFreeTunnelBridgeTiles(TrainReservationLookAhead *lookahead, int free_tiles, TileIndex tile, TileIndex end); void ApplyAvailableFreeTunnelBridgeTiles(TrainReservationLookAhead *lookahead, int free_tiles, TileIndex tile, TileIndex end);
void TryCreateLookAheadForTrainInTunnelBridge(Train *t); void TryCreateLookAheadForTrainInTunnelBridge(Train *t);
void SetTrainReservationLookaheadEnd(Train *v);
void FillTrainReservationLookAhead(Train *v); void FillTrainReservationLookAhead(Train *v);
void SetLookAheadNextExtendPosition(Train *v); void SetLookAheadNextExtendPosition(Train *v);
void SetLookAheadNextExtendPositionIfUnset(Train *v); void SetLookAheadNextExtendPositionIfUnset(Train *v);

View File

@@ -4082,6 +4082,14 @@ bool AfterLoadGame()
_aspect_cfg_hash = 0; _aspect_cfg_hash = 0;
} }
if (!SlXvIsFeaturePresent(XSLFI_REALISTIC_TRAIN_BRAKING, 9) && _settings_game.vehicle.train_braking_model == TBM_REALISTIC) {
for (Train *t : Train::Iterate()) {
if (t->lookahead != nullptr) {
t->lookahead->lookahead_end_position = t->lookahead->reservation_end_position + 1;
}
}
}
InitializeRoadGUI(); InitializeRoadGUI();
/* This needs to be done after conversion. */ /* This needs to be done after conversion. */

View File

@@ -151,7 +151,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_ANIMATED_TILE_EXTRA, XSCF_NULL, 1, 1, "animated_tile_extra", nullptr, nullptr, nullptr }, { 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_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_INDUSTRY_CARGO_ADJ, XSCF_IGNORABLE_UNKNOWN, 1, 1, "industry_cargo_adj", nullptr, nullptr, nullptr },
{ XSLFI_REALISTIC_TRAIN_BRAKING,XSCF_NULL, 8, 8, "realistic_train_braking", nullptr, nullptr, "VLKA" }, { XSLFI_REALISTIC_TRAIN_BRAKING,XSCF_NULL, 9, 9, "realistic_train_braking", nullptr, nullptr, "VLKA" },
{ XSLFI_INFLATION_FIXED_DATES, XSCF_IGNORABLE_ALL, 1, 1, "inflation_fixed_dates", nullptr, nullptr, nullptr }, { 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_WATER_FLOODING, XSCF_NULL, 2, 2, "water_flooding", nullptr, nullptr, nullptr },
{ XSLFI_MORE_HOUSES, XSCF_NULL, 2, 2, "more_houses", nullptr, nullptr, nullptr }, { XSLFI_MORE_HOUSES, XSCF_NULL, 2, 2, "more_houses", nullptr, nullptr, nullptr },

View File

@@ -1387,6 +1387,7 @@ const SaveLoadTable GetVehicleLookAheadDescription()
SLE_VAR(TrainReservationLookAhead, reservation_end_trackdir, SLE_UINT8), SLE_VAR(TrainReservationLookAhead, reservation_end_trackdir, SLE_UINT8),
SLE_VAR(TrainReservationLookAhead, current_position, SLE_INT32), SLE_VAR(TrainReservationLookAhead, current_position, SLE_INT32),
SLE_VAR(TrainReservationLookAhead, reservation_end_position, SLE_INT32), SLE_VAR(TrainReservationLookAhead, reservation_end_position, SLE_INT32),
SLE_CONDVAR_X(TrainReservationLookAhead, lookahead_end_position, SLE_INT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_REALISTIC_TRAIN_BRAKING, 9)),
SLE_VAR(TrainReservationLookAhead, reservation_end_z, SLE_INT16), SLE_VAR(TrainReservationLookAhead, reservation_end_z, SLE_INT16),
SLE_VAR(TrainReservationLookAhead, tunnel_bridge_reserved_tiles, SLE_INT16), SLE_VAR(TrainReservationLookAhead, tunnel_bridge_reserved_tiles, SLE_INT16),
SLE_VAR(TrainReservationLookAhead, flags, SLE_UINT16), SLE_VAR(TrainReservationLookAhead, flags, SLE_UINT16),
@@ -1406,6 +1407,7 @@ const SaveLoadTable GetVehicleLookAheadItemDescription()
SLE_VAR(TrainReservationLookAheadItem, end, SLE_INT32), SLE_VAR(TrainReservationLookAheadItem, end, SLE_INT32),
SLE_VAR(TrainReservationLookAheadItem, z_pos, SLE_INT16), SLE_VAR(TrainReservationLookAheadItem, z_pos, SLE_INT16),
SLE_VAR(TrainReservationLookAheadItem, data_id, SLE_UINT16), SLE_VAR(TrainReservationLookAheadItem, data_id, SLE_UINT16),
SLE_CONDVAR_X(TrainReservationLookAheadItem, data_aux, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_REALISTIC_TRAIN_BRAKING, 9)),
SLE_VAR(TrainReservationLookAheadItem, type, SLE_UINT8), SLE_VAR(TrainReservationLookAheadItem, type, SLE_UINT8),
}; };

View File

@@ -1138,6 +1138,7 @@ static void TrainBrakingModelChanged(int32 new_value)
UpdateAllBlockSignals(); UpdateAllBlockSignals();
InvalidateWindowData(WC_BUILD_SIGNAL, 0); InvalidateWindowData(WC_BUILD_SIGNAL, 0);
InvalidateWindowClassesData(WC_GAME_OPTIONS);
} }
/** /**

View File

@@ -2018,6 +2018,7 @@ static SettingsContainer &GetSettingsTree()
{ {
physics->Add(new SettingEntry("vehicle.train_acceleration_model")); physics->Add(new SettingEntry("vehicle.train_acceleration_model"));
physics->Add(new SettingEntry("vehicle.train_braking_model")); physics->Add(new SettingEntry("vehicle.train_braking_model"));
physics->Add(new ConditionallyHiddenSettingEntry("vehicle.realistic_braking_aspect_limited", []() -> bool { return GetGameSettings().vehicle.train_braking_model != TBM_REALISTIC; }));
physics->Add(new SettingEntry("vehicle.train_slope_steepness")); physics->Add(new SettingEntry("vehicle.train_slope_steepness"));
physics->Add(new SettingEntry("vehicle.wagon_speed_limits")); physics->Add(new SettingEntry("vehicle.wagon_speed_limits"));
physics->Add(new SettingEntry("vehicle.train_speed_adaptation")); physics->Add(new SettingEntry("vehicle.train_speed_adaptation"));

View File

@@ -603,6 +603,7 @@ struct VehicleSettings {
uint8 smoke_amount; ///< amount of smoke/sparks locomotives produce uint8 smoke_amount; ///< amount of smoke/sparks locomotives produce
uint8 train_acceleration_model; ///< realistic acceleration for trains uint8 train_acceleration_model; ///< realistic acceleration for trains
uint8 train_braking_model; ///< braking model for trains uint8 train_braking_model; ///< braking model for trains
uint8 realistic_braking_aspect_limited; ///< realistic braking lookahead is aspect limited
uint8 roadveh_acceleration_model; ///< realistic acceleration for road vehicles uint8 roadveh_acceleration_model; ///< realistic acceleration for road vehicles
uint8 train_slope_steepness; ///< Steepness of hills for trains when using realistic acceleration uint8 train_slope_steepness; ///< Steepness of hills for trains when using realistic acceleration
uint8 roadveh_slope_steepness; ///< Steepness of hills for road vehicles when using realistic acceleration uint8 roadveh_slope_steepness; ///< Steepness of hills for road vehicles when using realistic acceleration

View File

@@ -225,6 +225,9 @@ class NIHVehicle : public NIHelper {
}; };
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); 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.lookahead_end_position <= l.reservation_end_position) {
b += seprintf(b, lastof(buffer), ", (lookahead: end: %d, remaining: %d)", l.lookahead_end_position, l.lookahead_end_position - l.current_position);
}
if (l.next_extend_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); b += seprintf(b, lastof(buffer), ", next extend position: %d (dist: %d)", l.next_extend_position, l.next_extend_position - l.current_position);
} }
@@ -273,7 +276,12 @@ class NIHVehicle : public NIHelper {
if (item.data_id > 0) print_braking_speed(item.start, item.data_id, item.z_pos); if (item.data_id > 0) print_braking_speed(item.start, item.data_id, item.z_pos);
break; break;
case TRLIT_SIGNAL: case TRLIT_SIGNAL:
b += seprintf(b, lastof(buffer), "signal: target speed: %u", item.data_id); b += seprintf(b, lastof(buffer), "signal: target speed: %u, flags:", item.data_id);
if (HasBit(item.data_aux, TRSLAI_NO_ASPECT_INC)) b += seprintf(b, lastof(buffer), "n");
if (_settings_game.vehicle.realistic_braking_aspect_limited == TRBALM_ON && l.lookahead_end_position == item.start) {
b += seprintf(b, lastof(buffer), ", lookahead end");
print_braking_speed(item.start, 0, item.z_pos);
}
break; break;
case TRLIT_CURVE_SPEED: case TRLIT_CURVE_SPEED:
b += seprintf(b, lastof(buffer), "curve speed: %u", item.data_id); b += seprintf(b, lastof(buffer), "curve speed: %u", item.data_id);

View File

@@ -125,6 +125,12 @@ static const SettingDescEnumEntry _train_braking_model[] = {
{ 0, STR_NULL } { 0, STR_NULL }
}; };
static const SettingDescEnumEntry _realistic_braking_aspect_limited[] = {
{ TRBALM_OFF, STR_CONFIG_SETTING_OFF },
{ TRBALM_ON, STR_CONFIG_SETTING_TRAIN_BRAKING_ASPECT_LIMITED_ON },
{ 0, STR_NULL }
};
static const SettingDescEnumEntry _station_delivery_mode[] = { static const SettingDescEnumEntry _station_delivery_mode[] = {
{ SD_NEAREST_FIRST, STR_CONFIG_SETTING_ORIGINAL}, { SD_NEAREST_FIRST, STR_CONFIG_SETTING_ORIGINAL},
{ SD_BALANCED, STR_CONFIG_SETTING_DELIVERY_BALANCED}, { SD_BALANCED, STR_CONFIG_SETTING_DELIVERY_BALANCED},
@@ -1327,6 +1333,16 @@ post_cb = TrainBrakingModelChanged
cat = SC_EXPERT cat = SC_EXPERT
patxname = ""realistic_braking.vehicle.train_braking_model"" patxname = ""realistic_braking.vehicle.train_braking_model""
[SDT_ENUM]
var = vehicle.realistic_braking_aspect_limited
type = SLE_UINT8
def = TRBALM_OFF
enumlist = _realistic_braking_aspect_limited
str = STR_CONFIG_SETTING_REALISTIC_BRAKING_ASPECT_LIMITED
strhelp = STR_CONFIG_SETTING_REALISTIC_BRAKING_ASPECT_LIMITED_HELPTEXT
cat = SC_EXPERT
patxname = ""realistic_braking.vehicle.realistic_braking_aspect_limited""
[SDT_VAR] [SDT_VAR]
var = vehicle.roadveh_acceleration_model var = vehicle.roadveh_acceleration_model
type = SLE_UINT8 type = SLE_UINT8

View File

@@ -958,6 +958,9 @@ static void ApplyLookAheadItem(const Train *v, const TrainReservationLookAheadIt
break; break;
case TRLIT_SIGNAL: case TRLIT_SIGNAL:
if (_settings_game.vehicle.realistic_braking_aspect_limited == TRBALM_ON && v->lookahead->lookahead_end_position == item.start) {
limit_advisory_speed(item.start, 0, item.z_pos);
}
break; break;
case TRLIT_CURVE_SPEED: case TRLIT_CURVE_SPEED:
@@ -982,6 +985,7 @@ static void AdvanceLookAheadPosition(Train *v)
const int32 old_position = v->lookahead->current_position; const int32 old_position = v->lookahead->current_position;
v->lookahead->current_position = 0; v->lookahead->current_position = 0;
v->lookahead->reservation_end_position -= old_position; v->lookahead->reservation_end_position -= old_position;
v->lookahead->lookahead_end_position -= old_position;
v->lookahead->next_extend_position -= old_position; v->lookahead->next_extend_position -= old_position;
for (TrainReservationLookAheadItem &item : v->lookahead->items) { for (TrainReservationLookAheadItem &item : v->lookahead->items) {
item.start -= old_position; item.start -= old_position;
@@ -1008,6 +1012,7 @@ static void AdvanceLookAheadPosition(Train *v)
} }
if (v->lookahead->current_position == v->lookahead->next_extend_position) { if (v->lookahead->current_position == v->lookahead->next_extend_position) {
SetTrainReservationLookaheadEnd(v);
TryLongReserveChooseTrainTrackFromReservationEnd(v, true); TryLongReserveChooseTrainTrackFromReservationEnd(v, true);
v->lookahead->SetNextExtendPositionIfUnset(); v->lookahead->SetNextExtendPositionIfUnset();
} }
@@ -3990,6 +3995,8 @@ static bool IsReservationLookAheadLongEnough(const Train *v, const ChooseTrainTr
if (v->lookahead->reservation_end_position >= v->lookahead->current_position + v->reverse_distance - 1) return true; if (v->lookahead->reservation_end_position >= v->lookahead->current_position + v->reverse_distance - 1) return true;
} }
if (v->lookahead->lookahead_end_position <= v->lookahead->reservation_end_position && _settings_game.vehicle.realistic_braking_aspect_limited == TRBALM_ON) return true;
TrainDecelerationStats stats(v, v->lookahead->cached_zpos); TrainDecelerationStats stats(v, v->lookahead->cached_zpos);
bool found_signal = false; bool found_signal = false;
@@ -4985,6 +4992,7 @@ static bool IsTooCloseBehindTrain(Train *t, TileIndex tile, uint16 distance, boo
TileIndex end = GetOtherTunnelBridgeEnd(t->tile); TileIndex end = GetOtherTunnelBridgeEnd(t->tile);
const int raw_free_tiles = GetAvailableFreeTilesInSignalledTunnelBridge(t->tile, end, tile); const int raw_free_tiles = GetAvailableFreeTilesInSignalledTunnelBridge(t->tile, end, tile);
ApplyAvailableFreeTunnelBridgeTiles(t->lookahead.get(), raw_free_tiles + ((raw_free_tiles != INT_MAX) ? DistanceManhattan(t->tile, tile) : 0), t->tile, end); ApplyAvailableFreeTunnelBridgeTiles(t->lookahead.get(), raw_free_tiles + ((raw_free_tiles != INT_MAX) ? DistanceManhattan(t->tile, tile) : 0), t->tile, end);
SetTrainReservationLookaheadEnd(t);
if (!LookaheadWithinCurrentTunnelBridge(t)) { if (!LookaheadWithinCurrentTunnelBridge(t)) {
/* Try to extend the reservation beyond the tunnel/bridge exit */ /* Try to extend the reservation beyond the tunnel/bridge exit */

View File

@@ -108,6 +108,12 @@ enum TrainBrakingModel {
TBM_REALISTIC, TBM_REALISTIC,
}; };
/** Train realistic braking aspect limited mode. */
enum TrainRealisticBrakingAspectLimitedMode {
TRBALM_OFF,
TRBALM_ON,
};
/** Visualisation contexts of vehicles and engines. */ /** Visualisation contexts of vehicles and engines. */
enum EngineImageType { enum EngineImageType {
EIT_ON_MAP = 0x00, ///< Vehicle drawn in viewport. EIT_ON_MAP = 0x00, ///< Vehicle drawn in viewport.