diff --git a/src/bridge_gui.cpp b/src/bridge_gui.cpp index 62f4c96b9b..0ed9ea78cc 100644 --- a/src/bridge_gui.cpp +++ b/src/bridge_gui.cpp @@ -138,7 +138,7 @@ private: StringID GetBridgeSelectString(const BuildBridgeData &bridge_data) const { SetDParam(0, bridge_data.spec->material); - SetDParam(1, bridge_data.spec->speed); + SetDParam(1, PackVelocity(bridge_data.spec->speed, static_cast(this->transport_type))); SetDParam(2, bridge_data.cost); /* If the bridge has no meaningful speed limit, don't display it. */ if (bridge_data.spec->speed == UINT16_MAX) { diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index b0d5d62e55..cc918c792a 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -611,7 +611,7 @@ static int DrawRailWagonPurchaseInfo(int left, int right, int y, EngineID engine if (_settings_game.vehicle.wagon_speed_limits) { uint max_speed = e->GetDisplayMaxSpeed(); if (max_speed > 0) { - SetDParam(0, max_speed); + SetDParam(0, PackVelocity(max_speed, e->type)); DrawString(left, right, y, STR_PURCHASE_INFO_SPEED); y += FONT_HEIGHT_NORMAL; } @@ -646,7 +646,7 @@ static int DrawRailEnginePurchaseInfo(int left, int right, int y, EngineID engin y += FONT_HEIGHT_NORMAL; /* Max speed - Engine power */ - SetDParam(0, e->GetDisplayMaxSpeed()); + SetDParam(0, PackVelocity(e->GetDisplayMaxSpeed(), e->type)); SetDParam(1, e->GetPower()); DrawString(left, right, y, STR_PURCHASE_INFO_SPEED_POWER); y += FONT_HEIGHT_NORMAL; @@ -701,7 +701,7 @@ static int DrawRoadVehPurchaseInfo(int left, int right, int y, EngineID engine_n y += FONT_HEIGHT_NORMAL; /* Max speed - Engine power */ - SetDParam(0, e->GetDisplayMaxSpeed()); + SetDParam(0, PackVelocity(e->GetDisplayMaxSpeed(), e->type)); SetDParam(1, e->GetPower()); DrawString(left, right, y, STR_PURCHASE_INFO_SPEED_POWER); y += FONT_HEIGHT_NORMAL; @@ -715,11 +715,11 @@ static int DrawRoadVehPurchaseInfo(int left, int right, int y, EngineID engine_n if (te.cost != 0) { SetDParam(0, e->GetCost() + te.cost); SetDParam(1, te.cost); - SetDParam(2, e->GetDisplayMaxSpeed()); + SetDParam(2, PackVelocity(e->GetDisplayMaxSpeed(), e->type)); DrawString(left, right, y, STR_PURCHASE_INFO_COST_REFIT_SPEED); } else { SetDParam(0, e->GetCost()); - SetDParam(1, e->GetDisplayMaxSpeed()); + SetDParam(1, PackVelocity(e->GetDisplayMaxSpeed(), e->type)); DrawString(left, right, y, STR_PURCHASE_INFO_COST_SPEED); } y += FONT_HEIGHT_NORMAL; @@ -747,11 +747,11 @@ static int DrawShipPurchaseInfo(int left, int right, int y, EngineID engine_numb if (te.cost != 0) { SetDParam(0, e->GetCost() + te.cost); SetDParam(1, te.cost); - SetDParam(2, ocean_speed); + SetDParam(2, PackVelocity(ocean_speed, e->type)); DrawString(left, right, y, STR_PURCHASE_INFO_COST_REFIT_SPEED); } else { SetDParam(0, e->GetCost()); - SetDParam(1, ocean_speed); + SetDParam(1, PackVelocity(ocean_speed, e->type)); DrawString(left, right, y, STR_PURCHASE_INFO_COST_SPEED); } y += FONT_HEIGHT_NORMAL; @@ -766,11 +766,11 @@ static int DrawShipPurchaseInfo(int left, int right, int y, EngineID engine_numb } y += FONT_HEIGHT_NORMAL; - SetDParam(0, ocean_speed); + SetDParam(0, PackVelocity(ocean_speed, e->type)); DrawString(left, right, y, STR_PURCHASE_INFO_SPEED_OCEAN); y += FONT_HEIGHT_NORMAL; - SetDParam(0, canal_speed); + SetDParam(0, PackVelocity(canal_speed, e->type)); DrawString(left, right, y, STR_PURCHASE_INFO_SPEED_CANAL); y += FONT_HEIGHT_NORMAL; } @@ -807,11 +807,11 @@ static int DrawAircraftPurchaseInfo(int left, int right, int y, EngineID engine_ if (te.cost != 0) { SetDParam(0, e->GetCost() + te.cost); SetDParam(1, te.cost); - SetDParam(2, e->GetDisplayMaxSpeed()); + SetDParam(2, PackVelocity(e->GetDisplayMaxSpeed(), e->type)); DrawString(left, right, y, STR_PURCHASE_INFO_COST_REFIT_SPEED); } else { SetDParam(0, e->GetCost()); - SetDParam(1, e->GetDisplayMaxSpeed()); + SetDParam(1, PackVelocity(e->GetDisplayMaxSpeed(), e->type)); DrawString(left, right, y, STR_PURCHASE_INFO_COST_SPEED); } y += FONT_HEIGHT_NORMAL; diff --git a/src/engine_gui.cpp b/src/engine_gui.cpp index 11a1cd7f3e..6b56ef91f9 100644 --- a/src/engine_gui.cpp +++ b/src/engine_gui.cpp @@ -170,7 +170,7 @@ uint GetTotalCapacityOfArticulatedParts(EngineID engine) static StringID GetTrainEngineInfoString(const Engine *e) { SetDParam(0, e->GetCost()); - SetDParam(2, e->GetDisplayMaxSpeed()); + SetDParam(2, PackVelocity(e->GetDisplayMaxSpeed(), e->type)); SetDParam(3, e->GetPower()); SetDParam(1, e->GetDisplayWeight()); SetDParam(7, e->GetDisplayMaxTractiveEffort()); @@ -196,7 +196,7 @@ static StringID GetAircraftEngineInfoString(const Engine *e) uint i = 0; SetDParam(i++, e->GetCost()); - SetDParam(i++, e->GetDisplayMaxSpeed()); + SetDParam(i++, PackVelocity(e->GetDisplayMaxSpeed(), e->type)); SetDParam(i++, e->GetAircraftTypeText()); if (range > 0) SetDParam(i++, range); SetDParam(i++, cargo); @@ -217,7 +217,7 @@ static StringID GetRoadVehEngineInfoString(const Engine *e) { if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) { SetDParam(0, e->GetCost()); - SetDParam(1, e->GetDisplayMaxSpeed()); + SetDParam(1, PackVelocity(e->GetDisplayMaxSpeed(), e->type)); uint capacity = GetTotalCapacityOfArticulatedParts(e->index); if (capacity != 0) { SetDParam(2, e->GetDefaultCargoType()); @@ -229,7 +229,7 @@ static StringID GetRoadVehEngineInfoString(const Engine *e) return STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST; } else { SetDParam(0, e->GetCost()); - SetDParam(2, e->GetDisplayMaxSpeed()); + SetDParam(2, PackVelocity(e->GetDisplayMaxSpeed(), e->type)); SetDParam(3, e->GetPower()); SetDParam(1, e->GetDisplayWeight()); SetDParam(7, e->GetDisplayMaxTractiveEffort()); @@ -250,7 +250,7 @@ static StringID GetRoadVehEngineInfoString(const Engine *e) static StringID GetShipEngineInfoString(const Engine *e) { SetDParam(0, e->GetCost()); - SetDParam(1, e->GetDisplayMaxSpeed()); + SetDParam(1, PackVelocity(e->GetDisplayMaxSpeed(), e->type)); SetDParam(2, e->GetDefaultCargoType()); SetDParam(3, e->GetDisplayDefaultCapacity()); SetDParam(4, e->GetRunningCost()); diff --git a/src/lang/english.txt b/src/lang/english.txt index a0aec4db7b..55a8a21425 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -195,6 +195,7 @@ STR_UNITS_VELOCITY_IMPERIAL :{COMMA}{NBSP}mp STR_UNITS_VELOCITY_METRIC :{COMMA}{NBSP}km/h STR_UNITS_VELOCITY_SI :{COMMA}{NBSP}m/s STR_UNITS_VELOCITY_GAMEUNITS :{DECIMAL}{NBSP}tiles/day +STR_UNITS_VELOCITY_KNOTS :{COMMA}{NBSP}knots STR_UNITS_POWER_IMPERIAL :{COMMA}{NBSP}hp STR_UNITS_POWER_METRIC :{COMMA}{NBSP}hp @@ -1951,13 +1952,15 @@ STR_CONFIG_SETTING_DEMAND_SIZE_HELPTEXT :Setting this to STR_CONFIG_SETTING_SHORT_PATH_SATURATION :Saturation of short paths before using high-capacity paths: {STRING2} STR_CONFIG_SETTING_SHORT_PATH_SATURATION_HELPTEXT :Frequently there are multiple paths between two given stations. Cargodist will saturate the shortest path first, then use the second shortest path until that is saturated and so on. Saturation is determined by an estimation of capacity and planned usage. Once it has saturated all paths, if there is still demand left, it will overload all paths, prefering the ones with high capacity. Most of the time the algorithm will not estimate the capacity accurately, though. This setting allows you to specify up to which percentage a shorter path must be saturated in the first pass before choosing the next longer one. Set it to less than 100% to avoid overcrowded stations in case of overestimated capacity. -STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY :Speed units: {STRING2} +STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY :Speed units (land): {STRING2} +STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_NAUTICAL :Speed units (nautical): {STRING2} STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT :Whenever a speed is shown in the user interface, show it in the selected units -###length 4 +###length 5 STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_IMPERIAL :Imperial (mph) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_METRIC :Metric (km/h) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_SI :SI (m/s) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS :Game units (tiles/day) +STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_KNOTS :Knots STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER :Vehicle power units: {STRING2} STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_HELPTEXT :Whenever a vehicle's power is shown in the user interface, show it in the selected units diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 3f6b03585d..f7567d0ed1 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -267,7 +267,7 @@ public: /* Rail speed limit */ if (td.rail_speed != 0) { - SetDParam(0, td.rail_speed); + SetDParam(0, PackVelocity(td.rail_speed, VEH_TRAIN)); this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT)); } @@ -279,7 +279,7 @@ public: /* Road speed limit */ if (td.road_speed != 0) { - SetDParam(0, td.road_speed); + SetDParam(0, PackVelocity(td.road_speed, VEH_ROAD)); this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT)); } @@ -291,7 +291,7 @@ public: /* Tram speed limit */ if (td.tram_speed != 0) { - SetDParam(0, td.tram_speed); + SetDParam(0, PackVelocity(td.tram_speed, VEH_ROAD)); this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_TRAM_SPEED_LIMIT)); } diff --git a/src/order_gui.cpp b/src/order_gui.cpp index db9074784b..2f68e0b839 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -177,8 +177,8 @@ static const StringID _order_conditional_condition[] = { INVALID_STRING_ID, }; -extern uint ConvertSpeedToDisplaySpeed(uint speed); -extern uint ConvertDisplaySpeedToSpeed(uint speed); +extern uint ConvertSpeedToDisplaySpeed(uint speed, VehicleType type); +extern uint ConvertDisplaySpeedToSpeed(uint speed, VehicleType type); static const StringID _order_depot_action_dropdown[] = { STR_ORDER_DROP_GO_ALWAYS_DEPOT, @@ -345,7 +345,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int SetDParam(3, STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + occ); uint value = order->GetConditionValue(); - if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value); + if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value, v->type); SetDParam(4, value); } @@ -1149,7 +1149,7 @@ public: if (order != nullptr && order->IsType(OT_CONDITIONAL)) { uint value = order->GetConditionValue(); - if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value); + if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value, this->vehicle->type); SetDParam(0, value); } break; @@ -1317,7 +1317,7 @@ public: const Order *order = this->vehicle->GetOrder(this->OrderGetSel()); assert(order != nullptr); uint value = order->GetConditionValue(); - if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value); + if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value, this->vehicle->type); SetDParam(0, value); ShowQueryString(STR_JUST_INT, STR_ORDER_CONDITIONAL_VALUE_CAPT, 5, this, CS_NUMERAL, QSF_NONE); break; @@ -1337,7 +1337,7 @@ public: switch (this->vehicle->GetOrder(sel)->GetConditionVariable()) { case OCV_MAX_SPEED: - value = ConvertDisplaySpeedToSpeed(value); + value = ConvertDisplaySpeedToSpeed(value, this->vehicle->type); break; case OCV_RELIABILITY: diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index f8bc5360aa..8532a04bd7 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -493,7 +493,7 @@ struct BuildRailToolbarWindow : Window { if (rti->max_speed > 0) { SetDParam(0, STR_TOOLBAR_RAILTYPE_VELOCITY); SetDParam(1, rti->strings.toolbar_caption); - SetDParam(2, rti->max_speed); + SetDParam(2, PackVelocity(rti->max_speed, VEH_TRAIN)); } else { SetDParam(0, rti->strings.toolbar_caption); } diff --git a/src/road_gui.cpp b/src/road_gui.cpp index 0c9ee9d298..ed5c0dc36f 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -411,7 +411,7 @@ struct BuildRoadToolbarWindow : Window { if (this->rti->max_speed > 0) { SetDParam(0, STR_TOOLBAR_RAILTYPE_VELOCITY); SetDParam(1, this->rti->strings.toolbar_caption); - SetDParam(2, this->rti->max_speed / 2); + SetDParam(2, PackVelocity(this->rti->max_speed / 2, VEH_ROAD)); } else { SetDParam(0, this->rti->strings.toolbar_caption); } diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index f1c0a4d2fd..fe696647a1 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -2877,6 +2877,11 @@ bool AfterLoadGame() _settings_game.locale.units_height = Clamp(_old_units, 0, 2); } + if (IsSavegameVersionBefore(SLV_VELOCITY_NAUTICAL)) { + /* Match nautical velocity with land velocity units. */ + _settings_game.locale.units_velocity_nautical = _settings_game.locale.units_velocity; + } + if (IsSavegameVersionBefore(SLV_186)) { /* Move ObjectType from map to pool */ for (auto t : Map::Iterate()) { diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 48bfa59be4..a8bb671517 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -347,6 +347,8 @@ enum SaveLoadVersion : uint16 { SLV_NEWGRF_ROAD_STOPS, ///< 303 PR#10144 NewGRF road stops. SLV_LINKGRAPH_EDGES, ///< 304 PR#10314 Explicitly store link graph edges destination, PR#10471 int64 instead of uint64 league rating + SLV_VELOCITY_NAUTICAL, ///< 305 PR#10594 Separation of land and nautical velocity (knots!) + SL_MAX_VERSION, ///< Highest possible saveload version }; diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 5d14637e64..36318d0a94 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1600,6 +1600,7 @@ static SettingsContainer &GetSettingsTree() SettingsPage *localisation = main->Add(new SettingsPage(STR_CONFIG_SETTING_LOCALISATION)); { localisation->Add(new SettingEntry("locale.units_velocity")); + localisation->Add(new SettingEntry("locale.units_velocity_nautical")); localisation->Add(new SettingEntry("locale.units_power")); localisation->Add(new SettingEntry("locale.units_weight")); localisation->Add(new SettingEntry("locale.units_volume")); diff --git a/src/settings_type.h b/src/settings_type.h index 2a33d3be0e..4b9bc2f447 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -234,7 +234,8 @@ struct MusicSettings { /** Settings related to currency/unit systems. */ struct LocaleSettings { byte currency; ///< currency we currently use - byte units_velocity; ///< unit system for velocity + byte units_velocity; ///< unit system for velocity of trains and road vehicles + byte units_velocity_nautical; ///< unit system for velocity of ships and aircraft byte units_power; ///< unit system for power byte units_weight; ///< unit system for weight byte units_volume; ///< unit system for volume diff --git a/src/strings.cpp b/src/strings.cpp index bd4fe15cc9..8aa69bacd7 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -703,10 +703,11 @@ struct UnitsLong { /** Unit conversions for velocity. */ static const Units _units_velocity[] = { - { { 1, 0}, STR_UNITS_VELOCITY_IMPERIAL, 0 }, - { { 103, 6}, STR_UNITS_VELOCITY_METRIC, 0 }, - { { 1831, 12}, STR_UNITS_VELOCITY_SI, 0 }, - { {37888, 16}, STR_UNITS_VELOCITY_GAMEUNITS, 1 }, + { { 1, 0}, STR_UNITS_VELOCITY_IMPERIAL, 0 }, + { { 103, 6}, STR_UNITS_VELOCITY_METRIC, 0 }, + { { 1831, 12}, STR_UNITS_VELOCITY_SI, 0 }, + { { 37888, 16}, STR_UNITS_VELOCITY_GAMEUNITS, 1 }, + { { 7289499, 23}, STR_UNITS_VELOCITY_KNOTS, 0 }, }; /** Unit conversions for power. */ @@ -757,17 +758,29 @@ static const Units _units_height[] = { { { 1, 0}, STR_UNITS_HEIGHT_SI, 0 }, }; +/** + * Get index for velocity conversion units for a vehicle type. + * @param type VehicleType to convert velocity for. + * @return Index within velocity conversion units for vehicle type. + */ +static byte GetVelocityUnits(VehicleType type) +{ + if (type == VEH_SHIP || type == VEH_AIRCRAFT) return _settings_game.locale.units_velocity_nautical; + + return _settings_game.locale.units_velocity; +} + /** * Convert the given (internal) speed to the display speed. * @param speed the speed to convert * @return the converted speed. */ -uint ConvertSpeedToDisplaySpeed(uint speed) +uint ConvertSpeedToDisplaySpeed(uint speed, VehicleType type) { /* For historical reasons we don't want to mess with the * conversion for speed. So, don't round it and keep the * original conversion factors instead of the real ones. */ - return _units_velocity[_settings_game.locale.units_velocity].c.ToDisplay(speed, false); + return _units_velocity[GetVelocityUnits(type)].c.ToDisplay(speed, false); } /** @@ -775,9 +788,9 @@ uint ConvertSpeedToDisplaySpeed(uint speed) * @param speed the speed to convert * @return the converted speed. */ -uint ConvertDisplaySpeedToSpeed(uint speed) +uint ConvertDisplaySpeedToSpeed(uint speed, VehicleType type) { - return _units_velocity[_settings_game.locale.units_velocity].c.FromDisplay(speed); + return _units_velocity[GetVelocityUnits(type)].c.FromDisplay(speed); } /** @@ -785,9 +798,9 @@ uint ConvertDisplaySpeedToSpeed(uint speed) * @param speed the speed to convert * @return the converted speed. */ -uint ConvertKmhishSpeedToDisplaySpeed(uint speed) +uint ConvertKmhishSpeedToDisplaySpeed(uint speed, VehicleType type) { - return _units_velocity[_settings_game.locale.units_velocity].c.ToDisplay(speed * 10, false) / 16; + return _units_velocity[GetVelocityUnits(type)].c.ToDisplay(speed * 10, false) / 16; } /** @@ -795,9 +808,9 @@ uint ConvertKmhishSpeedToDisplaySpeed(uint speed) * @param speed the speed to convert * @return the converted speed. */ -uint ConvertDisplaySpeedToKmhishSpeed(uint speed) +uint ConvertDisplaySpeedToKmhishSpeed(uint speed, VehicleType type) { - return _units_velocity[_settings_game.locale.units_velocity].c.FromDisplay(speed * 16, true, 10); + return _units_velocity[GetVelocityUnits(type)].c.FromDisplay(speed * 16, true, 10); } static std::vector _game_script_raw_strings; @@ -1291,11 +1304,15 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg } case SCC_VELOCITY: { // {VELOCITY} - assert(_settings_game.locale.units_velocity < lengthof(_units_velocity)); - unsigned int decimal_places = _units_velocity[_settings_game.locale.units_velocity].decimal_places; - uint64 args_array[] = {ConvertKmhishSpeedToDisplaySpeed(args->GetInt64(SCC_VELOCITY)), decimal_places}; + int64 arg = args->GetInt64(SCC_VELOCITY); + // Unpack vehicle type from packed argument to get desired units. + VehicleType vt = static_cast(GB(arg, 56, 8)); + byte units = GetVelocityUnits(vt); + assert(units < lengthof(_units_velocity)); + unsigned int decimal_places = _units_velocity[units].decimal_places; + uint64 args_array[] = {ConvertKmhishSpeedToDisplaySpeed(GB(arg, 0, 56), vt), decimal_places}; StringParameters tmp_params(args_array, decimal_places ? 2 : 1, nullptr); - buff = FormatString(buff, GetStringPtr(_units_velocity[_settings_game.locale.units_velocity].s), &tmp_params, last); + buff = FormatString(buff, GetStringPtr(_units_velocity[units].s), &tmp_params, last); break; } diff --git a/src/strings_func.h b/src/strings_func.h index bdb4fc6cd6..760931d1a9 100644 --- a/src/strings_func.h +++ b/src/strings_func.h @@ -14,6 +14,7 @@ #include "string_type.h" #include "gfx_type.h" #include "core/bitmath_func.hpp" +#include "vehicle_type.h" /** * Extract the StringTab from a StringID. @@ -174,8 +175,21 @@ std::string GetString(StringID string); char *GetStringWithArgs(char *buffr, StringID string, StringParameters *args, const char *last, uint case_index = 0, bool game_script = false); const char *GetStringPtr(StringID string); -uint ConvertKmhishSpeedToDisplaySpeed(uint speed); -uint ConvertDisplaySpeedToKmhishSpeed(uint speed); +uint ConvertKmhishSpeedToDisplaySpeed(uint speed, VehicleType type); +uint ConvertDisplaySpeedToKmhishSpeed(uint speed, VehicleType type); + +/** + * Pack velocity and vehicle type for use with SCC_VELOCITY string parameter. + * @param speed Display speed for parameter. + * @param type Type of vehicle for parameter. + * @return Bit-packed velocity and vehicle type, for use with SetDParam(). + */ +static inline int64 PackVelocity(uint speed, VehicleType type) +{ + /* Vehicle type is a byte, so packed into the top 8 bits of the 64-bit + * parameter, although only values from 0-3 are relevant. */ + return speed | (static_cast(type) << 56); +} /** * Set a string parameter \a v at index \a n in a given array \a s. diff --git a/src/table/settings/locale_settings.ini b/src/table/settings/locale_settings.ini index da501755b7..33dd1eae1d 100644 --- a/src/table/settings/locale_settings.ini +++ b/src/table/settings/locale_settings.ini @@ -73,7 +73,7 @@ type = SLE_UINT8 from = SLV_184 flags = SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN def = 1 -max = 3 +max = 4 full = _locale_units post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC @@ -81,6 +81,20 @@ str = STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY strhelp = STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT strval = STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_IMPERIAL +[SDT_OMANY] +var = locale.units_velocity_nautical +type = SLE_UINT8 +from = SLV_VELOCITY_NAUTICAL +flags = SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN +def = 1 +max = 4 +full = _locale_units +post_cb = [](auto) { MarkWholeScreenDirty(); } +cat = SC_BASIC +str = STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_NAUTICAL +strhelp = STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT +strval = STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_IMPERIAL + [SDT_OMANY] var = locale.units_power type = SLE_UINT8 diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp index 8e0252a333..bb1efed006 100644 --- a/src/timetable_gui.cpp +++ b/src/timetable_gui.cpp @@ -408,7 +408,7 @@ struct TimetableWindow : Window { string = order->GetMaxSpeed() != UINT16_MAX ? STR_TIMETABLE_TRAVEL_FOR_SPEED : STR_TIMETABLE_TRAVEL_FOR; } - SetDParam(2, order->GetMaxSpeed()); + SetDParam(2, PackVelocity(order->GetMaxSpeed(), v->type)); DrawString(rtl ? tr.left : middle, rtl ? middle : tr.right, tr.top, string, colour); @@ -568,7 +568,7 @@ struct TimetableWindow : Window { const Order *order = v->GetOrder(real); if (order != nullptr) { if (order->GetMaxSpeed() != UINT16_MAX) { - SetDParam(0, ConvertKmhishSpeedToDisplaySpeed(order->GetMaxSpeed())); + SetDParam(0, ConvertKmhishSpeedToDisplaySpeed(order->GetMaxSpeed(), v->type)); current = STR_JUST_INT; } } @@ -628,7 +628,7 @@ struct TimetableWindow : Window { uint64 val = StrEmpty(str) ? 0 : strtoul(str, nullptr, 10); if (this->query_is_speed_query) { - val = ConvertDisplaySpeedToKmhishSpeed(val); + val = ConvertDisplaySpeedToKmhishSpeed(val, v->type); } else { if (!_settings_client.gui.timetable_in_ticks) val *= DAY_TICKS; } diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index dadb726d21..21cdc20359 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -2493,7 +2493,7 @@ struct VehicleDetailsWindow : Window { if (v->type == VEH_TRAIN || (v->type == VEH_ROAD && _settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL)) { const GroundVehicleCache *gcache = v->GetGroundVehicleCache(); - SetDParam(2, v->GetDisplayMaxSpeed()); + SetDParam(2, PackVelocity(v->GetDisplayMaxSpeed(), v->type)); SetDParam(1, gcache->cached_power); SetDParam(0, gcache->cached_weight); SetDParam(3, gcache->cached_max_te / 1000); @@ -2504,7 +2504,7 @@ struct VehicleDetailsWindow : Window { string = STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE; } } else { - SetDParam(0, v->GetDisplayMaxSpeed()); + SetDParam(0, PackVelocity(v->GetDisplayMaxSpeed(), v->type)); if (v->type == VEH_AIRCRAFT) { SetDParam(1, v->GetEngine()->GetAircraftTypeText()); if (Aircraft::From(v)->GetRange() > 0) { @@ -2999,7 +2999,7 @@ public: str = STR_VEHICLE_STATUS_STOPPED; } } else { - SetDParam(0, v->GetDisplaySpeed()); + SetDParam(0, PackVelocity(v->GetDisplaySpeed(), v->type)); str = STR_VEHICLE_STATUS_TRAIN_STOPPING_VEL; } } else { // no train @@ -3020,7 +3020,7 @@ public: switch (v->current_order.GetType()) { case OT_GOTO_STATION: { SetDParam(0, v->current_order.GetDestination()); - SetDParam(1, v->GetDisplaySpeed()); + SetDParam(1, PackVelocity(v->GetDisplaySpeed(), v->type)); str = HasBit(v->vehicle_flags, VF_PATHFINDER_LOST) ? STR_VEHICLE_STATUS_CANNOT_REACH_STATION_VEL : STR_VEHICLE_STATUS_HEADING_FOR_STATION_VEL; break; } @@ -3028,7 +3028,7 @@ public: case OT_GOTO_DEPOT: { SetDParam(0, v->type); SetDParam(1, v->current_order.GetDestination()); - SetDParam(2, v->GetDisplaySpeed()); + SetDParam(2, PackVelocity(v->GetDisplaySpeed(), v->type)); if (v->current_order.GetDestination() == INVALID_DEPOT) { /* This case *only* happens when multiple nearest depot orders * follow each other (including an order list only one order: a @@ -3053,7 +3053,7 @@ public: assert(v->type == VEH_TRAIN || v->type == VEH_SHIP); SetDParam(0, v->current_order.GetDestination()); str = HasBit(v->vehicle_flags, VF_PATHFINDER_LOST) ? STR_VEHICLE_STATUS_CANNOT_REACH_WAYPOINT_VEL : STR_VEHICLE_STATUS_HEADING_FOR_WAYPOINT_VEL; - SetDParam(1, v->GetDisplaySpeed()); + SetDParam(1, PackVelocity(v->GetDisplaySpeed(), v->type)); break; } @@ -3066,7 +3066,7 @@ public: default: if (v->GetNumManualOrders() == 0) { str = STR_VEHICLE_STATUS_NO_ORDERS_VEL; - SetDParam(0, v->GetDisplaySpeed()); + SetDParam(0, PackVelocity(v->GetDisplaySpeed(), v->type)); } else { str = STR_EMPTY; }