From 8b66ebd4f03d2d455ee868e51a40f70990aa4269 Mon Sep 17 00:00:00 2001 From: Andreas Schmitt Date: Sun, 20 Jun 2021 08:35:28 +0200 Subject: [PATCH 1/8] Add auto named group generated when dropping a vehicle onto new group button --- src/command.cpp | 2 + src/command_type.h | 1 + src/group_cmd.cpp | 203 +++++++++++++++++++++++++++++++++++++++++++ src/group_gui.cpp | 10 +++ src/lang/english.txt | 1 + 5 files changed, 217 insertions(+) diff --git a/src/command.cpp b/src/command.cpp index 55edd921fc..cb1e14f522 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -223,6 +223,7 @@ CommandProc CmdDepotSellAllVehicles; CommandProc CmdDepotMassAutoReplace; CommandProc CmdCreateGroup; +CommandProc CmdCreateGroupAutoName; CommandProc CmdAlterGroup; CommandProc CmdDeleteGroup; CommandProc CmdCreateGroupFromList; @@ -457,6 +458,7 @@ static const Command _command_proc_table[] = { DEF_CMD(CmdDepotSellAllVehicles, 0, CMDT_VEHICLE_CONSTRUCTION ), // CMD_DEPOT_SELL_ALL_VEHICLES DEF_CMD(CmdDepotMassAutoReplace, 0, CMDT_VEHICLE_CONSTRUCTION ), // CMD_DEPOT_MASS_AUTOREPLACE DEF_CMD(CmdCreateGroup, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_CREATE_GROUP + DEF_CMD(CmdCreateGroupAutoName, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_CREATE_GROUP_AUTO_NAME DEF_CMD(CmdDeleteGroup, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_DELETE_GROUP DEF_CMD(CmdAlterGroup, 0, CMDT_OTHER_MANAGEMENT ), // CMD_ALTER_GROUP DEF_CMD(CmdCreateGroupFromList, 0, CMDT_OTHER_MANAGEMENT ), // CMD_CREATE_GROUP_FROM_LIST diff --git a/src/command_type.h b/src/command_type.h index 840b4645c1..167822ffe6 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -404,6 +404,7 @@ enum Commands { CMD_DEPOT_MASS_AUTOREPLACE, ///< force the autoreplace to take action in a given depot CMD_CREATE_GROUP, ///< create a new group + CMD_CREATE_GROUP_AUTO_NAME, ///< create a new group with an automatically generated name CMD_DELETE_GROUP, ///< delete a group CMD_ALTER_GROUP, ///< alter a group CMD_CREATE_GROUP_FROM_LIST, ///< create and rename a new group from a vehicle list diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index 5fc8688de4..5a2382ae6f 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -15,6 +15,7 @@ #include "vehicle_func.h" #include "autoreplace_base.h" #include "autoreplace_func.h" +#include "base_station_base.h" #include "string_func.h" #include "company_func.h" #include "core/pool_func.hpp" @@ -25,6 +26,8 @@ #include "table/strings.h" #include "safeguards.h" +#include "strings_func.h" +#include "townname_func.h" GroupID _new_group_id; @@ -645,6 +648,206 @@ CommandCost CmdAddVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, u return CommandCost(); } +Group* CreateAutoGroup(const VehicleType vt, const std::string& name, Group* parent) +{ + Group *group = nullptr; + + if (Group::CanAllocateItem()) + { + const Company *company = Company::Get(_current_company); + group = new Group(_current_company); + group->vehicle_type = vt; + group->parent = parent != nullptr ? parent->index : INVALID_GROUP; + group->livery.colour1 = company->livery[LS_DEFAULT].colour1; + group->livery.colour2 = company->livery[LS_DEFAULT].colour2; + + if (company->settings.renew_keep_length) { + SetBit(group->flags, GF_REPLACE_WAGON_REMOVAL); + } + + group->name = name; + } + + return group; +} + +std::string GetCargoList(const Vehicle *vehicle) +{ + auto checked_vehicle = vehicle; + std::vector cargoes; + + do { + if (checked_vehicle->cargo_cap == 0) continue; + + const StringID cargo_name = CargoSpec::Get(checked_vehicle->cargo_type)->name; + + if(cargo_name == INVALID_STRING_ID) continue; + + if (std::find(cargoes.begin(), cargoes.end(), cargo_name) == cargoes.end()) { + cargoes.push_back(cargo_name); + } + } while ((checked_vehicle = checked_vehicle->Next()) != nullptr); + + std::string cargo_list; + + if (!cargoes.empty()) { + for (auto cargo : cargoes) { + if (cargo_list.empty()) { + cargo_list += " ("; + } else { + cargo_list += ", "; + } + + char cargo_name_buffer[255]; + SetDParam(0, cargo); + GetString(cargo_name_buffer, STR_JUST_STRING, lastof(cargo_name_buffer)); + cargo_list += cargo_name_buffer; + } + } + + if (!cargo_list.empty()) { + cargo_list += ")"; + } + + return cargo_list; +} + +/** + * Adds a vehicle to an auto group. + * @param vehicle the vehicle + * @param from the first town in the orders list + * @param to the last town in the orders list + * @return the group to add the vehicle to. + */ +Group* AddVehicleToAutoGroup(const Vehicle *vehicle, const Town *from, const Town *to) +{ + assert(from != nullptr); + char from_town_name[255]; + GetTownName(from_town_name, from, from_town_name + 255); + Group *group; + + if (from == to || to == nullptr) + { + char local_name[255]; + GetString(local_name, STR_VEHICLE_GROUP_LOCAL_ROUTE, lastof(local_name)); + std::string name; + name += from_town_name; + name += " "; + name += local_name; + name += GetCargoList(vehicle); + group = CreateAutoGroup(vehicle->type, name, nullptr); + } + else + { + char to_town_name[255]; + std::string name; + name += from_town_name; + name += " to "; + GetTownName(to_town_name, to, to_town_name + 255); + name += to_town_name; + name += GetCargoList(vehicle); + group = CreateAutoGroup(vehicle->type, name, nullptr); + } + + return group; +} + +Town* GetTownFromDestination(const DestinationID destination) +{ + Town* town = nullptr; + + if (BaseStation *st = BaseStation::GetIfValid(destination); st != nullptr) + { + town = st->town; + } + + return town; +} + +void GetAutoGroupMostRelevantTowns(const Vehicle *vehicle, Town* &from, Town* &to) +{ + std::vector unique_destinations; + + const int num = vehicle->GetNumOrders(); + + for (int x = 0; x < num; x++) + { + Order *order = vehicle->GetOrder(x); + const DestinationID dest = order->GetDestination(); + Town *town = GetTownFromDestination(dest); + + if (order->GetType() == OT_GOTO_DEPOT) continue; + + if (town != nullptr && unique_destinations.end() == std::find(unique_destinations.begin(), unique_destinations.end(), town)) + { + unique_destinations.push_back(town); + } + } + + if (unique_destinations.empty()) return; + + from = unique_destinations[0]; + + if (unique_destinations.size() > 1) { + to = unique_destinations[unique_destinations.size() - 1]; + } +} + +/** + * Create a new group, rename it with automatically generated name and add vehicle to this group + * @param tile unused + * @param flags type of operation + * @param p1 vehicle to add to a group + * - p1 bit 0-19 : VehicleID + * - p1 bit 31 : Add shared vehicles as well. + * @param p2 unused + * @param text unused + * @return the cost of this operation or an error + */ +CommandCost CmdCreateGroupAutoName(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +{ + Vehicle *vehicle = Vehicle::GetIfValid(GB(p1, 0, 20)); + + if (vehicle == nullptr) return CMD_ERROR; + if (vehicle->owner != _current_company || !vehicle->IsPrimaryVehicle()) return CMD_ERROR; + + if (flags & DC_EXEC) { + Town *town_from = nullptr; + Town *town_to = nullptr; + + GetAutoGroupMostRelevantTowns(vehicle, town_from, town_to); + + if (town_from == nullptr) return CMD_ERROR; + + const auto new_group = AddVehicleToAutoGroup(vehicle, town_from, town_to); + + if (new_group == nullptr) return CMD_ERROR; + + if (HasBit(p1, 31)) { + /* Add vehicles in the shared order list as well. */ + for (Vehicle *v2 = vehicle->FirstShared(); v2 != nullptr; v2 = v2->NextShared()) { + if (v2->group_id != new_group->index) { + AddVehicleToGroup(v2, new_group->index); + } + } + } + + GroupStatistics::UpdateAutoreplace(vehicle->owner); + + /* Update the Replace Vehicle Windows */ + SetWindowDirty(WC_REPLACE_VEHICLE, vehicle->type); + SetWindowDirty(WC_VEHICLE_DEPOT, vehicle->tile); + SetWindowDirty(WC_VEHICLE_VIEW, vehicle->index); + SetWindowDirty(WC_VEHICLE_DETAILS, vehicle->index); + InvalidateWindowData(WC_VEHICLE_VIEW, vehicle->index); + InvalidateWindowData(WC_VEHICLE_DETAILS, vehicle->index); + InvalidateWindowData(GetWindowClassForVehicleType(vehicle->type), VehicleListIdentifier(VL_GROUP_LIST, vehicle->type, _current_company).Pack()); + InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN); + } + + return CommandCost(); +} + /** * Add all shared vehicles of all vehicles from a group * @param tile unused diff --git a/src/group_gui.cpp b/src/group_gui.cpp index 5da1d41934..a839a13e3e 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -999,6 +999,16 @@ public: } break; } + case WID_GL_CREATE_GROUP: { // make new group with vehicle specific name and add vehicle + const VehicleID vindex = this->vehicle_sel; + this->vehicle_sel = INVALID_VEHICLE; + this->group_over = INVALID_GROUP; + this->SetDirty(); + + DoCommandP(0, vindex | (_ctrl_pressed ? 1 << 31 : 0),0 , CMD_CREATE_GROUP_AUTO_NAME, nullptr, nullptr); + + break; + } } } diff --git a/src/lang/english.txt b/src/lang/english.txt index eba78574a4..997cc7b1ee 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -4925,6 +4925,7 @@ STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR_LIFETIME :{STRING2} (life STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS :{BLACK}Reliability: {LTBLUE}{COMMA}% {BLACK}Breakdowns since last service: {LTBLUE}{COMMA} STR_VEHICLE_INFO_GROUP :{BLACK}Group: {LTBLUE}{GROUP} +STR_VEHICLE_GROUP_LOCAL_ROUTE :Local STR_VEHICLE_INFO_BUILT_VALUE :{LTBLUE}{ENGINE} {BLACK}Built: {LTBLUE}{NUM}{BLACK} Value: {LTBLUE}{CURRENCY_LONG} STR_VEHICLE_INFO_NO_CAPACITY :{BLACK}Capacity: {LTBLUE}None{STRING} From 05b76aa3f8c3b549264fc3744b06bd521cbce0f4 Mon Sep 17 00:00:00 2001 From: Andreas Schmitt Date: Sun, 20 Jun 2021 10:22:16 +0200 Subject: [PATCH 2/8] Fix single vehicle not being added and wrong town name being used --- src/group_cmd.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index 5a2382ae6f..af088a7049 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -27,6 +27,7 @@ #include "safeguards.h" #include "strings_func.h" +#include "town.h" #include "townname_func.h" GroupID _new_group_id; @@ -719,11 +720,9 @@ std::string GetCargoList(const Vehicle *vehicle) * @param to the last town in the orders list * @return the group to add the vehicle to. */ -Group* AddVehicleToAutoGroup(const Vehicle *vehicle, const Town *from, const Town *to) +Group* CreateVehicleAutoGroup(const Vehicle *vehicle, const Town *from, const Town *to) { assert(from != nullptr); - char from_town_name[255]; - GetTownName(from_town_name, from, from_town_name + 255); Group *group; if (from == to || to == nullptr) @@ -731,7 +730,7 @@ Group* AddVehicleToAutoGroup(const Vehicle *vehicle, const Town *from, const Tow char local_name[255]; GetString(local_name, STR_VEHICLE_GROUP_LOCAL_ROUTE, lastof(local_name)); std::string name; - name += from_town_name; + name += from->GetCachedName(); name += " "; name += local_name; name += GetCargoList(vehicle); @@ -739,12 +738,10 @@ Group* AddVehicleToAutoGroup(const Vehicle *vehicle, const Town *from, const Tow } else { - char to_town_name[255]; std::string name; - name += from_town_name; + name += from->GetCachedName(); name += " to "; - GetTownName(to_town_name, to, to_town_name + 255); - name += to_town_name; + name += to->GetCachedName(); name += GetCargoList(vehicle); group = CreateAutoGroup(vehicle->type, name, nullptr); } @@ -819,10 +816,12 @@ CommandCost CmdCreateGroupAutoName(TileIndex tile, DoCommandFlag flags, uint32 p if (town_from == nullptr) return CMD_ERROR; - const auto new_group = AddVehicleToAutoGroup(vehicle, town_from, town_to); + const auto new_group = CreateVehicleAutoGroup(vehicle, town_from, town_to); if (new_group == nullptr) return CMD_ERROR; + AddVehicleToGroup(vehicle, new_group->index); + if (HasBit(p1, 31)) { /* Add vehicles in the shared order list as well. */ for (Vehicle *v2 = vehicle->FirstShared(); v2 != nullptr; v2 = v2->NextShared()) { From c2785be685716fc47b089e46d37afcfab08e1ff4 Mon Sep 17 00:00:00 2001 From: Andreas Schmitt Date: Sun, 20 Jun 2021 10:22:43 +0200 Subject: [PATCH 3/8] Make old group creation methods consistent with new one by calling the same command --- src/order_gui.cpp | 4 ++-- src/vehicle_gui.cpp | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/order_gui.cpp b/src/order_gui.cpp index c8c446df81..6aec110b13 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -2552,8 +2552,8 @@ public: break; case WID_O_ADD_VEH_GROUP: { - this->query_text_widget = WID_O_ADD_VEH_GROUP; - ShowQueryString(STR_EMPTY, STR_GROUP_RENAME_CAPTION, MAX_LENGTH_GROUP_NAME_CHARS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT | QSF_LEN_IN_CHARS); + this->SetDirty(); + DoCommandP(0, this->vehicle->index | 0,0 , CMD_CREATE_GROUP_AUTO_NAME, nullptr, nullptr); break; } diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 9b7fabffee..195cbd3157 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -2346,7 +2346,11 @@ public: break; case ADI_CREATE_GROUP: - ShowQueryString(STR_EMPTY, STR_GROUP_RENAME_CAPTION, MAX_LENGTH_GROUP_NAME_CHARS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT | QSF_LEN_IN_CHARS); + if (!this->vehicles.empty()) { + const VehicleID vindex = (*this->vehicles.begin())->index; + this->SetDirty(); + DoCommandP(0, vindex | (1 << 31),0 , CMD_CREATE_GROUP_AUTO_NAME, nullptr, nullptr); + } break; case ADI_TRACERESTRICT_SLOT_MGMT: { From 64488fdf296db49453eccc2ccc7dd26f1873707a Mon Sep 17 00:00:00 2001 From: Andreas Schmitt Date: Mon, 21 Jun 2021 00:31:36 +0200 Subject: [PATCH 4/8] Revert "Make old group creation methods consistent with new one by calling the same command" This reverts commit c2785be685716fc47b089e46d37afcfab08e1ff4. --- src/order_gui.cpp | 4 ++-- src/vehicle_gui.cpp | 6 +----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 6aec110b13..c8c446df81 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -2552,8 +2552,8 @@ public: break; case WID_O_ADD_VEH_GROUP: { - this->SetDirty(); - DoCommandP(0, this->vehicle->index | 0,0 , CMD_CREATE_GROUP_AUTO_NAME, nullptr, nullptr); + this->query_text_widget = WID_O_ADD_VEH_GROUP; + ShowQueryString(STR_EMPTY, STR_GROUP_RENAME_CAPTION, MAX_LENGTH_GROUP_NAME_CHARS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT | QSF_LEN_IN_CHARS); break; } diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 195cbd3157..9b7fabffee 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -2346,11 +2346,7 @@ public: break; case ADI_CREATE_GROUP: - if (!this->vehicles.empty()) { - const VehicleID vindex = (*this->vehicles.begin())->index; - this->SetDirty(); - DoCommandP(0, vindex | (1 << 31),0 , CMD_CREATE_GROUP_AUTO_NAME, nullptr, nullptr); - } + ShowQueryString(STR_EMPTY, STR_GROUP_RENAME_CAPTION, MAX_LENGTH_GROUP_NAME_CHARS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT | QSF_LEN_IN_CHARS); break; case ADI_TRACERESTRICT_SLOT_MGMT: { From 5d505f23896317aed66f3a15169066160f544c9d Mon Sep 17 00:00:00 2001 From: Andreas Schmitt Date: Mon, 21 Jun 2021 00:47:50 +0200 Subject: [PATCH 5/8] Fix crash and show error message if group creation fails --- src/group_cmd.cpp | 22 ++++++++++++---------- src/group_gui.cpp | 4 ++-- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index af088a7049..eaf26ce58b 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -770,11 +770,12 @@ void GetAutoGroupMostRelevantTowns(const Vehicle *vehicle, Town* &from, Town* &t for (int x = 0; x < num; x++) { Order *order = vehicle->GetOrder(x); + + if (order->GetType() != OT_GOTO_STATION) continue; + const DestinationID dest = order->GetDestination(); Town *town = GetTownFromDestination(dest); - if (order->GetType() == OT_GOTO_DEPOT) continue; - if (town != nullptr && unique_destinations.end() == std::find(unique_destinations.begin(), unique_destinations.end(), town)) { unique_destinations.push_back(town); @@ -807,18 +808,19 @@ CommandCost CmdCreateGroupAutoName(TileIndex tile, DoCommandFlag flags, uint32 p if (vehicle == nullptr) return CMD_ERROR; if (vehicle->owner != _current_company || !vehicle->IsPrimaryVehicle()) return CMD_ERROR; + if (!Group::CanAllocateItem()) return CMD_ERROR; + + Town *town_from = nullptr; + Town *town_to = nullptr; + + GetAutoGroupMostRelevantTowns(vehicle, town_from, town_to); + + if (town_from == nullptr) return CMD_ERROR; if (flags & DC_EXEC) { - Town *town_from = nullptr; - Town *town_to = nullptr; - - GetAutoGroupMostRelevantTowns(vehicle, town_from, town_to); - - if (town_from == nullptr) return CMD_ERROR; - const auto new_group = CreateVehicleAutoGroup(vehicle, town_from, town_to); - if (new_group == nullptr) return CMD_ERROR; + assert(new_group != nullptr); AddVehicleToGroup(vehicle, new_group->index); diff --git a/src/group_gui.cpp b/src/group_gui.cpp index a839a13e3e..3074610d58 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -999,13 +999,13 @@ public: } break; } - case WID_GL_CREATE_GROUP: { // make new group with vehicle specific name and add vehicle + case WID_GL_CREATE_GROUP: { // make new group with auto generated vehicle specific name and add vehicle const VehicleID vindex = this->vehicle_sel; this->vehicle_sel = INVALID_VEHICLE; this->group_over = INVALID_GROUP; this->SetDirty(); - DoCommandP(0, vindex | (_ctrl_pressed ? 1 << 31 : 0),0 , CMD_CREATE_GROUP_AUTO_NAME, nullptr, nullptr); + DoCommandP(0, vindex | (_ctrl_pressed ? 1U << 31 : 0),0 , CMD_CREATE_GROUP_AUTO_NAME | CMD_MSG(STR_ERROR_GROUP_CAN_T_CREATE), nullptr, nullptr); break; } From dee05f520f0a1fe5d29cdaea311536853a2c1a79 Mon Sep 17 00:00:00 2001 From: Andreas Schmitt Date: Mon, 21 Jun 2021 01:15:20 +0200 Subject: [PATCH 6/8] Add German translation --- src/lang/german.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/german.txt b/src/lang/german.txt index f1724dd482..b974400749 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -4781,6 +4781,7 @@ STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR_LIFETIME :{STRING} (seit STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS :{BLACK}Zuverlässigkeit: {LTBLUE}{COMMA}% {BLACK}Pannen seit der letzten Wartung: {LTBLUE}{COMMA} STR_VEHICLE_INFO_GROUP :{BLACK}Gruppe: {LTBLUE}{GROUP} +STR_VEHICLE_GROUP_LOCAL_ROUTE :Ortsbereich STR_VEHICLE_INFO_BUILT_VALUE :{LTBLUE}{ENGINE} {BLACK}Gebaut: {LTBLUE}{NUM}{BLACK} Wert: {LTBLUE}{CURRENCY_LONG} STR_VEHICLE_INFO_NO_CAPACITY :{BLACK}Kapazität: {LTBLUE}Keine{STRING} From 6c07758cc309bcdb42d3c2aa4d1597e75530bfb9 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 27 Jun 2021 02:28:52 +0100 Subject: [PATCH 7/8] Do name generation at client, fix localisation Use existing group creation command --- src/command.cpp | 2 - src/command_type.h | 1 - src/group.h | 2 + src/group_cmd.cpp | 182 ++++++++----------------------------------- src/group_gui.cpp | 9 ++- src/lang/english.txt | 5 +- src/lang/german.txt | 3 +- 7 files changed, 45 insertions(+), 159 deletions(-) diff --git a/src/command.cpp b/src/command.cpp index cb1e14f522..55edd921fc 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -223,7 +223,6 @@ CommandProc CmdDepotSellAllVehicles; CommandProc CmdDepotMassAutoReplace; CommandProc CmdCreateGroup; -CommandProc CmdCreateGroupAutoName; CommandProc CmdAlterGroup; CommandProc CmdDeleteGroup; CommandProc CmdCreateGroupFromList; @@ -458,7 +457,6 @@ static const Command _command_proc_table[] = { DEF_CMD(CmdDepotSellAllVehicles, 0, CMDT_VEHICLE_CONSTRUCTION ), // CMD_DEPOT_SELL_ALL_VEHICLES DEF_CMD(CmdDepotMassAutoReplace, 0, CMDT_VEHICLE_CONSTRUCTION ), // CMD_DEPOT_MASS_AUTOREPLACE DEF_CMD(CmdCreateGroup, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_CREATE_GROUP - DEF_CMD(CmdCreateGroupAutoName, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_CREATE_GROUP_AUTO_NAME DEF_CMD(CmdDeleteGroup, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_DELETE_GROUP DEF_CMD(CmdAlterGroup, 0, CMDT_OTHER_MANAGEMENT ), // CMD_ALTER_GROUP DEF_CMD(CmdCreateGroupFromList, 0, CMDT_OTHER_MANAGEMENT ), // CMD_CREATE_GROUP_FROM_LIST diff --git a/src/command_type.h b/src/command_type.h index 167822ffe6..840b4645c1 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -404,7 +404,6 @@ enum Commands { CMD_DEPOT_MASS_AUTOREPLACE, ///< force the autoreplace to take action in a given depot CMD_CREATE_GROUP, ///< create a new group - CMD_CREATE_GROUP_AUTO_NAME, ///< create a new group with an automatically generated name CMD_DELETE_GROUP, ///< delete a group CMD_ALTER_GROUP, ///< alter a group CMD_CREATE_GROUP_FROM_LIST, ///< create and rename a new group from a vehicle list diff --git a/src/group.h b/src/group.h index f296ee844f..5de8dd4e96 100644 --- a/src/group.h +++ b/src/group.h @@ -117,6 +117,8 @@ void RemoveVehicleFromGroup(const Vehicle *v); void RemoveAllGroupsForCompany(const CompanyID company); bool GroupIsInGroup(GroupID search, GroupID group); +std::string GenerateAutoNameForVehicleGroup(const Vehicle *v); + extern GroupID _new_group_id; #endif /* GROUP_H */ diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index eaf26ce58b..7d888dabbc 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -649,119 +649,19 @@ CommandCost CmdAddVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, u return CommandCost(); } -Group* CreateAutoGroup(const VehicleType vt, const std::string& name, Group* parent) -{ - Group *group = nullptr; - - if (Group::CanAllocateItem()) - { - const Company *company = Company::Get(_current_company); - group = new Group(_current_company); - group->vehicle_type = vt; - group->parent = parent != nullptr ? parent->index : INVALID_GROUP; - group->livery.colour1 = company->livery[LS_DEFAULT].colour1; - group->livery.colour2 = company->livery[LS_DEFAULT].colour2; - - if (company->settings.renew_keep_length) { - SetBit(group->flags, GF_REPLACE_WAGON_REMOVAL); - } - - group->name = name; - } - - return group; -} - -std::string GetCargoList(const Vehicle *vehicle) -{ - auto checked_vehicle = vehicle; - std::vector cargoes; - - do { - if (checked_vehicle->cargo_cap == 0) continue; - - const StringID cargo_name = CargoSpec::Get(checked_vehicle->cargo_type)->name; - - if(cargo_name == INVALID_STRING_ID) continue; - - if (std::find(cargoes.begin(), cargoes.end(), cargo_name) == cargoes.end()) { - cargoes.push_back(cargo_name); - } - } while ((checked_vehicle = checked_vehicle->Next()) != nullptr); - - std::string cargo_list; - - if (!cargoes.empty()) { - for (auto cargo : cargoes) { - if (cargo_list.empty()) { - cargo_list += " ("; - } else { - cargo_list += ", "; - } - - char cargo_name_buffer[255]; - SetDParam(0, cargo); - GetString(cargo_name_buffer, STR_JUST_STRING, lastof(cargo_name_buffer)); - cargo_list += cargo_name_buffer; - } - } - - if (!cargo_list.empty()) { - cargo_list += ")"; - } - - return cargo_list; -} - -/** - * Adds a vehicle to an auto group. - * @param vehicle the vehicle - * @param from the first town in the orders list - * @param to the last town in the orders list - * @return the group to add the vehicle to. - */ -Group* CreateVehicleAutoGroup(const Vehicle *vehicle, const Town *from, const Town *to) -{ - assert(from != nullptr); - Group *group; - - if (from == to || to == nullptr) - { - char local_name[255]; - GetString(local_name, STR_VEHICLE_GROUP_LOCAL_ROUTE, lastof(local_name)); - std::string name; - name += from->GetCachedName(); - name += " "; - name += local_name; - name += GetCargoList(vehicle); - group = CreateAutoGroup(vehicle->type, name, nullptr); - } - else - { - std::string name; - name += from->GetCachedName(); - name += " to "; - name += to->GetCachedName(); - name += GetCargoList(vehicle); - group = CreateAutoGroup(vehicle->type, name, nullptr); - } - - return group; -} - -Town* GetTownFromDestination(const DestinationID destination) +static Town* GetTownFromDestination(const DestinationID destination) { Town* town = nullptr; - if (BaseStation *st = BaseStation::GetIfValid(destination); st != nullptr) - { + BaseStation *st = BaseStation::GetIfValid(destination); + if (st != nullptr) { town = st->town; } return town; } -void GetAutoGroupMostRelevantTowns(const Vehicle *vehicle, Town* &from, Town* &to) +static void GetAutoGroupMostRelevantTowns(const Vehicle *vehicle, Town* &from, Town* &to) { std::vector unique_destinations; @@ -791,62 +691,42 @@ void GetAutoGroupMostRelevantTowns(const Vehicle *vehicle, Town* &from, Town* &t } } -/** - * Create a new group, rename it with automatically generated name and add vehicle to this group - * @param tile unused - * @param flags type of operation - * @param p1 vehicle to add to a group - * - p1 bit 0-19 : VehicleID - * - p1 bit 31 : Add shared vehicles as well. - * @param p2 unused - * @param text unused - * @return the cost of this operation or an error - */ -CommandCost CmdCreateGroupAutoName(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +static CargoTypes GetVehicleCargoList(const Vehicle *vehicle) { - Vehicle *vehicle = Vehicle::GetIfValid(GB(p1, 0, 20)); + CargoTypes cargoes = 0; - if (vehicle == nullptr) return CMD_ERROR; - if (vehicle->owner != _current_company || !vehicle->IsPrimaryVehicle()) return CMD_ERROR; - if (!Group::CanAllocateItem()) return CMD_ERROR; + for (const Vehicle *u = vehicle; u != nullptr; u = u->Next()) { + if (u->cargo_cap == 0) continue; + SetBit(cargoes, u->cargo_type); + } + return cargoes; +} + +std::string GenerateAutoNameForVehicleGroup(const Vehicle *v) +{ Town *town_from = nullptr; Town *town_to = nullptr; - - GetAutoGroupMostRelevantTowns(vehicle, town_from, town_to); - if (town_from == nullptr) return CMD_ERROR; + GetAutoGroupMostRelevantTowns(v, town_from, town_to); + if (town_from == nullptr) return ""; - if (flags & DC_EXEC) { - const auto new_group = CreateVehicleAutoGroup(vehicle, town_from, town_to); + CargoTypes cargoes = GetVehicleCargoList(v); - assert(new_group != nullptr); - - AddVehicleToGroup(vehicle, new_group->index); - - if (HasBit(p1, 31)) { - /* Add vehicles in the shared order list as well. */ - for (Vehicle *v2 = vehicle->FirstShared(); v2 != nullptr; v2 = v2->NextShared()) { - if (v2->group_id != new_group->index) { - AddVehicleToGroup(v2, new_group->index); - } - } - } - - GroupStatistics::UpdateAutoreplace(vehicle->owner); - - /* Update the Replace Vehicle Windows */ - SetWindowDirty(WC_REPLACE_VEHICLE, vehicle->type); - SetWindowDirty(WC_VEHICLE_DEPOT, vehicle->tile); - SetWindowDirty(WC_VEHICLE_VIEW, vehicle->index); - SetWindowDirty(WC_VEHICLE_DETAILS, vehicle->index); - InvalidateWindowData(WC_VEHICLE_VIEW, vehicle->index); - InvalidateWindowData(WC_VEHICLE_DETAILS, vehicle->index); - InvalidateWindowData(GetWindowClassForVehicleType(vehicle->type), VehicleListIdentifier(VL_GROUP_LIST, vehicle->type, _current_company).Pack()); - InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN); + char group_name[512]; + if (town_from == town_to || town_to == nullptr) { + SetDParam(0, town_from->index); + SetDParam(1, (cargoes != 0) ? STR_VEHICLE_AUTO_GROUP_CARGO_LIST : STR_EMPTY); + SetDParam(2, cargoes); + GetString(group_name, STR_VEHICLE_AUTO_GROUP_LOCAL_ROUTE, lastof(group_name)); + } else { + SetDParam(0, town_from->index); + SetDParam(1, town_to->index); + SetDParam(2, (cargoes != 0) ? STR_VEHICLE_AUTO_GROUP_CARGO_LIST : STR_EMPTY); + SetDParam(3, cargoes); + GetString(group_name, STR_VEHICLE_AUTO_GROUP_ROUTE, lastof(group_name)); } - - return CommandCost(); + return std::string(group_name); } /** diff --git a/src/group_gui.cpp b/src/group_gui.cpp index 3074610d58..9c2b5a3ff0 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -999,14 +999,17 @@ public: } break; } + case WID_GL_CREATE_GROUP: { // make new group with auto generated vehicle specific name and add vehicle - const VehicleID vindex = this->vehicle_sel; + const Vehicle *v = Vehicle::Get(vehicle_sel); this->vehicle_sel = INVALID_VEHICLE; this->group_over = INVALID_GROUP; this->SetDirty(); - DoCommandP(0, vindex | (_ctrl_pressed ? 1U << 31 : 0),0 , CMD_CREATE_GROUP_AUTO_NAME | CMD_MSG(STR_ERROR_GROUP_CAN_T_CREATE), nullptr, nullptr); - + std::string name = GenerateAutoNameForVehicleGroup(v); + + DoCommandP(0, VehicleListIdentifier(_ctrl_pressed ? VL_SHARED_ORDERS : VL_SINGLE_VEH, v->type, v->owner, v->index).Pack(), 0, CMD_CREATE_GROUP_FROM_LIST | CMD_MSG(STR_ERROR_GROUP_CAN_T_CREATE), nullptr, name.c_str()); + break; } } diff --git a/src/lang/english.txt b/src/lang/english.txt index 997cc7b1ee..7ad5bafd41 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -4925,7 +4925,10 @@ STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR_LIFETIME :{STRING2} (life STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS :{BLACK}Reliability: {LTBLUE}{COMMA}% {BLACK}Breakdowns since last service: {LTBLUE}{COMMA} STR_VEHICLE_INFO_GROUP :{BLACK}Group: {LTBLUE}{GROUP} -STR_VEHICLE_GROUP_LOCAL_ROUTE :Local + +STR_VEHICLE_AUTO_GROUP_ROUTE :{TOWN} to {TOWN}{STRING1} +STR_VEHICLE_AUTO_GROUP_LOCAL_ROUTE :{TOWN} Local{STRING1} +STR_VEHICLE_AUTO_GROUP_CARGO_LIST : ({CARGO_LIST}) STR_VEHICLE_INFO_BUILT_VALUE :{LTBLUE}{ENGINE} {BLACK}Built: {LTBLUE}{NUM}{BLACK} Value: {LTBLUE}{CURRENCY_LONG} STR_VEHICLE_INFO_NO_CAPACITY :{BLACK}Capacity: {LTBLUE}None{STRING} diff --git a/src/lang/german.txt b/src/lang/german.txt index b974400749..24e7a2680a 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -4781,7 +4781,8 @@ STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR_LIFETIME :{STRING} (seit STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS :{BLACK}Zuverlässigkeit: {LTBLUE}{COMMA}% {BLACK}Pannen seit der letzten Wartung: {LTBLUE}{COMMA} STR_VEHICLE_INFO_GROUP :{BLACK}Gruppe: {LTBLUE}{GROUP} -STR_VEHICLE_GROUP_LOCAL_ROUTE :Ortsbereich + +STR_VEHICLE_AUTO_GROUP_LOCAL_ROUTE :{TOWN} Ortsbereich {CARGO_LIST} STR_VEHICLE_INFO_BUILT_VALUE :{LTBLUE}{ENGINE} {BLACK}Gebaut: {LTBLUE}{NUM}{BLACK} Wert: {LTBLUE}{CURRENCY_LONG} STR_VEHICLE_INFO_NO_CAPACITY :{BLACK}Kapazität: {LTBLUE}Keine{STRING} From d246ba1dd173448f4f27e2a030b8d7bae9fd0626 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 27 Jun 2021 02:55:21 +0100 Subject: [PATCH 8/8] Lower create group button when vehicle dragged over it --- src/group_gui.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/group_gui.cpp b/src/group_gui.cpp index 9c2b5a3ff0..0b4f4e2cd8 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -1123,6 +1123,21 @@ public: this->group_sel = INVALID_GROUP; this->group_over = INVALID_GROUP; this->SetWidgetDirty(WID_GL_LIST_VEHICLE); + this->SetVehicleDraggedOverCreateGroupButton(false); + } + + void SetVehicleDraggedOverCreateGroupButton(bool dragged) + { + NWidgetCore *create_group = this->GetWidget(WID_GL_CREATE_GROUP); + if (dragged && (create_group->type & WWB_PUSHBUTTON)) { + create_group->type = static_cast(create_group->type & ~WWB_PUSHBUTTON); + create_group->SetLowered(true); + create_group->SetDirty(this); + } else if (!dragged && !(create_group->type & WWB_PUSHBUTTON)) { + create_group->type = static_cast(create_group->type | WWB_PUSHBUTTON); + create_group->SetLowered(false); + create_group->SetDirty(this); + } } void OnMouseDrag(Point pt, int widget) override @@ -1131,6 +1146,8 @@ public: /* A vehicle is dragged over... */ GroupID new_group_over = INVALID_GROUP; + + bool create_group_drag_over = false; switch (widget) { case WID_GL_DEFAULT_VEHICLES: // ... the 'default' group. new_group_over = DEFAULT_GROUP; @@ -1141,8 +1158,15 @@ public: new_group_over = id_g >= this->groups.size() ? NEW_GROUP : this->groups[id_g]->index; break; } + + case WID_GL_CREATE_GROUP: { + if (this->vehicle_sel != INVALID_VEHICLE) create_group_drag_over = true; + break; + } } + this->SetVehicleDraggedOverCreateGroupButton(create_group_drag_over); + /* Do not highlight when dragging over the current group */ if (this->vehicle_sel != INVALID_VEHICLE) { if (Vehicle::Get(vehicle_sel)->group_id == new_group_over) new_group_over = INVALID_GROUP;