diff --git a/src/group_gui.cpp b/src/group_gui.cpp index e27fa4fb43..e59781e5cc 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -963,6 +963,9 @@ public: DoCommandP(0, DEPOT_MASS_SEND | (index == ADI_SERVICE ? DEPOT_SERVICE : 0U), this->vli.Pack(), GetCmdSendToDepot(this->vli.vtype)); break; } + case ADI_DEPOT_SELL: + DoCommandP(0, DEPOT_MASS_SEND | DEPOT_SELL, this->vli.Pack(), GetCmdSendToDepot(this->vli.vtype)); + break; case ADI_CANCEL_DEPOT: DoCommandP(0, DEPOT_MASS_SEND | DEPOT_CANCEL, this->vli.Pack(), GetCmdSendToDepot(this->vli.vtype)); break; diff --git a/src/lang/english.txt b/src/lang/english.txt index e450f7d1d2..08197be86d 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1327,6 +1327,8 @@ STR_CONFIG_SETTING_SHOW_ADV_LOADING_MODE_FEATURES :Show advanced l STR_CONFIG_SETTING_SHOW_ADV_LOADING_MODE_FEATURES_HELPTEXT :Show advanced loading mode features (through load/unload). When disabled, some advanced loading mode features are not shown in the UI, but are still available to all players. STR_CONFIG_SETTING_DISABLE_TOP_VEH_LIST_MASS_ACTIONS :Disable mass action buttons for top-level vehicle lists STR_CONFIG_SETTING_DISABLE_TOP_VEH_LIST_MASS_ACTIONS_HELPTEXT :This disables depot/service and start/stop buttons for all vehicle and all ungrouped vehicle lists. This is intended to help avoid the negative impact of accidentally pressing one of these buttons. +STR_CONFIG_SETTING_SHOW_DEPOT_SELL_GUI :Show go to depot/hangar and sell feature: {STRING2} +STR_CONFIG_SETTING_SHOW_DEPOT_SELL_GUI_HELPTEXT :Show go to depot/hangar and sell vehicle on arrival feature. When enabled, the behaviour of the vehicle go to depot button is changed. STR_CONFIG_SETTING_ADV_SIG_BRIDGE_TUN_MODES :Enable signals on bridges/tunnels advanced modes: {STRING2} STR_CONFIG_SETTING_ADV_SIG_BRIDGE_TUN_MODES_HELPTEXT :Enables use of advanced modes of signal simulation on bridges and tunnels. When disabled, bridges/tunnels which are not already in an advanced mode cannot be changed to an advanced mode, however other players may choose to enable this setting and use an advanced mode. @@ -3935,6 +3937,11 @@ STR_VEHICLE_LIST_SEND_ROAD_VEHICLE_TO_DEPOT :Send to Depot STR_VEHICLE_LIST_SEND_SHIP_TO_DEPOT :Send to Depot STR_VEHICLE_LIST_SEND_AIRCRAFT_TO_HANGAR :Send to Hangar +STR_VEHICLE_LIST_SEND_TRAIN_TO_DEPOT_SELL :Send to Depot and sell +STR_VEHICLE_LIST_SEND_ROAD_VEHICLE_TO_DEPOT_SELL :Send to Depot and sell +STR_VEHICLE_LIST_SEND_SHIP_TO_DEPOT_SELL :Send to Depot and sell +STR_VEHICLE_LIST_SEND_AIRCRAFT_TO_HANGAR_SELL :Send to Hangar and sell + STR_VEHICLE_LIST_MASS_STOP_LIST_TOOLTIP :{BLACK}Click to stop all the vehicles in the list STR_VEHICLE_LIST_MASS_START_LIST_TOOLTIP :{BLACK}Click to start all the vehicles in the list @@ -4215,6 +4222,7 @@ STR_VEHICLE_VIEW_SHIP_SEND_TO_DEPOT_TOOLTIP :{BLACK}Send shi STR_VEHICLE_VIEW_AIRCRAFT_SEND_TO_DEPOT_TOOLTIP :{BLACK}Send aircraft to hangar. Ctrl+Click will only service STR_VEHICLE_VIEW_SEND_TO_DEPOT_TOOLTIP_SHIFT :{STRING}. Shift+Click to select which +STR_VEHICLE_VIEW_SEND_TO_DEPOT_MENU :{BLACK}Cancel send vehicle to depot/hangar. Ctrl+Click for menu. Shift+Click to select depot/hangar STR_VEHICLE_VIEW_CLONE_TRAIN_INFO :{BLACK}This will buy a copy of the train including all cars. Ctrl+Click will share the orders. Shift+Click shows estimated cost without purchase STR_VEHICLE_VIEW_CLONE_ROAD_VEHICLE_INFO :{BLACK}This will buy a copy of the road vehicle. Ctrl+Click will share the orders. Shift+Click shows estimated cost without purchase @@ -4274,6 +4282,7 @@ STR_VEHICLE_STATUS_HEADING_FOR_STATION_VEL :{LTBLUE}Heading STR_VEHICLE_STATUS_NO_ORDERS_VEL :{LTBLUE}No orders, {VELOCITY} STR_VEHICLE_STATUS_HEADING_FOR_WAYPOINT_VEL :{LTBLUE}Heading for {WAYPOINT}, {VELOCITY} STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_VEL :{ORANGE}Heading for {DEPOT}, {VELOCITY} +STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SELL_VEL :{CREAM}Heading for {PUSH_COLOUR}{RED}sale{POP_COLOUR} at {DEPOT}, {VELOCITY} STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SERVICE_VEL :{LTBLUE}Service at {DEPOT}, {VELOCITY} # Vehicle stopped/started animations @@ -4441,6 +4450,7 @@ STR_ORDER_SERVICE :{BLACK}Service STR_ORDER_DROP_GO_ALWAYS_DEPOT :Always go STR_ORDER_DROP_SERVICE_DEPOT :Service if needed STR_ORDER_DROP_HALT_DEPOT :Stop +STR_ORDER_DROP_SELL_DEPOT :Sell vehicle STR_ORDER_SERVICE_TOOLTIP :{BLACK}Skip this order unless a service is needed STR_ORDER_CONDITIONAL_VARIABLE_TOOLTIP :{BLACK}Vehicle data to base jumping on @@ -4538,6 +4548,7 @@ STR_ORDER_GO_TO_DEPOT_FORMAT :{STRING} {DEPOT STR_ORDER_REFIT_ORDER :(Refit to {STRING}) STR_ORDER_REFIT_STOP_ORDER :(Refit to {STRING} and stop) STR_ORDER_STOP_ORDER :(Stop) +STR_ORDER_SELL_ORDER :(Sell vehicle) STR_ORDER_GO_TO_STATION :{STRING} {STATION} {STRING1} diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index e731fa895b..1cb902e248 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -960,7 +960,7 @@ CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && !v->IsGroundVehicle()) return CMD_ERROR; if (new_order.GetDepotOrderType() & ~(ODTFB_PART_OF_ORDERS | ((new_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0 ? ODTFB_SERVICE : 0))) return CMD_ERROR; - if (new_order.GetDepotActionType() & ~(ODATFB_HALT | ODATFB_NEAREST_DEPOT)) return CMD_ERROR; + if (new_order.GetDepotActionType() & ~(ODATFB_HALT | ODATFB_SELL | ODATFB_NEAREST_DEPOT)) return CMD_ERROR; if ((new_order.GetDepotOrderType() & ODTFB_SERVICE) && (new_order.GetDepotActionType() & ODATFB_HALT)) return CMD_ERROR; break; } @@ -1671,21 +1671,28 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 break; case MOF_DEPOT_ACTION: { + OrderDepotActionFlags base_order_action_type = order->GetDepotActionType() & ~(ODATFB_HALT | ODATFB_SELL); switch (data) { case DA_ALWAYS_GO: order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() & ~ODTFB_SERVICE)); - order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() & ~ODATFB_HALT)); + order->SetDepotActionType((OrderDepotActionFlags)(base_order_action_type)); break; case DA_SERVICE: order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() | ODTFB_SERVICE)); - order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() & ~ODATFB_HALT)); + order->SetDepotActionType((OrderDepotActionFlags)(base_order_action_type)); order->SetRefit(CT_NO_REFIT); break; case DA_STOP: order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() & ~ODTFB_SERVICE)); - order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() | ODATFB_HALT)); + order->SetDepotActionType((OrderDepotActionFlags)(base_order_action_type | ODATFB_HALT)); + order->SetRefit(CT_NO_REFIT); + break; + + case DA_SELL: + order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() & ~ODTFB_SERVICE)); + order->SetDepotActionType((OrderDepotActionFlags)(base_order_action_type | ODATFB_HALT | ODATFB_SELL)); order->SetRefit(CT_NO_REFIT); break; @@ -2095,7 +2102,7 @@ CommandCost CmdOrderRefit(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 /* Make the depot order an 'always go' order. */ if (cargo != CT_NO_REFIT && order->IsType(OT_GOTO_DEPOT)) { order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() & ~ODTFB_SERVICE)); - order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() & ~ODATFB_HALT)); + order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() & ~(ODATFB_HALT | ODATFB_SELL))); } for (Vehicle *u = v->FirstShared(); u != NULL; u = u->NextShared()) { diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 2d0dbdfba5..d98556a7cc 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -665,12 +665,15 @@ static const StringID _order_depot_action_dropdown[] = { STR_ORDER_DROP_GO_ALWAYS_DEPOT, STR_ORDER_DROP_SERVICE_DEPOT, STR_ORDER_DROP_HALT_DEPOT, + STR_ORDER_DROP_SELL_DEPOT, INVALID_STRING_ID }; static int DepotActionStringIndex(const Order *order) { - if (order->GetDepotActionType() & ODATFB_HALT) { + if (order->GetDepotActionType() & ODATFB_SELL) { + return DA_SELL; + } else if (order->GetDepotActionType() & ODATFB_HALT) { return DA_STOP; } else if (order->GetDepotOrderType() & ODTFB_SERVICE) { return DA_SERVICE; @@ -791,13 +794,17 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int SetDParam(1, (order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_ORDER_GO_NON_STOP_TO : STR_ORDER_GO_TO); } - if (!timetable && (order->GetDepotActionType() & ODATFB_HALT)) { - SetDParam(5, STR_ORDER_STOP_ORDER); - } + if (!timetable && (order->GetDepotActionType() & ODATFB_SELL)) { + SetDParam(5, STR_ORDER_SELL_ORDER); + } else { + if (!timetable && (order->GetDepotActionType() & ODATFB_HALT)) { + SetDParam(5, STR_ORDER_STOP_ORDER); + } - if (!timetable && order->IsRefit()) { - SetDParam(5, (order->GetDepotActionType() & ODATFB_HALT) ? STR_ORDER_REFIT_STOP_ORDER : STR_ORDER_REFIT_ORDER); - SetDParam(6, CargoSpec::Get(order->GetRefitCargo())->name); + if (!timetable && order->IsRefit()) { + SetDParam(5, (order->GetDepotActionType() & ODATFB_HALT) ? STR_ORDER_REFIT_STOP_ORDER : STR_ORDER_REFIT_ORDER); + SetDParam(6, CargoSpec::Get(order->GetRefitCargo())->name); + } } if (timetable) { @@ -1993,7 +2000,8 @@ public: if (this->GetWidget(widget)->ButtonHit(pt)) { this->OrderClick_Service(-1); } else { - ShowDropDownMenu(this, _order_depot_action_dropdown, DepotActionStringIndex(this->vehicle->GetOrder(this->OrderGetSel())), WID_O_SERVICE, 0, 0, 0, DDSF_LOST_FOCUS); + ShowDropDownMenu(this, _order_depot_action_dropdown, DepotActionStringIndex(this->vehicle->GetOrder(this->OrderGetSel())), + WID_O_SERVICE, 0, _settings_client.gui.show_depot_sell_gui ? 0 : (1 << DA_SELL), 0, DDSF_LOST_FOCUS); } break; diff --git a/src/order_type.h b/src/order_type.h index ffc4b247b2..1ed6712e18 100644 --- a/src/order_type.h +++ b/src/order_type.h @@ -117,6 +117,7 @@ enum OrderDepotActionFlags { ODATF_SERVICE_ONLY = 0, ///< Only service the vehicle. ODATFB_HALT = 1 << 0, ///< Service the vehicle and then halt it. ODATFB_NEAREST_DEPOT = 1 << 1, ///< Send the vehicle to the nearest depot. + ODATFB_SELL = 1 << 2, ///< Sell the vehicle on arrival at the depot. }; DECLARE_ENUM_AS_BIT_SET(OrderDepotActionFlags) @@ -191,6 +192,7 @@ enum OrderDepotAction { DA_ALWAYS_GO, ///< Always go to the depot DA_SERVICE, ///< Service only if needed DA_STOP, ///< Go to the depot and stop there + DA_SELL, ///< Go to the depot and sell vehicle DA_END }; diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index 50fe4fae63..5345389bb6 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -86,6 +86,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_ORDER_EXTRA_DATA, XSCF_NULL, 1, 1, "order_extra_data", NULL, NULL, NULL }, { XSLFI_WHOLE_MAP_CHUNK, XSCF_NULL, 1, 1, "whole_map_chunk", NULL, NULL, "WMAP" }, { XSLFI_ST_LAST_VEH_TYPE, XSCF_NULL, 1, 1, "station_last_veh_type", NULL, NULL, NULL }, + { XSLFI_SELL_AT_DEPOT_ORDER, XSCF_NULL, 1, 1, "sell_at_depot_order", NULL, NULL, NULL }, { XSLFI_NULL, XSCF_NULL, 0, 0, NULL, NULL, NULL, NULL },// This is the end marker }; diff --git a/src/saveload/extended_ver_sl.h b/src/saveload/extended_ver_sl.h index f0304442c2..dd550ac700 100644 --- a/src/saveload/extended_ver_sl.h +++ b/src/saveload/extended_ver_sl.h @@ -60,6 +60,7 @@ enum SlXvFeatureIndex { XSLFI_ORDER_EXTRA_DATA, ///< Order extra data field(s) XSLFI_WHOLE_MAP_CHUNK, ///< Whole map chunk XSLFI_ST_LAST_VEH_TYPE, ///< Per-cargo station last vehicle type + XSLFI_SELL_AT_DEPOT_ORDER, ///< Sell vehicle on arrival at depot orders 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 diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 0ba8e2b15e..925a0fe545 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1617,6 +1617,7 @@ static SettingsContainer &GetSettingsTree() interface->Add(new SettingEntry("gui.show_adv_load_mode_features")); interface->Add(new SettingEntry("gui.disable_top_veh_list_mass_actions")); interface->Add(new SettingEntry("gui.adv_sig_bridge_tun_modes")); + interface->Add(new SettingEntry("gui.show_depot_sell_gui")); } SettingsPage *advisors = main->Add(new SettingsPage(STR_CONFIG_SETTING_ADVISORS)); diff --git a/src/settings_type.h b/src/settings_type.h index 1d28f1e227..699ac4e76d 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -191,6 +191,7 @@ struct GUISettings { bool show_adv_load_mode_features; ///< enable advanced loading mode features in UI bool disable_top_veh_list_mass_actions; ///< disable mass actions buttons for non-group vehicle lists bool adv_sig_bridge_tun_modes; ///< Enable advanced modes for signals on bridges/tunnels. + bool show_depot_sell_gui; ///< Show go to depot and sell in UI uint16 console_backlog_timeout; ///< the minimum amount of time items should be in the console backlog before they will be removed in ~3 seconds granularity. uint16 console_backlog_length; ///< the minimum amount of items in the console backlog before items will be removed. diff --git a/src/table/settings.ini b/src/table/settings.ini index 091b5e6e89..430127f5c1 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -4177,6 +4177,14 @@ str = STR_CONFIG_SETTING_ADV_SIG_BRIDGE_TUN_MODES strhelp = STR_CONFIG_SETTING_ADV_SIG_BRIDGE_TUN_MODES_HELPTEXT cat = SC_EXPERT +[SDTC_BOOL] +var = gui.show_depot_sell_gui +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +def = false +str = STR_CONFIG_SETTING_SHOW_DEPOT_SELL_GUI +strhelp = STR_CONFIG_SETTING_SHOW_DEPOT_SELL_GUI_HELPTEXT +cat = SC_EXPERT + ; For the dedicated build we'll enable dates in logs by default. [SDTC_BOOL] ifdef = DEDICATED diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 687ffc356a..107fdd1454 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -101,6 +101,7 @@ VehiclePool _vehicle_pool("Vehicle"); INSTANTIATE_POOL_METHODS(Vehicle) static btree::btree_set _vehicles_to_pay_repair; +static btree::btree_set _vehicles_to_sell; /** * Determine shared bounds of all sprites. @@ -1098,6 +1099,7 @@ void CallVehicleTicks() _vehicles_to_autoreplace.Clear(); _vehicles_to_templatereplace.Clear(); _vehicles_to_pay_repair.clear(); + _vehicles_to_sell.clear(); if (_tick_skip_counter == 0) RunVehicleDayProc(); @@ -1188,6 +1190,34 @@ void CallVehicleTicks() } v = NULL; + /* do Template Replacement */ + Backup sell_cur_company(_current_company, FILE_LINE); + for (Vehicle *v : _vehicles_to_sell) { + SCOPE_INFO_FMT([v], "CallVehicleTicks: sell: %s", scope_dumper().VehicleInfo(v)); + Train *t = (v->type == VEH_TRAIN) ? Train::From(v) : nullptr; + + sell_cur_company.Change(v->owner); + + int x = v->x_pos; + int y = v->y_pos; + int z = v->z_pos; + + CommandCost cost = DoCommand(v->tile, v->index | (1 << 20), 0, DC_EXEC, GetCmdSellVeh(v)); + + if (!cost.Succeeded()) continue; + + if (IsLocalCompany() && cost.Succeeded()) { + if (cost.GetCost() != 0) { + ShowCostOrIncomeAnimation(x, y, z, cost.GetCost()); + } + } + + _vehicles_to_pay_repair.erase(v); + if (t) _vehicles_to_templatereplace.Erase(t); + _vehicles_to_autoreplace.Erase(v); + } + sell_cur_company.Restore(); + /* do Template Replacement */ Backup tmpl_cur_company(_current_company, FILE_LINE); for (TemplateReplacementMap::iterator it = _vehicles_to_templatereplace.Begin(); it != _vehicles_to_templatereplace.End(); it++) { @@ -1995,6 +2025,11 @@ void VehicleEnterDepot(Vehicle *v) return; } + if (v->current_order.GetDepotActionType() & ODATFB_SELL) { + _vehicles_to_sell.insert(v); + return; + } + if (v->current_order.IsRefit()) { Backup cur_company(_current_company, v->owner, FILE_LINE); CommandCost cost = DoCommand(v->tile, v->index, v->current_order.GetRefitCargo() | 0xFF << 8, DC_EXEC, GetCmdRefitVeh(v)); @@ -3001,13 +3036,14 @@ CommandCost Vehicle::SendToDepot(DoCommandFlag flags, DepotCommand command, Tile if (this->current_order.IsType(OT_GOTO_DEPOT) && !(command & DEPOT_SPECIFIC)) { bool halt_in_depot = (this->current_order.GetDepotActionType() & ODATFB_HALT) != 0; - if (!!(command & DEPOT_SERVICE) == halt_in_depot) { - /* We called with a different DEPOT_SERVICE setting. + bool sell_in_depot = (this->current_order.GetDepotActionType() & ODATFB_SELL) != 0; + if (!!(command & DEPOT_SERVICE) == halt_in_depot || !!(command & DEPOT_SELL) != sell_in_depot) { + /* We called with a different DEPOT_SERVICE or DEPOT_SELL setting. * Now we change the setting to apply the new one and let the vehicle head for the same depot. * Note: the if is (true for requesting service == true for ordered to stop in depot) */ if (flags & DC_EXEC) { if (!(this->current_order.GetDepotOrderType() & ODTFB_BREAKDOWN)) this->current_order.SetDepotOrderType(ODTF_MANUAL); - this->current_order.SetDepotActionType(halt_in_depot ? ODATF_SERVICE_ONLY : ODATFB_HALT); + this->current_order.SetDepotActionType((command & DEPOT_SELL) ? ODATFB_HALT | ODATFB_SELL : ((command & DEPOT_SERVICE) ? ODATF_SERVICE_ONLY : ODATFB_HALT)); this->ClearSeparation(); if (HasBit(this->vehicle_flags, VF_TIMETABLE_SEPARATION)) ClrBit(this->vehicle_flags, VF_TIMETABLE_STARTED); SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, WID_VV_START_STOP); @@ -3046,7 +3082,11 @@ CommandCost Vehicle::SendToDepot(DoCommandFlag flags, DepotCommand command, Tile this->dest_tile = location; this->current_order.MakeGoToDepot(destination, ODTF_MANUAL); - if (!(command & DEPOT_SERVICE)) this->current_order.SetDepotActionType(ODATFB_HALT); + if (command & DEPOT_SELL) { + this->current_order.SetDepotActionType(ODATFB_HALT | ODATFB_SELL); + } else if (!(command & DEPOT_SERVICE)) { + this->current_order.SetDepotActionType(ODATFB_HALT); + } SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, WID_VV_START_STOP); /* If there is no depot in front, reverse automatically (trains only) */ diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index 53f755b66e..a760cf5737 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -1542,7 +1542,7 @@ CommandCost CmdSendVehicleToDepot(TileIndex tile, DoCommandFlag flags, uint32 p1 /* Mass goto depot requested */ VehicleListIdentifier vli; if (!vli.UnpackIfValid(p2)) return CMD_ERROR; - uint32 depot_flags = (p1 & (DEPOT_SERVICE | DEPOT_CANCEL)); + uint32 depot_flags = (p1 & (DEPOT_SERVICE | DEPOT_CANCEL | DEPOT_SELL)); if (!(p1 & DEPOT_CANCEL)) depot_flags |= DEPOT_DONT_CANCEL; return SendAllVehiclesToDepot(flags, (DepotCommand) depot_flags, vli); } diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 7098af503c..ca702b3e75 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -110,6 +110,13 @@ const StringID BaseVehicleListWindow::vehicle_depot_name[] = { STR_VEHICLE_LIST_SEND_AIRCRAFT_TO_HANGAR }; +const StringID BaseVehicleListWindow::vehicle_depot_sell_name[] = { + STR_VEHICLE_LIST_SEND_TRAIN_TO_DEPOT_SELL, + STR_VEHICLE_LIST_SEND_ROAD_VEHICLE_TO_DEPOT_SELL, + STR_VEHICLE_LIST_SEND_SHIP_TO_DEPOT_SELL, + STR_VEHICLE_LIST_SEND_AIRCRAFT_TO_HANGAR_SELL +}; + /** * Get the number of digits the biggest unit number of a set of vehicles has. * @param vehicles The list of vehicles. @@ -323,6 +330,7 @@ DropDownList *BaseVehicleListWindow::BuildActionDropdownList(bool show_autorepla } *list->Append() = new DropDownListStringItem(STR_VEHICLE_LIST_SEND_FOR_SERVICING, ADI_SERVICE, mass_action_disable); *list->Append() = new DropDownListStringItem(this->vehicle_depot_name[this->vli.vtype], ADI_DEPOT, mass_action_disable); + if (_settings_client.gui.show_depot_sell_gui) *list->Append() = new DropDownListStringItem(this->vehicle_depot_sell_name[this->vli.vtype], ADI_DEPOT_SELL, mass_action_disable); *list->Append() = new DropDownListStringItem(STR_VEHICLE_LIST_CANCEL_DEPOT_SERVICE, ADI_CANCEL_DEPOT, mass_action_disable); if (show_group) { @@ -1956,6 +1964,10 @@ public: DoCommandP(0, DEPOT_MASS_SEND | (index == ADI_SERVICE ? DEPOT_SERVICE : (DepotCommand)0), this->window_number, GetCmdSendToDepot(this->vli.vtype)); break; + case ADI_DEPOT_SELL: + DoCommandP(0, DEPOT_MASS_SEND | DEPOT_SELL, this->window_number, GetCmdSendToDepot(this->vli.vtype)); + break; + case ADI_CHANGE_ORDER: SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, HT_RECT, this); break; @@ -3204,6 +3216,8 @@ public: * depot with index 0, which would be used as fallback for * evaluating the string in the status bar. */ str = STR_EMPTY; + } else if (v->current_order.GetDepotActionType() & ODATFB_SELL) { + str = STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SELL_VEL; } else if (v->current_order.GetDepotActionType() & ODATFB_HALT) { str = STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_VEL; } else { @@ -3291,6 +3305,18 @@ public: this->depot_select_ctrl_pressed = _ctrl_pressed; this->depot_select_active = true; } + } else if (_settings_client.gui.show_depot_sell_gui && v->current_order.IsType(OT_GOTO_DEPOT)) { + if (_ctrl_pressed) { + OrderDepotActionFlags flags = v->current_order.GetDepotActionType() & (ODATFB_HALT | ODATFB_SELL); + DropDownList *list = new DropDownList(); + *list->Append() = new DropDownListStringItem(STR_VEHICLE_LIST_SEND_FOR_SERVICING, DEPOT_SERVICE | DEPOT_DONT_CANCEL, !flags); + *list->Append() = new DropDownListStringItem(BaseVehicleListWindow::vehicle_depot_name[v->type], DEPOT_DONT_CANCEL, flags == ODATFB_HALT); + *list->Append() = new DropDownListStringItem(BaseVehicleListWindow::vehicle_depot_sell_name[v->type], DEPOT_SELL | DEPOT_DONT_CANCEL, flags == (ODATFB_HALT | ODATFB_SELL)); + *list->Append() = new DropDownListStringItem(STR_VEHICLE_LIST_CANCEL_DEPOT_SERVICE, DEPOT_CANCEL, false); + ShowDropDownList(this, list, -1, widget, 0, true); + } else { + DoCommandP(v->tile, v->index | DEPOT_CANCEL, 0, GetCmdSendToDepot(v)); + } } else { this->HandleButtonClick(WID_VV_GOTO_DEPOT); DoCommandP(v->tile, v->index | (_ctrl_pressed ? DEPOT_SERVICE : 0U), 0, GetCmdSendToDepot(v)); @@ -3330,6 +3356,18 @@ public: } } + + virtual void OnDropdownSelect(int widget, int index) OVERRIDE + { + switch (widget) { + case WID_VV_GOTO_DEPOT: { + const Vehicle *v = Vehicle::Get(this->window_number); + DoCommandP(v->tile, v->index | index, 0, GetCmdSendToDepot(v)); + break; + } + } + } + virtual void OnTimeout() { if (!this->depot_select_active) { @@ -3358,8 +3396,13 @@ public: virtual bool OnRightClick(Point pt, int widget) { if (widget == WID_VV_GOTO_DEPOT && _settings_client.gui.hover_delay_ms == 0) { - uint64 arg = STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP + Vehicle::Get(this->window_number)->type; - GuiShowTooltips(this, STR_VEHICLE_VIEW_SEND_TO_DEPOT_TOOLTIP_SHIFT, 1, &arg, TCC_RIGHT_CLICK); + const Vehicle *v = Vehicle::Get(this->window_number); + if (_settings_client.gui.show_depot_sell_gui && v->current_order.IsType(OT_GOTO_DEPOT)) { + GuiShowTooltips(this, STR_VEHICLE_VIEW_SEND_TO_DEPOT_MENU, 0, nullptr, TCC_RIGHT_CLICK); + } else { + uint64 arg = STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP + v->type; + GuiShowTooltips(this, STR_VEHICLE_VIEW_SEND_TO_DEPOT_TOOLTIP_SHIFT, 1, &arg, TCC_RIGHT_CLICK); + } } return false; } @@ -3367,8 +3410,13 @@ public: virtual void OnHover(Point pt, int widget) { if (widget == WID_VV_GOTO_DEPOT) { - uint64 arg = STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP + Vehicle::Get(this->window_number)->type; - GuiShowTooltips(this, STR_VEHICLE_VIEW_SEND_TO_DEPOT_TOOLTIP_SHIFT, 1, &arg, TCC_HOVER); + const Vehicle *v = Vehicle::Get(this->window_number); + if (_settings_client.gui.show_depot_sell_gui && v->current_order.IsType(OT_GOTO_DEPOT)) { + GuiShowTooltips(this, STR_VEHICLE_VIEW_SEND_TO_DEPOT_MENU, 0, nullptr, TCC_HOVER); + } else { + uint64 arg = STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP + v->type; + GuiShowTooltips(this, STR_VEHICLE_VIEW_SEND_TO_DEPOT_TOOLTIP_SHIFT, 1, &arg, TCC_HOVER); + } } } diff --git a/src/vehicle_gui_base.h b/src/vehicle_gui_base.h index 469913e2e1..edd10e567d 100644 --- a/src/vehicle_gui_base.h +++ b/src/vehicle_gui_base.h @@ -44,6 +44,7 @@ struct BaseVehicleListWindow : public Window { ADI_REPLACE, ADI_SERVICE, ADI_DEPOT, + ADI_DEPOT_SELL, ADI_CANCEL_DEPOT, ADI_ADD_SHARED, ADI_REMOVE_ALL, @@ -53,6 +54,7 @@ struct BaseVehicleListWindow : public Window { }; static const StringID vehicle_depot_name[]; + static const StringID vehicle_depot_sell_name[]; static const StringID vehicle_sorter_names[]; static GUIVehicleList::SortFunction * const vehicle_sorter_funcs[]; const uint vehicle_sorter_non_ground_veh_disable_mask = (1 << 11); // STR_SORT_BY_LENGTH diff --git a/src/vehicle_type.h b/src/vehicle_type.h index d3672bcf8e..e9b901461b 100644 --- a/src/vehicle_type.h +++ b/src/vehicle_type.h @@ -65,13 +65,14 @@ enum VehiclePathFinders { /** Flags to add to p1 for goto depot commands. */ enum DepotCommand { + DEPOT_SELL = (1U << 25), ///< Go to depot and sell order DEPOT_CANCEL = (1U << 26), ///< Cancel depot/service order DEPOT_SPECIFIC = (1U << 27), ///< Send vehicle to specific depot DEPOT_SERVICE = (1U << 28), ///< The vehicle will leave the depot right after arrival (service only) DEPOT_MASS_SEND = (1U << 29), ///< Tells that it's a mass send to depot command (type in VLW flag) DEPOT_DONT_CANCEL = (1U << 30), ///< Don't cancel current goto depot command if any DEPOT_LOCATE_HANGAR = (1U << 31), ///< Find another airport if the target one lacks a hangar - DEPOT_COMMAND_MASK = 0x3FU << 26, + DEPOT_COMMAND_MASK = 0x7FU << 25, }; static const uint MAX_LENGTH_VEHICLE_NAME_CHARS = 128; ///< The maximum length of a vehicle name in characters including '\0'