diff --git a/src/lang/english.txt b/src/lang/english.txt index cc08099187..2c12835f9d 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1448,6 +1448,8 @@ STR_CONFIG_SETTING_TIMETABLE_START_TEXT_ENTRY :Enter timetable STR_CONFIG_SETTING_TIMETABLE_START_TEXT_ENTRY_HELPTEXT :Select whether timetable start times may be entered as text if time is being shown in minutes STR_CONFIG_SETTING_TIMETABLE_SEPARATION :Use timetable to ensure vehicle separation: {STRING2} STR_CONFIG_SETTING_TIMETABLE_SEPARATION_HELPTEXT :Select whether to ensure separation of vehicles when using automatic timetables +STR_CONFIG_SETTING_TIMETABLE_SEPARATION_RATE :Vehicle separation factor: {STRING2} +STR_CONFIG_SETTING_TIMETABLE_SEPARATION_RATE_HELPTEXT :How much of the vehicle separation timetable change to apply at each step STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE :Show arrival and departure in timetables: {STRING2} STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE_HELPTEXT :Display anticipated arrival and departure times in timetables STR_CONFIG_SETTING_QUICKGOTO :Quick creation of vehicle orders: {STRING2} diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index b0a7ac64d7..a6bbf32d70 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1675,6 +1675,7 @@ static SettingsContainer &GetSettingsTree() vehicles->Add(new SettingEntry("order.serviceathelipad")); vehicles->Add(new SettingEntry("order.timetable_automated")); vehicles->Add(new SettingEntry("order.timetable_separation")); + vehicles->Add(new SettingEntry("order.timetable_separation_rate")); vehicles->Add(new SettingEntry("vehicle.adjacent_crossings")); vehicles->Add(new SettingEntry("order.occupancy_smoothness")); } diff --git a/src/settings_type.h b/src/settings_type.h index 8daacaed02..56aac6a19b 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -474,6 +474,7 @@ struct OrderSettings { bool no_servicing_if_no_breakdowns; ///< don't send vehicles to depot when breakdowns are disabled bool timetable_automated; ///< whether to automatically manage timetables bool timetable_separation; ///< whether to perform automatic separation based on timetable + uint8 timetable_separation_rate; ///< percentage of timetable separation change to apply bool serviceathelipad; ///< service helicopters at helipads automatically (no need to send to depot) uint8 occupancy_smoothness; ///< percentage smoothness of occupancy measurement changes }; diff --git a/src/table/settings.ini b/src/table/settings.ini index d574aa1e6c..122da30607 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -355,6 +355,21 @@ cat = SC_EXPERT extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_AUTO_TIMETABLE) patxname = ""auto_timetables.order.timetable_separation"" +[SDT_VAR] +base = GameSettings +var = order.timetable_separation_rate +type = SLE_UINT8 +def = 100 +min = 0 +max = 100 +interval = 10 +str = STR_CONFIG_SETTING_TIMETABLE_SEPARATION_RATE +strhelp = STR_CONFIG_SETTING_TIMETABLE_SEPARATION_RATE_HELPTEXT +strval = STR_CONFIG_SETTING_PERCENTAGE +cat = SC_EXPERT +extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_AUTO_TIMETABLE) +patxname = ""auto_timetables.order.timetable_separation_rate"" + ; There are only 21 predefined town_name values (0-20), but you can have more with newgrf action F so allow ; these bigger values (21-255). Invalid values will fallback to english on use and (undefined string) in GUI. [SDT_OMANY] diff --git a/src/timetable_cmd.cpp b/src/timetable_cmd.cpp index 325f490a23..270e399ddd 100644 --- a/src/timetable_cmd.cpp +++ b/src/timetable_cmd.cpp @@ -557,8 +557,11 @@ void UpdateSeparationOrder(Vehicle *v_start) } int separation_ahead = SeparationBetween(v, v->AheadSeparation()); int separation_behind = SeparationBetween(v->BehindSeparation(), v); - v->lateness_counter = (separation_ahead - separation_behind) / 2; - if (separation_ahead == -1 || separation_behind == -1) v->lateness_counter = 0; + if (separation_ahead != -1 && separation_behind != -1) { + int new_lateness = (separation_ahead - separation_behind) / 2; + v->lateness_counter = (new_lateness * _settings_game.order.timetable_separation_rate + + v->lateness_counter * (100 - _settings_game.order.timetable_separation_rate)) / 100; + } v = v->AheadSeparation(); } while (v != v_start); } @@ -681,15 +684,7 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling) new_time = time_loading; } - /* Check for too large a difference from expected time, and if so don't average. */ - if (!(new_time > (int32)timetabled * 2 || new_time < (int32)timetabled / 2)) { - int arrival_error = timetabled - new_time; - /* Compute running average, with sign conversion to avoid negative overflow. */ - new_time = ((int32)timetabled * 4 + new_time + 2) / 5; - /* Use arrival_error to finetune order ticks. */ - if (arrival_error < 0) new_time++; - if (arrival_error > 0) new_time--; - } else if (new_time > (int32)timetabled * 10 && travelling) { + if (new_time > (int32)timetabled * 4 && travelling) { /* Possible jam, clear time and restart timetable for all vehicles. * Otherwise we risk trains blocking 1-lane stations for long times. */ ChangeTimetable(v, v->cur_real_order_index, 0, travelling ? MTF_TRAVEL_TIME : MTF_WAIT_TIME, true); @@ -699,6 +694,15 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling) SetWindowDirty(WC_VEHICLE_TIMETABLE, v2->index); } return; + } else if (new_time >= (int32)timetabled / 2) { + /* Compute running average, with sign conversion to avoid negative overflow. */ + if (new_time < (int32)timetabled) { + new_time = ((int32)timetabled * 3 + new_time * 2 + 2) / 5; + } else { + new_time = ((int32)timetabled * 9 + new_time + 5) / 10; + } + } else { + /* new time is less than hald old time, set value directly */ } if (new_time < 1) new_time = 1;