Merge pull request #281 from VacuumBreather/train_speed_adaptation
# Conflicts: # src/saveload/extended_ver_sl.cpp # src/saveload/extended_ver_sl.h
This commit is contained in:
@@ -479,6 +479,7 @@ add_files(
|
|||||||
train.h
|
train.h
|
||||||
train_cmd.cpp
|
train_cmd.cpp
|
||||||
train_gui.cpp
|
train_gui.cpp
|
||||||
|
train_speed_adaptation.h
|
||||||
transparency.h
|
transparency.h
|
||||||
transparency_gui.cpp
|
transparency_gui.cpp
|
||||||
transparency_gui.h
|
transparency_gui.h
|
||||||
|
@@ -39,6 +39,8 @@ YearMonthDay _game_load_cur_date_ymd;
|
|||||||
DateFract _game_load_date_fract;
|
DateFract _game_load_date_fract;
|
||||||
uint8 _game_load_tick_skip_counter;
|
uint8 _game_load_tick_skip_counter;
|
||||||
|
|
||||||
|
extern void ClearOutOfDateSignalSpeedRestrictions();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the date.
|
* Set the date.
|
||||||
* @param date New date
|
* @param date New date
|
||||||
@@ -283,6 +285,7 @@ static void OnNewDay()
|
|||||||
SetWindowWidgetDirty(WC_STATUS_BAR, 0, WID_S_LEFT);
|
SetWindowWidgetDirty(WC_STATUS_BAR, 0, WID_S_LEFT);
|
||||||
}
|
}
|
||||||
EnginesDailyLoop();
|
EnginesDailyLoop();
|
||||||
|
ClearOutOfDateSignalSpeedRestrictions();
|
||||||
|
|
||||||
/* Refresh after possible snowline change */
|
/* Refresh after possible snowline change */
|
||||||
SetWindowClassesDirty(WC_TOWN_VIEW);
|
SetWindowClassesDirty(WC_TOWN_VIEW);
|
||||||
|
@@ -1818,6 +1818,8 @@ STR_CONFIG_SETTING_NOSERVICE :Disable servici
|
|||||||
STR_CONFIG_SETTING_NOSERVICE_HELPTEXT :When enabled, vehicles do not get serviced if they cannot break down
|
STR_CONFIG_SETTING_NOSERVICE_HELPTEXT :When enabled, vehicles do not get serviced if they cannot break down
|
||||||
STR_CONFIG_SETTING_WAGONSPEEDLIMITS :Enable wagon speed limits: {STRING2}
|
STR_CONFIG_SETTING_WAGONSPEEDLIMITS :Enable wagon speed limits: {STRING2}
|
||||||
STR_CONFIG_SETTING_WAGONSPEEDLIMITS_HELPTEXT :When enabled, also use speed limits of wagons for deciding the maximum speed of a train
|
STR_CONFIG_SETTING_WAGONSPEEDLIMITS_HELPTEXT :When enabled, also use speed limits of wagons for deciding the maximum speed of a train
|
||||||
|
STR_CONFIG_SETTING_TRAIN_SPEED_ADAPTATION :Enable train speed adaptation: {STRING2}
|
||||||
|
STR_CONFIG_SETTING_TRAIN_SPEED_ADAPTATION_HELPTEXT :When enabled, faster trains adjust their speed to match slower trains in front.
|
||||||
STR_CONFIG_SETTING_SLOW_ROAD_VEHICLES_IN_CURVES :Road vehicles slow down in curves: {STRING2}
|
STR_CONFIG_SETTING_SLOW_ROAD_VEHICLES_IN_CURVES :Road vehicles slow down in curves: {STRING2}
|
||||||
STR_CONFIG_SETTING_SLOW_ROAD_VEHICLES_IN_CURVES_HELPTEXT :When enabled, road vehicles slow down in curves. (Only with realistic acceleration)
|
STR_CONFIG_SETTING_SLOW_ROAD_VEHICLES_IN_CURVES_HELPTEXT :When enabled, road vehicles slow down in curves. (Only with realistic acceleration)
|
||||||
STR_CONFIG_SETTING_DISABLE_ELRAILS :Disable electric rails: {STRING2}
|
STR_CONFIG_SETTING_DISABLE_ELRAILS :Disable electric rails: {STRING2}
|
||||||
|
@@ -1743,6 +1743,10 @@ STR_CONFIG_SETTING_NOSERVICE :Wartung deaktiv
|
|||||||
STR_CONFIG_SETTING_NOSERVICE_HELPTEXT :Schicke Fahrzeuge nicht zur Wartung, wenn Pannen ausgeschaltet sind
|
STR_CONFIG_SETTING_NOSERVICE_HELPTEXT :Schicke Fahrzeuge nicht zur Wartung, wenn Pannen ausgeschaltet sind
|
||||||
STR_CONFIG_SETTING_WAGONSPEEDLIMITS :Berücksichtige Waggonhöchstgeschwindigkeit: {STRING}
|
STR_CONFIG_SETTING_WAGONSPEEDLIMITS :Berücksichtige Waggonhöchstgeschwindigkeit: {STRING}
|
||||||
STR_CONFIG_SETTING_WAGONSPEEDLIMITS_HELPTEXT :Begrenze die Höchstgeschwindigkeit eines Zuges durch die jeweiligen Höchstgeschwindigkeiten der mitgeführten Waggons
|
STR_CONFIG_SETTING_WAGONSPEEDLIMITS_HELPTEXT :Begrenze die Höchstgeschwindigkeit eines Zuges durch die jeweiligen Höchstgeschwindigkeiten der mitgeführten Waggons
|
||||||
|
STR_CONFIG_SETTING_TRAIN_SPEED_ADAPTATION :Zuggeschwindigkeitsanpassung aktivieren: {STRING}
|
||||||
|
STR_CONFIG_SETTING_TRAIN_SPEED_ADAPTATION_HELPTEXT :Wenn aktiviert, passen schnellere Züge hinter langsameren Zügen ihre Geschwindigkeit an.
|
||||||
|
STR_CONFIG_SETTING_SLOW_ROAD_VEHICLES_IN_CURVES :Straßenfahrzeuge werden in Kurven langsamer: {STRING}
|
||||||
|
STR_CONFIG_SETTING_SLOW_ROAD_VEHICLES_IN_CURVES_HELPTEXT :Wenn aktiviert, verlangsamen Straßenfahrzeuge in Kurven. (Nur im Beschleunigungsmodell „Realistisch“)
|
||||||
STR_CONFIG_SETTING_DISABLE_ELRAILS :Deaktiviere elektrifizierte Strecken: {STRING}
|
STR_CONFIG_SETTING_DISABLE_ELRAILS :Deaktiviere elektrifizierte Strecken: {STRING}
|
||||||
STR_CONFIG_SETTING_DISABLE_ELRAILS_HELPTEXT :Erlaube Elektrolokomotiven das Fahren auf nicht elektrifizierten Gleisen
|
STR_CONFIG_SETTING_DISABLE_ELRAILS_HELPTEXT :Erlaube Elektrolokomotiven das Fahren auf nicht elektrifizierten Gleisen
|
||||||
|
|
||||||
|
@@ -43,6 +43,7 @@
|
|||||||
|
|
||||||
|
|
||||||
extern TileIndex _cur_tileloop_tile;
|
extern TileIndex _cur_tileloop_tile;
|
||||||
|
extern void ClearAllSignalSpeedRestrictions();
|
||||||
extern void MakeNewgameSettingsLive();
|
extern void MakeNewgameSettingsLive();
|
||||||
|
|
||||||
void InitializeSound();
|
void InitializeSound();
|
||||||
@@ -118,6 +119,8 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
|
|||||||
FreeSignalPrograms();
|
FreeSignalPrograms();
|
||||||
FreeSignalDependencies();
|
FreeSignalDependencies();
|
||||||
|
|
||||||
|
ClearAllSignalSpeedRestrictions();
|
||||||
|
|
||||||
ClearZoningCaches();
|
ClearZoningCaches();
|
||||||
IntialiseOrderDestinationRefcountMap();
|
IntialiseOrderDestinationRefcountMap();
|
||||||
|
|
||||||
|
@@ -439,6 +439,9 @@ static void ShutdownGame()
|
|||||||
FreeSignalPrograms();
|
FreeSignalPrograms();
|
||||||
FreeSignalDependencies();
|
FreeSignalDependencies();
|
||||||
|
|
||||||
|
extern void ClearAllSignalSpeedRestrictions();
|
||||||
|
ClearAllSignalSpeedRestrictions();
|
||||||
|
|
||||||
ClearZoningCaches();
|
ClearZoningCaches();
|
||||||
ClearOrderDestinationRefcountMap();
|
ClearOrderDestinationRefcountMap();
|
||||||
|
|
||||||
|
@@ -48,6 +48,7 @@ add_files(
|
|||||||
tbtr_template_veh_sl.cpp
|
tbtr_template_veh_sl.cpp
|
||||||
town_sl.cpp
|
town_sl.cpp
|
||||||
tracerestrict_sl.cpp
|
tracerestrict_sl.cpp
|
||||||
|
train_speed_adaptation.cpp
|
||||||
tunnel_sl.cpp
|
tunnel_sl.cpp
|
||||||
vehicle_sl.cpp
|
vehicle_sl.cpp
|
||||||
waypoint_sl.cpp
|
waypoint_sl.cpp
|
||||||
|
@@ -938,6 +938,10 @@ bool AfterLoadGame()
|
|||||||
_settings_game.vehicle.train_braking_model = TBM_ORIGINAL;
|
_settings_game.vehicle.train_braking_model = TBM_ORIGINAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SlXvIsFeatureMissing(XSLFI_TRAIN_SPEED_ADAPTATION)) {
|
||||||
|
_settings_game.vehicle.train_speed_adaptation = false;
|
||||||
|
}
|
||||||
|
|
||||||
AfterLoadEngines();
|
AfterLoadEngines();
|
||||||
|
|
||||||
/* Update all vehicles */
|
/* Update all vehicles */
|
||||||
|
@@ -152,6 +152,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
|
|||||||
{ XSLFI_MORE_HOUSES, XSCF_NULL, 2, 2, "more_houses", nullptr, nullptr, nullptr },
|
{ XSLFI_MORE_HOUSES, XSCF_NULL, 2, 2, "more_houses", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_CUSTOM_TOWN_ZONE, XSCF_IGNORABLE_UNKNOWN, 1, 1, "custom_town_zone", nullptr, nullptr, nullptr },
|
{ XSLFI_CUSTOM_TOWN_ZONE, XSCF_IGNORABLE_UNKNOWN, 1, 1, "custom_town_zone", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_STATION_CARGO_HISTORY, XSCF_NULL, 1, 1, "station_cargo_history", nullptr, nullptr, nullptr },
|
{ XSLFI_STATION_CARGO_HISTORY, XSCF_NULL, 1, 1, "station_cargo_history", nullptr, nullptr, nullptr },
|
||||||
|
{ XSLFI_TRAIN_SPEED_ADAPTATION, XSCF_NULL, 1, 1, "train_speed_adaptation", nullptr, nullptr, "TSAS" },
|
||||||
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
|
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -106,6 +106,7 @@ enum SlXvFeatureIndex {
|
|||||||
XSLFI_MORE_HOUSES, ///< More house types
|
XSLFI_MORE_HOUSES, ///< More house types
|
||||||
XSLFI_CUSTOM_TOWN_ZONE, ///< Custom town zones
|
XSLFI_CUSTOM_TOWN_ZONE, ///< Custom town zones
|
||||||
XSLFI_STATION_CARGO_HISTORY, ///< Station waiting cargo history
|
XSLFI_STATION_CARGO_HISTORY, ///< Station waiting cargo history
|
||||||
|
XSLFI_TRAIN_SPEED_ADAPTATION, ///< Train speed adaptation
|
||||||
|
|
||||||
XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit
|
XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit
|
||||||
XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk
|
XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk
|
||||||
|
@@ -288,6 +288,7 @@ extern const ChunkHandler _template_replacement_chunk_handlers[];
|
|||||||
extern const ChunkHandler _template_vehicle_chunk_handlers[];
|
extern const ChunkHandler _template_vehicle_chunk_handlers[];
|
||||||
extern const ChunkHandler _bridge_signal_chunk_handlers[];
|
extern const ChunkHandler _bridge_signal_chunk_handlers[];
|
||||||
extern const ChunkHandler _tunnel_chunk_handlers[];
|
extern const ChunkHandler _tunnel_chunk_handlers[];
|
||||||
|
extern const ChunkHandler _train_speed_adaptation_chunk_handlers[];
|
||||||
extern const ChunkHandler _debug_chunk_handlers[];
|
extern const ChunkHandler _debug_chunk_handlers[];
|
||||||
|
|
||||||
/** Array of all chunks in a savegame, \c nullptr terminated. */
|
/** Array of all chunks in a savegame, \c nullptr terminated. */
|
||||||
@@ -333,6 +334,7 @@ static const ChunkHandler * const _chunk_handlers[] = {
|
|||||||
_template_vehicle_chunk_handlers,
|
_template_vehicle_chunk_handlers,
|
||||||
_bridge_signal_chunk_handlers,
|
_bridge_signal_chunk_handlers,
|
||||||
_tunnel_chunk_handlers,
|
_tunnel_chunk_handlers,
|
||||||
|
_train_speed_adaptation_chunk_handlers,
|
||||||
_debug_chunk_handlers,
|
_debug_chunk_handlers,
|
||||||
nullptr,
|
nullptr,
|
||||||
};
|
};
|
||||||
|
51
src/saveload/train_speed_adaptation.cpp
Normal file
51
src/saveload/train_speed_adaptation.cpp
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file train_speed_adaptation.cpp Code handling saving and loading of data for train speed adaptation */
|
||||||
|
|
||||||
|
#include "../stdafx.h"
|
||||||
|
#include "../train_speed_adaptation.h"
|
||||||
|
#include "saveload.h"
|
||||||
|
|
||||||
|
using SignalSpeedType = std::pair<const SignalSpeedKey, SignalSpeedValue>;
|
||||||
|
|
||||||
|
static const SaveLoad _train_speed_adaptation_map_desc[] = {
|
||||||
|
SLE_VAR(SignalSpeedType, first.signal_track, SLE_UINT8),
|
||||||
|
SLE_VAR(SignalSpeedType, first.last_passing_train_dir, SLE_UINT8),
|
||||||
|
SLE_VAR(SignalSpeedType, second.train_speed, SLE_UINT16),
|
||||||
|
SLE_VAR(SignalSpeedType, second.time_stamp, SLE_UINT64),
|
||||||
|
SLE_END()
|
||||||
|
};
|
||||||
|
|
||||||
|
static void Load_TSAS()
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
SignalSpeedType data;
|
||||||
|
while ((index = SlIterateArray()) != -1) {
|
||||||
|
const_cast<SignalSpeedKey &>(data.first).signal_tile = index;
|
||||||
|
SlObject(&data, _train_speed_adaptation_map_desc);
|
||||||
|
_signal_speeds.insert(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RealSave_TSAS(SignalSpeedType *data)
|
||||||
|
{
|
||||||
|
SlObject(data, _train_speed_adaptation_map_desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Save_TSAS()
|
||||||
|
{
|
||||||
|
for (auto &it : _signal_speeds) {
|
||||||
|
SlSetArrayIndex(it.first.signal_tile);
|
||||||
|
SignalSpeedType *data = ⁢
|
||||||
|
SlAutolength((AutolengthProc*) RealSave_TSAS, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const ChunkHandler _train_speed_adaptation_chunk_handlers[] = {
|
||||||
|
{ 'TSAS', Save_TSAS, Load_TSAS, nullptr, nullptr, CH_SPARSE_ARRAY | CH_LAST},
|
||||||
|
};
|
@@ -807,6 +807,7 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
|
|||||||
SLE_CONDNULL(11, SLV_2, SLV_144), // old reserved space
|
SLE_CONDNULL(11, SLV_2, SLV_144), // old reserved space
|
||||||
SLE_CONDVAR_X(Train, reverse_distance, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_REVERSE_AT_WAYPOINT)),
|
SLE_CONDVAR_X(Train, reverse_distance, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_REVERSE_AT_WAYPOINT)),
|
||||||
SLE_CONDVAR_X(Train, speed_restriction, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_SPEED_RESTRICTION)),
|
SLE_CONDVAR_X(Train, speed_restriction, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_SPEED_RESTRICTION)),
|
||||||
|
SLE_CONDVAR_X(Train, signal_speed_restriction, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TRAIN_SPEED_ADAPTATION)),
|
||||||
SLE_CONDVAR_X(Train, critical_breakdown_count, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_IMPROVED_BREAKDOWNS, 2)),
|
SLE_CONDVAR_X(Train, critical_breakdown_count, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_IMPROVED_BREAKDOWNS, 2)),
|
||||||
|
|
||||||
SLE_END()
|
SLE_END()
|
||||||
|
@@ -1541,6 +1541,15 @@ static bool PublicRoadsSettingChange(int32 p1) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool TrainSpeedAdaptationChanged(int32 p1) {
|
||||||
|
extern void ClearAllSignalSpeedRestrictions();
|
||||||
|
ClearAllSignalSpeedRestrictions();
|
||||||
|
for (Train *t : Train::Iterate()) {
|
||||||
|
t->signal_speed_restriction = 0;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/** Checks if any settings are set to incorrect values, and sets them to correct values in that case. */
|
/** Checks if any settings are set to incorrect values, and sets them to correct values in that case. */
|
||||||
static void ValidateSettings()
|
static void ValidateSettings()
|
||||||
{
|
{
|
||||||
@@ -1784,7 +1793,12 @@ static bool ImprovedBreakdownsSettingChanged(int32 p1)
|
|||||||
|
|
||||||
static bool DayLengthChanged(int32 p1)
|
static bool DayLengthChanged(int32 p1)
|
||||||
{
|
{
|
||||||
|
const DateTicksScaled old_scaled_date_ticks = _scaled_date_ticks;
|
||||||
SetScaledTickVariables();
|
SetScaledTickVariables();
|
||||||
|
|
||||||
|
extern void AdjustAllSignalSpeedRestrictionTickValues(DateTicksScaled delta);
|
||||||
|
AdjustAllSignalSpeedRestrictionTickValues(_scaled_date_ticks - old_scaled_date_ticks);
|
||||||
|
|
||||||
MarkWholeScreenDirty();
|
MarkWholeScreenDirty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -1924,6 +1924,7 @@ static SettingsContainer &GetSettingsTree()
|
|||||||
physics->Add(new SettingEntry("vehicle.train_braking_model"));
|
physics->Add(new SettingEntry("vehicle.train_braking_model"));
|
||||||
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.freight_trains"));
|
physics->Add(new SettingEntry("vehicle.freight_trains"));
|
||||||
physics->Add(new SettingEntry("vehicle.roadveh_acceleration_model"));
|
physics->Add(new SettingEntry("vehicle.roadveh_acceleration_model"));
|
||||||
physics->Add(new SettingEntry("vehicle.roadveh_slope_steepness"));
|
physics->Add(new SettingEntry("vehicle.roadveh_slope_steepness"));
|
||||||
|
@@ -573,6 +573,7 @@ struct VehicleSettings {
|
|||||||
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
|
||||||
bool wagon_speed_limits; ///< enable wagon speed limits
|
bool wagon_speed_limits; ///< enable wagon speed limits
|
||||||
|
bool train_speed_adaptation; ///< Faster trains slow down when behind slower trains
|
||||||
bool slow_road_vehicles_in_curves; ///< Road vehicles slow down in curves.
|
bool slow_road_vehicles_in_curves; ///< Road vehicles slow down in curves.
|
||||||
bool disable_elrails; ///< when true, the elrails are disabled
|
bool disable_elrails; ///< when true, the elrails are disabled
|
||||||
UnitID max_trains; ///< max trains in game per company
|
UnitID max_trains; ///< max trains in game per company
|
||||||
|
@@ -162,8 +162,11 @@ class NIHVehicle : public NIHelper {
|
|||||||
seprintf(buffer, lastof(buffer), " T cache: veh weight: %u, user data: %u, curve speed: %u",
|
seprintf(buffer, lastof(buffer), " T cache: veh weight: %u, user data: %u, curve speed: %u",
|
||||||
t->tcache.cached_veh_weight, t->tcache.user_def_data, t->tcache.cached_max_curve_speed);
|
t->tcache.cached_veh_weight, t->tcache.user_def_data, t->tcache.cached_max_curve_speed);
|
||||||
print(buffer);
|
print(buffer);
|
||||||
seprintf(buffer, lastof(buffer), " Wait counter: %u, rev distance: %u, TBSN: %u, speed restriction: %u",
|
seprintf(buffer, lastof(buffer), " Wait counter: %u, rev distance: %u, TBSN: %u",
|
||||||
t->wait_counter, t->reverse_distance, t->tunnel_bridge_signal_num, t->speed_restriction);
|
t->wait_counter, t->reverse_distance, t->tunnel_bridge_signal_num);
|
||||||
|
print(buffer);
|
||||||
|
seprintf(buffer, lastof(buffer), " Speed restriction: %u, signal speed restriction (ATC): %u",
|
||||||
|
t->speed_restriction, t->signal_speed_restriction);
|
||||||
print(buffer);
|
print(buffer);
|
||||||
seprintf(buffer, lastof(buffer), " Railtype: %u, compatible_railtypes: 0x" OTTD_PRINTFHEX64,
|
seprintf(buffer, lastof(buffer), " Railtype: %u, compatible_railtypes: 0x" OTTD_PRINTFHEX64,
|
||||||
t->railtype, t->compatible_railtypes);
|
t->railtype, t->compatible_railtypes);
|
||||||
|
@@ -64,6 +64,7 @@ static bool ClimateThresholdModeChanged(int32 p1);
|
|||||||
static bool VelocityUnitsChanged(int32 p1);
|
static bool VelocityUnitsChanged(int32 p1);
|
||||||
static bool ChangeTrackTypeSortMode(int32 p1);
|
static bool ChangeTrackTypeSortMode(int32 p1);
|
||||||
static bool PublicRoadsSettingChange(int32 p1);
|
static bool PublicRoadsSettingChange(int32 p1);
|
||||||
|
static bool TrainSpeedAdaptationChanged(int32 p1);
|
||||||
|
|
||||||
static bool UpdateClientName(int32 p1);
|
static bool UpdateClientName(int32 p1);
|
||||||
static bool UpdateServerPassword(int32 p1);
|
static bool UpdateServerPassword(int32 p1);
|
||||||
@@ -1675,10 +1676,19 @@ strhelp = STR_CONFIG_SETTING_SLOW_ROAD_VEHICLES_IN_CURVES_HELPTEXT
|
|||||||
cat = SC_BASIC
|
cat = SC_BASIC
|
||||||
patxname = ""slow_road_vehicles_in_curves.vehicle.slow_road_vehicles_in_curves""
|
patxname = ""slow_road_vehicles_in_curves.vehicle.slow_road_vehicles_in_curves""
|
||||||
|
|
||||||
;; vehicle.train_speed_adaption
|
[SDT_XREF]
|
||||||
[SDT_NULL]
|
|
||||||
length = 1
|
|
||||||
extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_JOKERPP)
|
extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_JOKERPP)
|
||||||
|
xref = ""vehicle.train_speed_adaptation""
|
||||||
|
|
||||||
|
[SDT_BOOL]
|
||||||
|
base = GameSettings
|
||||||
|
var = vehicle.train_speed_adaptation
|
||||||
|
def = false
|
||||||
|
str = STR_CONFIG_SETTING_TRAIN_SPEED_ADAPTATION
|
||||||
|
strhelp = STR_CONFIG_SETTING_TRAIN_SPEED_ADAPTATION_HELPTEXT
|
||||||
|
cat = SC_EXPERT
|
||||||
|
proc = TrainSpeedAdaptationChanged
|
||||||
|
patxname = ""train_speed_adaptation.vehicle.train_speed_adaptation""
|
||||||
|
|
||||||
[SDT_BOOL]
|
[SDT_BOOL]
|
||||||
base = GameSettings
|
base = GameSettings
|
||||||
|
@@ -147,6 +147,7 @@ struct Train FINAL : public GroundVehicle<Train, VEH_TRAIN> {
|
|||||||
uint16 reverse_distance;
|
uint16 reverse_distance;
|
||||||
uint16 tunnel_bridge_signal_num;
|
uint16 tunnel_bridge_signal_num;
|
||||||
uint16 speed_restriction;
|
uint16 speed_restriction;
|
||||||
|
uint16 signal_speed_restriction;
|
||||||
|
|
||||||
/** We don't want GCC to zero our struct! It already is zeroed and has an index! */
|
/** We don't want GCC to zero our struct! It already is zeroed and has an index! */
|
||||||
Train() : GroundVehicleBase() {}
|
Train() : GroundVehicleBase() {}
|
||||||
|
@@ -44,6 +44,7 @@
|
|||||||
#include "scope.h"
|
#include "scope.h"
|
||||||
#include "core/checksum_func.hpp"
|
#include "core/checksum_func.hpp"
|
||||||
#include "debug_settings.h"
|
#include "debug_settings.h"
|
||||||
|
#include "train_speed_adaptation.h"
|
||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
#include "table/train_cmd.h"
|
#include "table/train_cmd.h"
|
||||||
@@ -76,6 +77,8 @@ enum ChooseTrainTrackFlags {
|
|||||||
};
|
};
|
||||||
DECLARE_ENUM_AS_BIT_SET(ChooseTrainTrackFlags)
|
DECLARE_ENUM_AS_BIT_SET(ChooseTrainTrackFlags)
|
||||||
|
|
||||||
|
std::unordered_map<SignalSpeedKey, SignalSpeedValue, SignalSpeedKeyHashFunc> _signal_speeds(1 << 16);
|
||||||
|
|
||||||
static void TryLongReserveChooseTrainTrackFromReservationEnd(Train *v, bool no_reserve_vehicle_tile = false);
|
static void TryLongReserveChooseTrainTrackFromReservationEnd(Train *v, bool no_reserve_vehicle_tile = false);
|
||||||
static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, ChooseTrainTrackFlags flags, bool *p_got_reservation, ChooseTrainTrackLookAheadState lookahead_state = {});
|
static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, ChooseTrainTrackFlags flags, bool *p_got_reservation, ChooseTrainTrackLookAheadState lookahead_state = {});
|
||||||
static bool TrainApproachingLineEnd(Train *v, bool signal, bool reverse);
|
static bool TrainApproachingLineEnd(Train *v, bool signal, bool reverse);
|
||||||
@@ -92,6 +95,52 @@ static void TrainEnterStation(Train *v, StationID station);
|
|||||||
static void UnreserveBridgeTunnelTile(TileIndex tile);
|
static void UnreserveBridgeTunnelTile(TileIndex tile);
|
||||||
static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile);
|
static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile);
|
||||||
|
|
||||||
|
/** Return the scaled date ticks by which the speed restriction
|
||||||
|
* at the current position of the train is going to be invalid */
|
||||||
|
static DateTicksScaled GetSpeedRestrictionTimeout(const Train *t)
|
||||||
|
{
|
||||||
|
const int64 velocity = std::max<int64>(25, t->cur_speed);
|
||||||
|
const int64 look_ahead_distance = Clamp(t->cur_speed / 8, 6, 16); // In tiles, varying between 6 and 16 depending on current speed
|
||||||
|
|
||||||
|
// This assumes travel along the X or Y map axis, not diagonally. See GetAdvanceDistance, GetAdvanceSpeed.
|
||||||
|
const int64 ticks_per_tile = (192 * 16 * 4 / 3) / velocity;
|
||||||
|
|
||||||
|
const int64 ticks = ticks_per_tile * look_ahead_distance;
|
||||||
|
|
||||||
|
return _scaled_date_ticks + ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if the timeout of the specified signal speed restriction value has passed */
|
||||||
|
static bool IsOutOfDate(const SignalSpeedValue& value)
|
||||||
|
{
|
||||||
|
return _scaled_date_ticks > value.time_stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Removes all speed restrictions from all signals */
|
||||||
|
void ClearAllSignalSpeedRestrictions()
|
||||||
|
{
|
||||||
|
_signal_speeds.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdjustAllSignalSpeedRestrictionTickValues(DateTicksScaled delta)
|
||||||
|
{
|
||||||
|
for (auto &it : _signal_speeds) {
|
||||||
|
it.second.time_stamp += delta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Removes all speed restrictions which have passed their timeout from all signals */
|
||||||
|
void ClearOutOfDateSignalSpeedRestrictions()
|
||||||
|
{
|
||||||
|
for(auto key_value_pair = _signal_speeds.begin(); key_value_pair != _signal_speeds.end(); ) {
|
||||||
|
if (IsOutOfDate(key_value_pair->second)) {
|
||||||
|
key_value_pair = _signal_speeds.erase(key_value_pair);
|
||||||
|
} else {
|
||||||
|
++key_value_pair;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void ClearLookAheadIfInvalid(Train *v)
|
inline void ClearLookAheadIfInvalid(Train *v)
|
||||||
{
|
{
|
||||||
if (v->lookahead != nullptr && !ValidateLookAhead(v)) v->lookahead.reset();
|
if (v->lookahead != nullptr && !ValidateLookAhead(v)) v->lookahead.reset();
|
||||||
@@ -1024,6 +1073,9 @@ Train::MaxSpeedInfo Train::GetCurrentMaxSpeedInfoInternal(bool update_state) con
|
|||||||
if (this->speed_restriction != 0) {
|
if (this->speed_restriction != 0) {
|
||||||
advisory_max_speed = std::min<int>(advisory_max_speed, this->speed_restriction);
|
advisory_max_speed = std::min<int>(advisory_max_speed, this->speed_restriction);
|
||||||
}
|
}
|
||||||
|
if (this->signal_speed_restriction != 0 && _settings_game.vehicle.train_speed_adaptation) {
|
||||||
|
advisory_max_speed = std::min<int>(advisory_max_speed, this->signal_speed_restriction);
|
||||||
|
}
|
||||||
if (this->reverse_distance > 1) {
|
if (this->reverse_distance > 1) {
|
||||||
advisory_max_speed = std::min<int>(advisory_max_speed, ReversingDistanceTargetSpeed(this));
|
advisory_max_speed = std::min<int>(advisory_max_speed, ReversingDistanceTargetSpeed(this));
|
||||||
}
|
}
|
||||||
@@ -1328,6 +1380,7 @@ static CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const
|
|||||||
v->vehstatus = VS_HIDDEN | VS_DEFPAL;
|
v->vehstatus = VS_HIDDEN | VS_DEFPAL;
|
||||||
v->reverse_distance = 0;
|
v->reverse_distance = 0;
|
||||||
v->speed_restriction = 0;
|
v->speed_restriction = 0;
|
||||||
|
v->signal_speed_restriction = 0;
|
||||||
|
|
||||||
v->SetWagon();
|
v->SetWagon();
|
||||||
|
|
||||||
@@ -4444,6 +4497,7 @@ static void TrainEnterStation(Train *v, StationID station)
|
|||||||
v->current_order.MakeWaiting();
|
v->current_order.MakeWaiting();
|
||||||
v->current_order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION);
|
v->current_order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION);
|
||||||
v->cur_speed = 0;
|
v->cur_speed = 0;
|
||||||
|
v->signal_speed_restriction = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5500,7 +5554,33 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (update_signals_crossing) {
|
if (update_signals_crossing) {
|
||||||
|
|
||||||
if (v->IsFrontEngine()) {
|
if (v->IsFrontEngine()) {
|
||||||
|
if (_settings_game.vehicle.train_speed_adaptation && IsTileType(gp.old_tile, MP_RAILWAY) && HasSignals(gp.old_tile)) {
|
||||||
|
const TrackdirBits rev_tracks = TrackBitsToTrackdirBits(GetTrackBits(gp.old_tile)) & DiagdirReachesTrackdirs(ReverseDiagDir(enterdir));
|
||||||
|
const Trackdir rev_trackdir = FindFirstTrackdir(rev_tracks);
|
||||||
|
if (HasSignalOnTrackdir(gp.old_tile, ReverseTrackdir(rev_trackdir))) {
|
||||||
|
const Track track = TrackdirToTrack(rev_trackdir);
|
||||||
|
SignalSpeedKey speed_key = {
|
||||||
|
speed_key.signal_tile = gp.old_tile,
|
||||||
|
speed_key.signal_track = track,
|
||||||
|
speed_key.last_passing_train_dir = v->GetVehicleTrackdir()
|
||||||
|
};
|
||||||
|
const auto found_speed_restriction = _signal_speeds.find(speed_key);
|
||||||
|
|
||||||
|
if (found_speed_restriction != _signal_speeds.end()) {
|
||||||
|
if (IsOutOfDate(found_speed_restriction->second)) {
|
||||||
|
_signal_speeds.erase(found_speed_restriction);
|
||||||
|
v->signal_speed_restriction = 0;
|
||||||
|
} else {
|
||||||
|
v->signal_speed_restriction = std::max<uint16>(25, found_speed_restriction->second.train_speed);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
v->signal_speed_restriction = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (TrainMovedChangeSignal(v, gp.new_tile, enterdir, true)) {
|
switch (TrainMovedChangeSignal(v, gp.new_tile, enterdir, true)) {
|
||||||
case CHANGED_NORMAL_TO_PBS_BLOCK:
|
case CHANGED_NORMAL_TO_PBS_BLOCK:
|
||||||
/* We are entering a block with PBS signals right now, but
|
/* We are entering a block with PBS signals right now, but
|
||||||
@@ -5538,17 +5618,33 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
|
|||||||
TrainMovedChangeSignal(v, gp.old_tile, ReverseDiagDir(enterdir), false);
|
TrainMovedChangeSignal(v, gp.old_tile, ReverseDiagDir(enterdir), false);
|
||||||
if (IsLevelCrossingTile(gp.old_tile)) UpdateLevelCrossing(gp.old_tile);
|
if (IsLevelCrossingTile(gp.old_tile)) UpdateLevelCrossing(gp.old_tile);
|
||||||
|
|
||||||
if (IsTileType(gp.old_tile, MP_RAILWAY) && HasSignals(gp.old_tile) && IsRestrictedSignal(gp.old_tile)) {
|
if (IsTileType(gp.old_tile, MP_RAILWAY) && HasSignals(gp.old_tile)) {
|
||||||
const TrackdirBits rev_tracks = TrackBitsToTrackdirBits(GetTrackBits(gp.old_tile)) & DiagdirReachesTrackdirs(ReverseDiagDir(enterdir));
|
const TrackdirBits rev_tracks = TrackBitsToTrackdirBits(GetTrackBits(gp.old_tile)) & DiagdirReachesTrackdirs(ReverseDiagDir(enterdir));
|
||||||
const Trackdir rev_trackdir = FindFirstTrackdir(rev_tracks);
|
const Trackdir rev_trackdir = FindFirstTrackdir(rev_tracks);
|
||||||
const Track track = TrackdirToTrack(rev_trackdir);
|
const Track track = TrackdirToTrack(rev_trackdir);
|
||||||
|
|
||||||
|
if (_settings_game.vehicle.train_speed_adaptation && HasSignalOnTrackdir(gp.old_tile, ReverseTrackdir(rev_trackdir))) {
|
||||||
|
SignalSpeedKey speed_key = {
|
||||||
|
speed_key.signal_tile = gp.old_tile,
|
||||||
|
speed_key.signal_track = track,
|
||||||
|
speed_key.last_passing_train_dir = v->GetVehicleTrackdir()
|
||||||
|
};
|
||||||
|
SignalSpeedValue speed_value = {
|
||||||
|
speed_value.train_speed = v->First()->cur_speed,
|
||||||
|
speed_value.time_stamp = GetSpeedRestrictionTimeout(v->First())
|
||||||
|
};
|
||||||
|
_signal_speeds[speed_key] = speed_value;
|
||||||
|
}
|
||||||
|
|
||||||
if (HasSignalOnTrack(gp.old_tile, track)) {
|
if (HasSignalOnTrack(gp.old_tile, track)) {
|
||||||
const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(gp.old_tile, track);
|
if (IsRestrictedSignal(gp.old_tile)) {
|
||||||
if (prog && prog->actions_used_flags & TRPAUF_SLOT_RELEASE_BACK) {
|
const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(gp.old_tile, track);
|
||||||
TraceRestrictProgramResult out;
|
if (prog && prog->actions_used_flags & TRPAUF_SLOT_RELEASE_BACK) {
|
||||||
TraceRestrictProgramInput input(gp.old_tile, ReverseTrackdir(rev_trackdir), nullptr, nullptr);
|
TraceRestrictProgramResult out;
|
||||||
input.permitted_slot_operations = TRPISP_RELEASE_BACK;
|
TraceRestrictProgramInput input(gp.old_tile, ReverseTrackdir(rev_trackdir), nullptr, nullptr);
|
||||||
prog->Execute(first, input, out);
|
input.permitted_slot_operations = TRPISP_RELEASE_BACK;
|
||||||
|
prog->Execute(first, input, out);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
53
src/train_speed_adaptation.h
Normal file
53
src/train_speed_adaptation.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file train_speed_adaptation.h Train speed adaptation data structures. */
|
||||||
|
|
||||||
|
#ifndef TRAIN_SPEED_ADAPTATION_H
|
||||||
|
#define TRAIN_SPEED_ADAPTATION_H
|
||||||
|
|
||||||
|
#include "date_type.h"
|
||||||
|
#include "track_type.h"
|
||||||
|
#include "tile_type.h"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
struct SignalSpeedKey
|
||||||
|
{
|
||||||
|
TileIndex signal_tile;
|
||||||
|
Track signal_track;
|
||||||
|
Trackdir last_passing_train_dir;
|
||||||
|
|
||||||
|
bool operator==(const SignalSpeedKey& other) const
|
||||||
|
{
|
||||||
|
return signal_tile == other.signal_tile &&
|
||||||
|
signal_track == other.signal_track &&
|
||||||
|
last_passing_train_dir == other.last_passing_train_dir;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SignalSpeedValue
|
||||||
|
{
|
||||||
|
uint16 train_speed;
|
||||||
|
DateTicksScaled time_stamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SignalSpeedKeyHashFunc
|
||||||
|
{
|
||||||
|
std::size_t operator() (const SignalSpeedKey &key) const
|
||||||
|
{
|
||||||
|
const std::size_t h1 = std::hash<TileIndex>()(key.signal_tile);
|
||||||
|
const std::size_t h2 = std::hash<Trackdir>()(key.last_passing_train_dir);
|
||||||
|
const std::size_t h3 = std::hash<Track>()(key.signal_track);
|
||||||
|
|
||||||
|
return (h1 ^ h2) ^ h3;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
extern std::unordered_map<SignalSpeedKey, SignalSpeedValue, SignalSpeedKeyHashFunc> _signal_speeds;
|
||||||
|
|
||||||
|
#endif /* TRAIN_SPEED_ADAPTATION_H */
|
@@ -2417,6 +2417,7 @@ void VehicleEnterDepot(Vehicle *v)
|
|||||||
ClrBit(t->flags, VRF_TOGGLE_REVERSE);
|
ClrBit(t->flags, VRF_TOGGLE_REVERSE);
|
||||||
t->ConsistChanged(CCF_ARRANGE);
|
t->ConsistChanged(CCF_ARRANGE);
|
||||||
t->reverse_distance = 0;
|
t->reverse_distance = 0;
|
||||||
|
t->signal_speed_restriction = 0;
|
||||||
t->lookahead.reset();
|
t->lookahead.reset();
|
||||||
if (!(t->vehstatus & VS_CRASHED)) {
|
if (!(t->vehstatus & VS_CRASHED)) {
|
||||||
t->crash_anim_pos = 0;
|
t->crash_anim_pos = 0;
|
||||||
@@ -4309,4 +4310,7 @@ void ShiftVehicleDates(int interval)
|
|||||||
for (Vehicle *v : Vehicle::Iterate()) {
|
for (Vehicle *v : Vehicle::Iterate()) {
|
||||||
v->date_of_last_service += interval;
|
v->date_of_last_service += interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void AdjustAllSignalSpeedRestrictionTickValues(DateTicksScaled delta);
|
||||||
|
AdjustAllSignalSpeedRestrictionTickValues(interval * DAY_TICKS * _settings_game.economy.day_length_factor);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user