diff --git a/src/command.cpp b/src/command.cpp index 644b8ccfa0..34b99d7cd0 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -246,6 +246,7 @@ CommandProc CmdAutoreplaceVehicle; CommandProc CmdTemplateReplaceVehicle; CommandProc CmdDepotSellAllVehicles; CommandProc CmdDepotMassAutoReplace; +CommandProc CmdSetTrainSpeedRestriction; CommandProc CmdCreateGroup; CommandProc CmdAlterGroup; @@ -515,6 +516,7 @@ static const Command _command_proc_table[] = { DEF_CMD(CmdTemplateReplaceVehicle, CMD_NO_TEST, CMDT_VEHICLE_MANAGEMENT ), // CMD_TEMPLATE_REPLACE_VEHICLE DEF_CMD(CmdDepotSellAllVehicles, 0, CMDT_VEHICLE_CONSTRUCTION ), // CMD_DEPOT_SELL_ALL_VEHICLES DEF_CMD(CmdDepotMassAutoReplace, CMD_NO_TEST, CMDT_VEHICLE_CONSTRUCTION ), // CMD_DEPOT_MASS_AUTOREPLACE + DEF_CMD(CmdSetTrainSpeedRestriction, 0, CMDT_VEHICLE_MANAGEMENT ), // CMD_SET_TRAIN_SPEED_RESTRICTION DEF_CMD(CmdCreateGroup, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_CREATE_GROUP DEF_CMD(CmdDeleteGroup, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_DELETE_GROUP DEF_CMD(CmdAlterGroup, 0, CMDT_OTHER_MANAGEMENT ), // CMD_ALTER_GROUP diff --git a/src/command_type.h b/src/command_type.h index 2ab0228e55..d2f55fa081 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -462,6 +462,7 @@ enum Commands { CMD_TEMPLATE_REPLACE_VEHICLE, ///< template replace a vehicle while it is in a depot CMD_DEPOT_SELL_ALL_VEHICLES, ///< sell all vehicles which are in a given depot CMD_DEPOT_MASS_AUTOREPLACE, ///< force the autoreplace to take action in a given depot + CMD_SET_TRAIN_SPEED_RESTRICTION, ///< manually set train speed restriction CMD_CREATE_GROUP, ///< create a new group CMD_DELETE_GROUP, ///< delete a group diff --git a/src/lang/extra/english.txt b/src/lang/extra/english.txt index 26127ba51b..46da7875bc 100644 --- a/src/lang/extra/english.txt +++ b/src/lang/extra/english.txt @@ -1619,6 +1619,10 @@ STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE_AND_SPEED :{LTBLUE}{ENGINE STR_VEHICLE_DETAILS_TRAIN_TOTAL_WEIGHT :{BLACK}Total weight: {LTBLUE}{WEIGHT_SHORT} {BLACK}(empty) - {LTBLUE}{WEIGHT_SHORT} {BLACK}(loaded) STR_VEHICLE_DETAILS_TRAIN_MAX_SPEED :{BLACK}Max. speed: {LTBLUE}{VELOCITY} {BLACK}(empty) - {LTBLUE}{VELOCITY} {BLACK}(loaded) +STR_VEHICLE_DETAILS_EXTRA_ACTIONS_TOOLTIP :{BLACK}Extra vehicle actions +STR_VEHICLE_DETAILS_REMOVE_SPEED_RESTRICTION :Remove speed restriction +STR_VEHICLE_DETAILS_SET_SPEED_RESTRICTION :Set speed restriction + STR_ORDER_DROP_CARGO_TYPE_LOAD :Load by cargo type STR_ORDER_DROP_CARGO_TYPE_UNLOAD :Unload by cargo type @@ -2312,3 +2316,5 @@ STR_VIEWPORT_TOWN_COLOUR_CITY_POP :{WHITE}{TOWN} { STR_ABOUT_MENU_SHOW_PICKER_TOOL :Picker tool STR_ABOUT_MENU_SHOW_TOGGLE_MODIFIER_KEYS :Modifier key window + +STR_ERROR_CAN_T_CHANGE_SPEED_RESTRICTION :{WHITE}Can't change vehicle's speed restriction... diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 3c6c15de2b..5d2a3e8417 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -7733,3 +7733,35 @@ uint16_t Train::GetMaxWeight() const return weight; } + +/** + * Set train speed restriction + * @param tile unused + * @param flags type of operation + * @param p1 vehicle + * @param p2 new speed restriction value + * @param text unused + * @return the cost of this operation or an error + */ +CommandCost CmdSetTrainSpeedRestriction(TileIndex tile, DoCommandFlag flags, uint32_t p1, uint32_t p2, const char *text) +{ + Vehicle *v = Vehicle::GetIfValid(p1); + if (v == nullptr || v->type != VEH_TRAIN || !v->IsPrimaryVehicle()) return CMD_ERROR; + + CommandCost ret = CheckVehicleControlAllowed(v); + if (ret.Failed()) return ret; + + if (v->vehstatus & VS_CRASHED) return_cmd_error(STR_ERROR_VEHICLE_IS_DESTROYED); + + if (flags & DC_EXEC) { + Train *t = Train::From(v); + if (HasBit(t->flags, VRF_PENDING_SPEED_RESTRICTION)) { + _pending_speed_restriction_change_map.erase(t->index); + ClrBit(t->flags, VRF_PENDING_SPEED_RESTRICTION); + } + t->speed_restriction = (uint16_t)p2; + + SetWindowDirty(WC_VEHICLE_DETAILS, t->index); + } + return CommandCost(); +} diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 52a00bf438..1b0aa03f3e 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -2757,6 +2757,7 @@ static_assert(WID_VD_DETAILS_TOTAL_CARGO == WID_VD_DETAILS_CARGO_CARRIED + static constexpr NWidgetPart _nested_nontrain_vehicle_details_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), + NWidget(WWT_IMGBTN, COLOUR_GREY, WID_VD_EXTRA_ACTIONS), SetDataTip(SPR_ARROW_DOWN, STR_VEHICLE_DETAILS_EXTRA_ACTIONS_TOOLTIP), NWidget(WWT_CAPTION, COLOUR_GREY, WID_VD_CAPTION), SetDataTip(STR_VEHICLE_DETAILS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), @@ -2780,6 +2781,7 @@ static constexpr NWidgetPart _nested_nontrain_vehicle_details_widgets[] = { static constexpr NWidgetPart _nested_train_vehicle_details_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), + NWidget(WWT_IMGBTN, COLOUR_GREY, WID_VD_EXTRA_ACTIONS), SetDataTip(SPR_ARROW_DOWN, STR_VEHICLE_DETAILS_EXTRA_ACTIONS_TOOLTIP), NWidget(WWT_CAPTION, COLOUR_GREY, WID_VD_CAPTION), SetDataTip(STR_VEHICLE_DETAILS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), @@ -2843,6 +2845,11 @@ struct VehicleDetailsWindow : Window { bool vehicle_speed_restriction_line_shown; bool vehicle_speed_adaptation_exempt_line_shown; + enum DropDownAction { + VDWDDA_CLEAR_SPEED_RESTRICTION, + VDWDDA_SET_SPEED_RESTRICTION, + }; + /** Initialize a newly created vehicle details window */ VehicleDetailsWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc) { @@ -3331,6 +3338,8 @@ struct VehicleDetailsWindow : Window { WID_VD_INCREASE_SERVICING_INTERVAL, WID_VD_DECREASE_SERVICING_INTERVAL); + this->SetWidgetDisabledState(WID_VD_EXTRA_ACTIONS, v->type != VEH_TRAIN); + StringID str = !v->ServiceIntervalIsCustom() ? STR_VEHICLE_DETAILS_DEFAULT : v->ServiceIntervalIsPercent() ? STR_VEHICLE_DETAILS_PERCENT : @@ -3382,6 +3391,18 @@ struct VehicleDetailsWindow : Window { this->tab = (TrainDetailsWindowTabs)(widget - WID_VD_DETAILS_CARGO_CARRIED); this->SetDirty(); break; + + case WID_VD_EXTRA_ACTIONS: { + const Vehicle *v = Vehicle::Get(this->window_number); + DropDownList list; + if (v->type == VEH_TRAIN) { + bool change_allowed = IsVehicleControlAllowed(v, _local_company); + list.emplace_back(new DropDownListStringItem(STR_VEHICLE_DETAILS_REMOVE_SPEED_RESTRICTION, VDWDDA_CLEAR_SPEED_RESTRICTION, !change_allowed || Train::From(v)->speed_restriction == 0)); + list.emplace_back(new DropDownListStringItem(STR_VEHICLE_DETAILS_SET_SPEED_RESTRICTION, VDWDDA_SET_SPEED_RESTRICTION, !change_allowed)); + } + ShowDropDownList(this, std::move(list), -1, WID_VD_EXTRA_ACTIONS, 140); + break; + } } } @@ -3415,9 +3436,32 @@ struct VehicleDetailsWindow : Window { DoCommandP(v->tile, v->index, interval | (iscustom << 16) | (ispercent << 17), CMD_CHANGE_SERVICE_INT | CMD_MSG(STR_ERROR_CAN_T_CHANGE_SERVICING)); break; } + + case WID_VD_EXTRA_ACTIONS: { + const Vehicle *v = Vehicle::Get(this->window_number); + switch (index) { + case VDWDDA_CLEAR_SPEED_RESTRICTION: + DoCommandP(v->tile, v->index, 0, CMD_SET_TRAIN_SPEED_RESTRICTION | CMD_MSG(STR_ERROR_CAN_T_CHANGE_SPEED_RESTRICTION)); + break; + + case VDWDDA_SET_SPEED_RESTRICTION: { + SetDParam(0, ConvertKmhishSpeedToDisplaySpeed(Train::From(v)->speed_restriction, VEH_TRAIN)); + ShowQueryString(STR_JUST_INT, STR_TIMETABLE_CHANGE_SPEED, 10, this, CS_NUMERAL, QSF_NONE); + } + } + break; + } } } + void OnQueryTextFinished(char *str) override + { + if (str == nullptr || StrEmpty(str)) return; + + const Vehicle *v = Vehicle::Get(this->window_number); + DoCommandP(v->tile, v->index, ConvertDisplaySpeedToKmhishSpeed(std::strtoul(str, nullptr, 10), VEH_TRAIN), CMD_SET_TRAIN_SPEED_RESTRICTION | CMD_MSG(STR_ERROR_CAN_T_CHANGE_SPEED_RESTRICTION)); + } + void OnResize() override { NWidgetCore *nwi = this->GetWidget(WID_VD_MATRIX); diff --git a/src/widgets/vehicle_widget.h b/src/widgets/vehicle_widget.h index 5b45ed190c..35b1441435 100644 --- a/src/widgets/vehicle_widget.h +++ b/src/widgets/vehicle_widget.h @@ -59,6 +59,7 @@ enum VehicleDetailsWidgets : WidgetID { WID_VD_DETAILS_TRAIN_VEHICLES, ///< Show all parts of the train with their description. WID_VD_DETAILS_CAPACITY_OF_EACH, ///< Show the capacity of all train parts. WID_VD_DETAILS_TOTAL_CARGO, ///< Show the capacity and carried cargo amounts aggregated per cargo of the train. + WID_VD_EXTRA_ACTIONS, ///< Extra actions drop-down. }; /** Widgets of the #VehicleListWindow class. */