Code: Select all
diff --git a/src/command.cpp b/src/command.cpp
index 959610c..de74e22 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -183,11 +183,13 @@ CommandProc CmdDepotSellAllVehicles;
CommandProc CmdDepotMassAutoReplace;
CommandProc CmdCreateGroup;
+CommandProc CmdCreateGroupSpecificName;
CommandProc CmdAlterGroup;
CommandProc CmdDeleteGroup;
CommandProc CmdAddVehicleGroup;
CommandProc CmdAddSharedVehicleGroup;
CommandProc CmdRemoveAllVehiclesGroup;
+CommandProc CmdAutoGroupVehiclesGroup;
CommandProc CmdSetGroupReplaceProtection;
CommandProc CmdMoveOrder;
@@ -341,11 +343,13 @@ 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(CmdCreateGroupSpecificName, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_CREATE_GROUP_SPECIFIC_NAME
DEF_CMD(CmdDeleteGroup, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_DELETE_GROUP
DEF_CMD(CmdAlterGroup, 0, CMDT_OTHER_MANAGEMENT ), // CMD_ALTER_GROUP
DEF_CMD(CmdAddVehicleGroup, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_ADD_VEHICLE_GROUP
DEF_CMD(CmdAddSharedVehicleGroup, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_ADD_SHARE_VEHICLE_GROUP
DEF_CMD(CmdRemoveAllVehiclesGroup, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_REMOVE_ALL_VEHICLES_GROUP
+ DEF_CMD(CmdAutoGroupVehiclesGroup, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_AUTO_GROUP_VEHICLES_GROUP
DEF_CMD(CmdSetGroupReplaceProtection, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_SET_GROUP_REPLACE_PROTECTION
DEF_CMD(CmdMoveOrder, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_MOVE_ORDER
DEF_CMD(CmdChangeTimetable, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_CHANGE_TIMETABLE
diff --git a/src/command_type.h b/src/command_type.h
index f318216..e0cd11b 100644
--- a/src/command_type.h
+++ b/src/command_type.h
@@ -314,11 +314,13 @@ 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_SPECIFIC_NAME, ///< create a new group
CMD_DELETE_GROUP, ///< delete a group
CMD_ALTER_GROUP, ///< alter a group
CMD_ADD_VEHICLE_GROUP, ///< add a vehicle to a group
CMD_ADD_SHARED_VEHICLE_GROUP, ///< add all other shared vehicles to a group which are missing
CMD_REMOVE_ALL_VEHICLES_GROUP, ///< remove all vehicles from a group
+ CMD_AUTO_GROUP_VEHICLES_GROUP, ///< group all vehicles
CMD_SET_GROUP_REPLACE_PROTECTION, ///< set the autoreplace-protection for a group
CMD_MOVE_ORDER, ///< move an order
diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp
index 12cce41..7d5f6a7 100644
--- a/src/group_cmd.cpp
+++ b/src/group_cmd.cpp
@@ -15,9 +15,12 @@
#include "train.h"
#include "vehiclelist.h"
#include "vehicle_func.h"
+#include "station_base.h"
+#include "town.h"
#include "autoreplace_base.h"
#include "autoreplace_func.h"
#include "string_func.h"
+#include "strings_func.h"
#include "company_func.h"
#include "core/pool_func.hpp"
#include "order_backup.h"
@@ -33,12 +36,12 @@ INSTANTIATE_POOL_METHODS(Group)
GroupStatistics::GroupStatistics()
{
- this->num_engines = CallocT<uint16>(Engine::GetPoolSize());
+ this->num_engines = CallocT<uint16>(Engine::GetPoolSize());
}
GroupStatistics::~GroupStatistics()
{
- free(this->num_engines);
+ free(this->num_engines);
}
/**
@@ -46,13 +49,13 @@ GroupStatistics::~GroupStatistics()
*/
void GroupStatistics::Clear()
{
- this->num_vehicle = 0;
- this->num_profit_vehicle = 0;
- this->profit_last_year = 0;
+ this->num_vehicle = 0;
+ this->num_profit_vehicle = 0;
+ this->profit_last_year = 0;
- /* This is also called when NewGRF change. So the number of engines might have changed. Reallocate. */
- free(this->num_engines);
- this->num_engines = CallocT<uint16>(Engine::GetPoolSize());
+ /* This is also called when NewGRF change. So the number of engines might have changed. Reallocate. */
+ free(this->num_engines);
+ this->num_engines = CallocT<uint16>(Engine::GetPoolSize());
}
/**
@@ -64,17 +67,17 @@ void GroupStatistics::Clear()
*/
/* static */ GroupStatistics &GroupStatistics::Get(CompanyID company, GroupID id_g, VehicleType type)
{
- if (Group::IsValidID(id_g)) {
- Group *g = Group::Get(id_g);
- assert(g->owner == company);
- assert(g->vehicle_type == type);
- return g->statistics;
- }
+ if (Group::IsValidID(id_g)) {
+ Group *g = Group::Get(id_g);
+ assert(g->owner == company);
+ assert(g->vehicle_type == type);
+ return g->statistics;
+ }
- if (IsDefaultGroupID(id_g)) return Company::Get(company)->group_default[type];
- if (IsAllGroupID(id_g)) return Company::Get(company)->group_all[type];
+ if (IsDefaultGroupID(id_g)) return Company::Get(company)->group_default[type];
+ if (IsAllGroupID(id_g)) return Company::Get(company)->group_all[type];
- NOT_REACHED();
+ NOT_REACHED();
}
/**
@@ -84,7 +87,7 @@ void GroupStatistics::Clear()
*/
/* static */ GroupStatistics &GroupStatistics::Get(const Vehicle *v)
{
- return GroupStatistics::Get(v->owner, v->group_id, v->type);
+ return GroupStatistics::Get(v->owner, v->group_id, v->type);
}
/**
@@ -94,7 +97,7 @@ void GroupStatistics::Clear()
*/
/* static */ GroupStatistics &GroupStatistics::GetAllGroup(const Vehicle *v)
{
- return GroupStatistics::Get(v->owner, ALL_GROUP, v->type);
+ return GroupStatistics::Get(v->owner, ALL_GROUP, v->type);
}
/**
@@ -102,32 +105,32 @@ void GroupStatistics::Clear()
*/
/* static */ void GroupStatistics::UpdateAfterLoad()
{
- /* Set up the engine count for all companies */
- Company *c;
- FOR_ALL_COMPANIES(c) {
- for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
- c->group_all[type].Clear();
- c->group_default[type].Clear();
- }
- }
-
- /* Recalculate */
- Group *g;
- FOR_ALL_GROUPS(g) {
- g->statistics.Clear();
- }
-
- const Vehicle *v;
- FOR_ALL_VEHICLES(v) {
- if (!v->IsEngineCountable()) continue;
-
- GroupStatistics::CountEngine(v, 1);
- if (v->IsPrimaryVehicle()) GroupStatistics::CountVehicle(v, 1);
- }
-
- FOR_ALL_COMPANIES(c) {
- GroupStatistics::UpdateAutoreplace(c->index);
- }
+ /* Set up the engine count for all companies */
+ Company *c;
+ FOR_ALL_COMPANIES(c) {
+ for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
+ c->group_all[type].Clear();
+ c->group_default[type].Clear();
+ }
+ }
+
+ /* Recalculate */
+ Group *g;
+ FOR_ALL_GROUPS(g) {
+ g->statistics.Clear();
+ }
+
+ const Vehicle *v;
+ FOR_ALL_VEHICLES(v) {
+ if (!v->IsEngineCountable()) continue;
+
+ GroupStatistics::CountEngine(v, 1);
+ if (v->IsPrimaryVehicle()) GroupStatistics::CountVehicle(v, 1);
+ }
+
+ FOR_ALL_COMPANIES(c) {
+ GroupStatistics::UpdateAutoreplace(c->index);
+ }
}
/**
@@ -137,20 +140,20 @@ void GroupStatistics::Clear()
*/
/* static */ void GroupStatistics::CountVehicle(const Vehicle *v, int delta)
{
- assert(delta == 1 || delta == -1);
+ assert(delta == 1 || delta == -1);
- GroupStatistics &stats_all = GroupStatistics::GetAllGroup(v);
- GroupStatistics &stats = GroupStatistics::Get(v);
+ GroupStatistics &stats_all = GroupStatistics::GetAllGroup(v);
+ GroupStatistics &stats = GroupStatistics::Get(v);
- stats_all.num_vehicle += delta;
- stats.num_vehicle += delta;
+ stats_all.num_vehicle += delta;
+ stats.num_vehicle += delta;
- if (v->age > VEHICLE_PROFIT_MIN_AGE) {
- stats_all.num_profit_vehicle += delta;
- stats_all.profit_last_year += v->GetDisplayProfitLastYear() * delta;
- stats.num_profit_vehicle += delta;
- stats.profit_last_year += v->GetDisplayProfitLastYear() * delta;
- }
+ if (v->age > VEHICLE_PROFIT_MIN_AGE) {
+ stats_all.num_profit_vehicle += delta;
+ stats_all.profit_last_year += v->GetDisplayProfitLastYear() * delta;
+ stats.num_profit_vehicle += delta;
+ stats.profit_last_year += v->GetDisplayProfitLastYear() * delta;
+ }
}
/**
@@ -160,9 +163,9 @@ void GroupStatistics::Clear()
*/
/* static */ void GroupStatistics::CountEngine(const Vehicle *v, int delta)
{
- assert(delta == 1 || delta == -1);
- GroupStatistics::GetAllGroup(v).num_engines[v->engine_type] += delta;
- GroupStatistics::Get(v).num_engines[v->engine_type] += delta;
+ assert(delta == 1 || delta == -1);
+ GroupStatistics::GetAllGroup(v).num_engines[v->engine_type] += delta;
+ GroupStatistics::Get(v).num_engines[v->engine_type] += delta;
}
/**
@@ -170,13 +173,13 @@ void GroupStatistics::Clear()
*/
/* static */ void GroupStatistics::VehicleReachedProfitAge(const Vehicle *v)
{
- GroupStatistics &stats_all = GroupStatistics::GetAllGroup(v);
- GroupStatistics &stats = GroupStatistics::Get(v);
+ GroupStatistics &stats_all = GroupStatistics::GetAllGroup(v);
+ GroupStatistics &stats = GroupStatistics::Get(v);
- stats_all.num_profit_vehicle++;
- stats_all.profit_last_year += v->GetDisplayProfitLastYear();
- stats.num_profit_vehicle++;
- stats.profit_last_year += v->GetDisplayProfitLastYear();
+ stats_all.num_profit_vehicle++;
+ stats_all.profit_last_year += v->GetDisplayProfitLastYear();
+ stats.num_profit_vehicle++;
+ stats.profit_last_year += v->GetDisplayProfitLastYear();
}
/**
@@ -184,25 +187,25 @@ void GroupStatistics::Clear()
*/
/* static */ void GroupStatistics::UpdateProfits()
{
- /* Set up the engine count for all companies */
- Company *c;
- FOR_ALL_COMPANIES(c) {
- for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
- c->group_all[type].ClearProfits();
- c->group_default[type].ClearProfits();
- }
- }
-
- /* Recalculate */
- Group *g;
- FOR_ALL_GROUPS(g) {
- g->statistics.ClearProfits();
- }
-
- const Vehicle *v;
- FOR_ALL_VEHICLES(v) {
- if (v->IsPrimaryVehicle() && v->age > VEHICLE_PROFIT_MIN_AGE) GroupStatistics::VehicleReachedProfitAge(v);
- }
+ /* Set up the engine count for all companies */
+ Company *c;
+ FOR_ALL_COMPANIES(c) {
+ for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
+ c->group_all[type].ClearProfits();
+ c->group_default[type].ClearProfits();
+ }
+ }
+
+ /* Recalculate */
+ Group *g;
+ FOR_ALL_GROUPS(g) {
+ g->statistics.ClearProfits();
+ }
+
+ const Vehicle *v;
+ FOR_ALL_VEHICLES(v) {
+ if (v->IsPrimaryVehicle() && v->age > VEHICLE_PROFIT_MIN_AGE) GroupStatistics::VehicleReachedProfitAge(v);
+ }
}
/**
@@ -211,29 +214,29 @@ void GroupStatistics::Clear()
*/
/* static */ void GroupStatistics::UpdateAutoreplace(CompanyID company)
{
- /* Set up the engine count for all companies */
- Company *c = Company::Get(company);
- for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
- c->group_all[type].ClearAutoreplace();
- c->group_default[type].ClearAutoreplace();
- }
-
- /* Recalculate */
- Group *g;
- FOR_ALL_GROUPS(g) {
- if (g->owner != company) continue;
- g->statistics.ClearAutoreplace();
- }
-
- for (EngineRenewList erl = c->engine_renew_list; erl != NULL; erl = erl->next) {
- const Engine *e = Engine::Get(erl->from);
- GroupStatistics &stats = GroupStatistics::Get(company, erl->group_id, e->type);
- if (!stats.autoreplace_defined) {
- stats.autoreplace_defined = true;
- stats.autoreplace_finished = true;
- }
- if (stats.num_engines[erl->from] > 0) stats.autoreplace_finished = false;
- }
+ /* Set up the engine count for all companies */
+ Company *c = Company::Get(company);
+ for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
+ c->group_all[type].ClearAutoreplace();
+ c->group_default[type].ClearAutoreplace();
+ }
+
+ /* Recalculate */
+ Group *g;
+ FOR_ALL_GROUPS(g) {
+ if (g->owner != company) continue;
+ g->statistics.ClearAutoreplace();
+ }
+
+ for (EngineRenewList erl = c->engine_renew_list; erl != NULL; erl = erl->next) {
+ const Engine *e = Engine::Get(erl->from);
+ GroupStatistics &stats = GroupStatistics::Get(company, erl->group_id, e->type);
+ if (!stats.autoreplace_defined) {
+ stats.autoreplace_defined = true;
+ stats.autoreplace_finished = true;
+ }
+ if (stats.num_engines[erl->from] > 0) stats.autoreplace_finished = false;
+ }
}
/**
@@ -245,25 +248,25 @@ void GroupStatistics::Clear()
*/
static inline void UpdateNumEngineGroup(const Vehicle *v, GroupID old_g, GroupID new_g)
{
- if (old_g != new_g) {
- /* Decrease the num engines in the old group */
- GroupStatistics::Get(v->owner, old_g, v->type).num_engines[v->engine_type]--;
+ if (old_g != new_g) {
+ /* Decrease the num engines in the old group */
+ GroupStatistics::Get(v->owner, old_g, v->type).num_engines[v->engine_type]--;
- /* Increase the num engines in the new group */
- GroupStatistics::Get(v->owner, new_g, v->type).num_engines[v->engine_type]++;
- }
+ /* Increase the num engines in the new group */
+ GroupStatistics::Get(v->owner, new_g, v->type).num_engines[v->engine_type]++;
+ }
}
Group::Group(Owner owner)
{
- this->owner = owner;
+ this->owner = owner;
}
Group::~Group()
{
- free(this->name);
+ free(this->name);
}
@@ -278,23 +281,23 @@ Group::~Group()
*/
CommandCost CmdCreateGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
- VehicleType vt = Extract<VehicleType, 0, 3>(p1);
- if (!IsCompanyBuildableVehicleType(vt)) return CMD_ERROR;
+ VehicleType vt = Extract<VehicleType, 0, 3>(p1);
+ if (!IsCompanyBuildableVehicleType(vt)) return CMD_ERROR;
- if (!Group::CanAllocateItem()) return CMD_ERROR;
+ if (!Group::CanAllocateItem()) return CMD_ERROR;
- if (flags & DC_EXEC) {
- Group *g = new Group(_current_company);
- g->replace_protection = false;
- g->vehicle_type = vt;
- g->parent = INVALID_GROUP;
+ if (flags & DC_EXEC) {
+ Group *g = new Group(_current_company);
+ g->replace_protection = false;
+ g->vehicle_type = vt;
+ g->parent = INVALID_GROUP;
- _new_group_id = g->index;
+ _new_group_id = g->index;
- InvalidateWindowData(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_GROUP_LIST, vt, _current_company).Pack());
- }
+ InvalidateWindowData(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_GROUP_LIST, vt, _current_company).Pack());
+ }
- return CommandCost();
+ return CommandCost();
}
@@ -310,56 +313,61 @@ CommandCost CmdCreateGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
*/
CommandCost CmdDeleteGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
- Group *g = Group::GetIfValid(p1);
- if (g == NULL || g->owner != _current_company) return CMD_ERROR;
+ Group *g = Group::GetIfValid(p1);
+ if (g == NULL || g->owner != _current_company) return CMD_ERROR;
- /* Remove all vehicles from the group */
- DoCommand(0, p1, 0, flags, CMD_REMOVE_ALL_VEHICLES_GROUP);
+ /* Remove all vehicles from the group */
+ DoCommand(0, p1, 0, flags, CMD_REMOVE_ALL_VEHICLES_GROUP);
- /* Delete sub-groups */
- Group *gp;
- FOR_ALL_GROUPS(gp) {
- if (gp->parent == g->index) {
- DoCommand(0, gp->index, 0, flags, CMD_DELETE_GROUP);
- }
- }
+ /* Delete sub-groups */
+ Group *gp;
+ FOR_ALL_GROUPS(gp) {
+ if (gp->parent == g->index) {
+ DoCommand(0, gp->index, 0, flags, CMD_DELETE_GROUP);
+ }
+ }
- if (flags & DC_EXEC) {
- /* Update backupped orders if needed */
- OrderBackup::ClearGroup(g->index);
+ if (flags & DC_EXEC) {
+ /* Update backupped orders if needed */
+ OrderBackup::ClearGroup(g->index);
- /* If we set an autoreplace for the group we delete, remove it. */
- if (_current_company < MAX_COMPANIES) {
- Company *c;
- EngineRenew *er;
+ /* If we set an autoreplace for the group we delete, remove it. */
+ if (_current_company < MAX_COMPANIES) {
+ Company *c;
+ EngineRenew *er;
- c = Company::Get(_current_company);
- FOR_ALL_ENGINE_RENEWS(er) {
- if (er->group_id == g->index) RemoveEngineReplacementForCompany(c, er->from, g->index, flags);
- }
- }
+ c = Company::Get(_current_company);
+ FOR_ALL_ENGINE_RENEWS(er) {
+ if (er->group_id == g->index) RemoveEngineReplacementForCompany(c, er->from, g->index, flags);
+ }
+ }
- VehicleType vt = g->vehicle_type;
+ VehicleType vt = g->vehicle_type;
- /* Delete the Replace Vehicle Windows */
- DeleteWindowById(WC_REPLACE_VEHICLE, g->vehicle_type);
- delete g;
+ /* Delete the Replace Vehicle Windows */
+ DeleteWindowById(WC_REPLACE_VEHICLE, g->vehicle_type);
+ delete g;
- InvalidateWindowData(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_GROUP_LIST, vt, _current_company).Pack());
- }
+ InvalidateWindowData(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_GROUP_LIST, vt, _current_company).Pack());
+ }
- return CommandCost();
+ return CommandCost();
}
-static bool IsUniqueGroupNameForVehicleType(const char *name, VehicleType type)
+static const Group *GetGroup(const char *name, VehicleType type)
{
- const Group *g;
-
- FOR_ALL_GROUPS(g) {
- if (g->name != NULL && g->vehicle_type == type && strcmp(g->name, name) == 0) return false;
- }
+ const Group *g = NULL;
+ FOR_ALL_GROUPS(g) {
+ if (g->name != NULL && g->vehicle_type == type && strcmp(g->name, name) == 0) break;
+ }
+ return g;
+}
- return true;
+static bool IsUniqueGroupNameForVehicleType(const char *name, VehicleType type)
+{
+ const Group *g = GetGroup(name, type);
+ if (g) return false;
+ return true;
}
/**
@@ -376,48 +384,48 @@ static bool IsUniqueGroupNameForVehicleType(const char *name, VehicleType type)
*/
CommandCost CmdAlterGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
- Group *g = Group::GetIfValid(GB(p1, 0, 16));
- if (g == NULL || g->owner != _current_company) return CMD_ERROR;
-
- if (!HasBit(p1, 16)) {
- /* Rename group */
- bool reset = StrEmpty(text);
-
- if (!reset) {
- if (Utf8StringLength(text) >= MAX_LENGTH_GROUP_NAME_CHARS) return CMD_ERROR;
- if (!IsUniqueGroupNameForVehicleType(text, g->vehicle_type)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
- }
-
- if (flags & DC_EXEC) {
- /* Delete the old name */
- free(g->name);
- /* Assign the new one */
- g->name = reset ? NULL : stredup(text);
- }
- } else {
- /* Set group parent */
- const Group *pg = Group::GetIfValid(GB(p2, 0, 16));
-
- if (pg != NULL) {
- if (pg->owner != _current_company) return CMD_ERROR;
- if (pg->vehicle_type != g->vehicle_type) return CMD_ERROR;
-
- /* Ensure request parent isn't child of group.
- * This is the only place that infinite loops are prevented. */
- if (GroupIsInGroup(pg->index, g->index)) return CMD_ERROR;
- }
-
- if (flags & DC_EXEC) {
- g->parent = (pg == NULL) ? INVALID_GROUP : pg->index;
- }
- }
-
- if (flags & DC_EXEC) {
- SetWindowDirty(WC_REPLACE_VEHICLE, g->vehicle_type);
- InvalidateWindowData(GetWindowClassForVehicleType(g->vehicle_type), VehicleListIdentifier(VL_GROUP_LIST, g->vehicle_type, _current_company).Pack());
- }
-
- return CommandCost();
+ Group *g = Group::GetIfValid(GB(p1, 0, 16));
+ if (g == NULL || g->owner != _current_company) return CMD_ERROR;
+
+ if (!HasBit(p1, 16)) {
+ /* Rename group */
+ bool reset = StrEmpty(text);
+
+ if (!reset) {
+ if (Utf8StringLength(text) >= MAX_LENGTH_GROUP_NAME_CHARS) return CMD_ERROR;
+ if (!IsUniqueGroupNameForVehicleType(text, g->vehicle_type)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
+ }
+
+ if (flags & DC_EXEC) {
+ /* Delete the old name */
+ free(g->name);
+ /* Assign the new one */
+ g->name = reset ? NULL : stredup(text);
+ }
+ } else {
+ /* Set group parent */
+ const Group *pg = Group::GetIfValid(GB(p2, 0, 16));
+
+ if (pg != NULL) {
+ if (pg->owner != _current_company) return CMD_ERROR;
+ if (pg->vehicle_type != g->vehicle_type) return CMD_ERROR;
+
+ /* Ensure request parent isn't child of group.
+ * This is the only place that infinite loops are prevented. */
+ if (GroupIsInGroup(pg->index, g->index)) return CMD_ERROR;
+ }
+
+ if (flags & DC_EXEC) {
+ g->parent = (pg == NULL) ? INVALID_GROUP : pg->index;
+ }
+ }
+
+ if (flags & DC_EXEC) {
+ SetWindowDirty(WC_REPLACE_VEHICLE, g->vehicle_type);
+ InvalidateWindowData(GetWindowClassForVehicleType(g->vehicle_type), VehicleListIdentifier(VL_GROUP_LIST, g->vehicle_type, _current_company).Pack());
+ }
+
+ return CommandCost();
}
@@ -428,23 +436,23 @@ CommandCost CmdAlterGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
*/
static void AddVehicleToGroup(Vehicle *v, GroupID new_g)
{
- GroupStatistics::CountVehicle(v, -1);
-
- switch (v->type) {
- default: NOT_REACHED();
- case VEH_TRAIN:
- SetTrainGroupID(Train::From(v), new_g);
- break;
-
- case VEH_ROAD:
- case VEH_SHIP:
- case VEH_AIRCRAFT:
- if (v->IsEngineCountable()) UpdateNumEngineGroup(v, v->group_id, new_g);
- v->group_id = new_g;
- break;
- }
-
- GroupStatistics::CountVehicle(v, 1);
+ GroupStatistics::CountVehicle(v, -1);
+
+ switch (v->type) {
+ default: NOT_REACHED();
+ case VEH_TRAIN:
+ SetTrainGroupID(Train::From(v), new_g);
+ break;
+
+ case VEH_ROAD:
+ case VEH_SHIP:
+ case VEH_AIRCRAFT:
+ if (v->IsEngineCountable()) UpdateNumEngineGroup(v, v->group_id, new_g);
+ v->group_id = new_g;
+ break;
+ }
+
+ GroupStatistics::CountVehicle(v, 1);
}
/**
@@ -461,82 +469,299 @@ static void AddVehicleToGroup(Vehicle *v, GroupID new_g)
*/
CommandCost CmdAddVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
- Vehicle *v = Vehicle::GetIfValid(GB(p2, 0, 20));
- GroupID new_g = p1;
+ Vehicle *v = Vehicle::GetIfValid(GB(p2, 0, 20));
+ GroupID new_g = p1;
+
+ if (v == NULL || (!Group::IsValidID(new_g) && !IsDefaultGroupID(new_g) && new_g != NEW_GROUP)) return CMD_ERROR;
- if (v == NULL || (!Group::IsValidID(new_g) && !IsDefaultGroupID(new_g) && new_g != NEW_GROUP)) return CMD_ERROR;
+ if (Group::IsValidID(new_g)) {
+ Group *g = Group::Get(new_g);
+ if (g->owner != _current_company || g->vehicle_type != v->type) return CMD_ERROR;
+ }
- if (Group::IsValidID(new_g)) {
- Group *g = Group::Get(new_g);
- if (g->owner != _current_company || g->vehicle_type != v->type) return CMD_ERROR;
- }
+ if (v->owner != _current_company || !v->IsPrimaryVehicle()) return CMD_ERROR;
- if (v->owner != _current_company || !v->IsPrimaryVehicle()) return CMD_ERROR;
+ if (new_g == NEW_GROUP) {
+ /* Create new group. */
+ CommandCost ret = CmdCreateGroup(0, flags, v->type, 0, NULL);
+ if (ret.Failed()) return ret;
- if (new_g == NEW_GROUP) {
- /* Create new group. */
- CommandCost ret = CmdCreateGroup(0, flags, v->type, 0, NULL);
- if (ret.Failed()) return ret;
+ new_g = _new_group_id;
+ }
- new_g = _new_group_id;
- }
+ if (flags & DC_EXEC) {
+ AddVehicleToGroup(v, new_g);
- if (flags & DC_EXEC) {
- AddVehicleToGroup(v, new_g);
+ if (HasBit(p2, 31)) {
+ /* Add vehicles in the shared order list as well. */
+ for (Vehicle *v2 = v->FirstShared(); v2 != NULL; v2 = v2->NextShared()) {
+ if (v2->group_id != new_g) AddVehicleToGroup(v2, new_g);
+ }
+ }
- if (HasBit(p2, 31)) {
- /* Add vehicles in the shared order list as well. */
- for (Vehicle *v2 = v->FirstShared(); v2 != NULL; v2 = v2->NextShared()) {
- if (v2->group_id != new_g) AddVehicleToGroup(v2, new_g);
- }
- }
+ GroupStatistics::UpdateAutoreplace(v->owner);
- GroupStatistics::UpdateAutoreplace(v->owner);
+ /* Update the Replace Vehicle Windows */
+ SetWindowDirty(WC_REPLACE_VEHICLE, v->type);
+ InvalidateWindowData(GetWindowClassForVehicleType(v->type), VehicleListIdentifier(VL_GROUP_LIST, v->type, _current_company).Pack());
+ }
- /* Update the Replace Vehicle Windows */
- SetWindowDirty(WC_REPLACE_VEHICLE, v->type);
- InvalidateWindowData(GetWindowClassForVehicleType(v->type), VehicleListIdentifier(VL_GROUP_LIST, v->type, _current_company).Pack());
- }
+ return CommandCost();
+}
- return CommandCost();
+static uint8 GroupSpecificName(Vehicle *v, char *str, char *str_last)
+{
+ /* Find first and last order */
+ Order *first = NULL;
+ Order *last = NULL;
+ {
+ typedef SmallVector<DestinationID,8> DestVec;
+ struct Data {
+ DestVec dests;
+ Order *order;
+ size_t count;
+ };
+ typedef SmallMap<DestinationID,Data> StationMap;
+
+ VehicleOrderID start = 0;
+ Order *order, *next;
+ DestinationID dest, ndest;
+ StationMap map = StationMap();
+ StationMap::iterator iter;
+ Data *f = NULL, *l = NULL, *d;
+ char looped = 0;
+
+ // Construct map of stations
+ for (order = v->GetOrder(start); order != NULL; order = order->next) {
+ if (order->IsType(OT_GOTO_STATION)) {
+ dest = order->GetDestination();
+ if (!map.Contains(dest)) {
+ DestVec ds = DestVec();
+ Data dat = { ds, order, 0};
+ memcpy(&map[dest], &dat, sizeof(Data));
+ }
+
+ for (next = order->next; !looped || next != NULL; next = next->next) {
+ if (next == NULL) next = v->GetOrder(start);
+
+ if (next->IsType(OT_GOTO_STATION)) {
+ ndest = next->GetDestination();
+ if (dest != ndest && !map[dest].dests.Contains(ndest)) {
+ map[dest].dests.Include(ndest);
+ map[dest].count++;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // Find first / last
+ for (iter = map.Begin(); iter != map.End(); iter++) {
+ d = &iter->second;
+ if (f == NULL) f = d;
+ else if (d->count < f->count) { l = f; f = d; }
+ else if (l == NULL) l = d;
+ else if (d->count < l->count) l = d;
+ }
+ if (f != NULL) first = f->order;
+ if (l != NULL) last = l->order;
+ }
+ if(last == NULL || first == NULL) return 1;
+
+ /* Find max lengths */
+ size_t str_len, sep_len;
+ {
+ static char sep_str[MAX_LENGTH_GROUP_NAME_CHARS] = { "" };
+ static char empty[1] = "";
+ SetDParamStr(0, empty);
+ SetDParamStr(1, empty);
+ GetString(sep_str, STR_GROUP_SPECIFIC_NAME_STATION, lastof(sep_str));
+ sep_len = strlen(sep_str);
+ str_len = max(MAX_LENGTH_STATION_NAME_CHARS,MAX_LENGTH_TOWN_NAME_CHARS) * 2 + sep_len;
+ }
+
+ /* Create group name */
+ if(_settings_client.gui.specific_group_name == 1) { // Use station names
+ static char stationname_first[MAX_LENGTH_STATION_NAME_CHARS+2] = { "" };
+ static char stationname_last[MAX_LENGTH_STATION_NAME_CHARS+2] = { "" };
+
+ /* Get station names */
+ SetDParam(0, first->GetDestination());
+ GetString(stationname_first, STR_STATION_NAME, lastof(stationname_first));
+ SetDParam(0, last->GetDestination());
+ GetString(stationname_last, STR_STATION_NAME, lastof(stationname_last));
+
+ /* Find greatest common prefix (that ends with a space) */
+ size_t prefix;
+ {
+ for (prefix = 0; stationname_first[prefix] != '\0' && stationname_last[prefix] != '\0' && stationname_first[prefix] == stationname_last[prefix]; prefix++);
+ if (stationname_first[prefix] == '\0' && stationname_last[prefix] == ' ') {
+ stationname_first[prefix] = ' ';
+ prefix++;
+ stationname_first[prefix] = '\0';
+ }
+ else if (stationname_last[prefix] == '\0' && stationname_first[prefix] == ' ') {
+ stationname_last[prefix] = ' ';
+ prefix++;
+ stationname_last[prefix] = '\0';
+ }
+ while (prefix > 0 && stationname_first[prefix-1] != ' ') prefix--;
+ }
+
+ /* Truncate */
+ {
+ int diff = Utf8StringLength(stationname_first) + sep_len + Utf8StringLength(stationname_last) - prefix - MAX_LENGTH_GROUP_NAME_CHARS + 1;
+ if ( diff > 0 ) {
+ diff = (diff+1)/2;
+ Utf8TrimString(stationname_first, Utf8StringLength(stationname_first)-diff);
+ Utf8TrimString(stationname_last, Utf8StringLength(stationname_last)-diff);
+ }
+
+ /* Remove white endings */
+ int i;
+ for (i = 0; stationname_first[i] != '\0'; i++); i--;
+ while (stationname_first[i] == ' ') { stationname_first[i] = '\0'; i--; }
+ for (i = 0; stationname_last[i] != '\0'; i++); i--;
+ while (stationname_last[i] == ' ') { stationname_last[i] = '\0'; i--; }
+ }
+
+ /* Create name (Sorted) */
+ if(strnatcmp(stationname_first, stationname_last) > 0) {
+ SetDParamStr(0, stationname_last);
+ SetDParamStr(1, &stationname_first[prefix]);
+ } else {
+ SetDParamStr(0, stationname_first);
+ SetDParamStr(1, &stationname_last[prefix]);
+ }
+ GetString(str, STR_GROUP_SPECIFIC_NAME_STATION, str_last);
+
+ } else { // Use town names
+
+ Station *station_first = Station::GetIfValid(first->GetDestination());
+ Station *station_last = Station::GetIfValid(last->GetDestination());
+
+ if(station_last->IsValidID == false || station_first->IsValidID == false) return 1;
+
+ Town *town_first = station_first->town;
+ Town *town_last = station_last->town;
+
+ if(town_first->index == town_last->index) { // First and last station belong to the same town
+ SetDParam(0, town_first->index);
+ GetString(str, STR_GROUP_SPECIFIC_NAME_TOWN_LOCAL, str_last);
+ } else {
+ static char townname_first[64] = { "" };
+ static char townname_last[64] = { "" };
+
+ SetDParam(0, town_first->index);
+ GetString(townname_first, STR_TOWN_NAME, lastof(townname_first));
+
+ SetDParam(0, town_last->index);
+ GetString(townname_last, STR_TOWN_NAME, lastof(townname_last));
+
+ if(strnatcmp(townname_first, townname_last) > 0) { // Sort by name
+ Town *town_temp = town_first;
+ town_first = town_last;
+ town_last = town_temp;
+ }
+
+ SetDParam(0, town_first->index);
+ SetDParam(1, town_last->index );
+ GetString(str, STR_GROUP_SPECIFIC_NAME_TOWN, str_last);
+ }
+ }
+
+ return 0;
}
/**
- * Add all shared vehicles of all vehicles from a group
+ * Create a new group, rename it with specific name and add vehicle to this group
* @param tile unused
* @param flags type of operation
- * @param p1 index of group array
- * - p1 bit 0-15 : GroupID
- * @param p2 type of vehicles
+ * @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 CmdAddSharedVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
+CommandCost CmdCreateGroupSpecificName(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
- VehicleType type = Extract<VehicleType, 0, 3>(p2);
- GroupID id_g = p1;
- if (!Group::IsValidID(id_g) || !IsCompanyBuildableVehicleType(type)) return CMD_ERROR;
+ Vehicle *v = Vehicle::GetIfValid(GB(p1, 0, 20));
+
+ /* Preconditions */
+ if (v == NULL) return CMD_ERROR;
+ if (v->owner != _current_company || !v->IsPrimaryVehicle()) return CMD_ERROR;
+
+ char str[MAX_LENGTH_GROUP_NAME_CHARS+1] = { "" };
+ if (GroupSpecificName(v, str, lastof(str))) return_cmd_error(STR_ERROR_GROUP_CAN_T_CREATE_NAME);
- if (flags & DC_EXEC) {
- Vehicle *v;
+ /* Check group name */
+ if (!IsUniqueGroupNameForVehicleType(str, v->type)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
+ if (Utf8StringLength(str) >= MAX_LENGTH_GROUP_NAME_CHARS) return CMD_ERROR;
- /* Find the first front engine which belong to the group id_g
- * then add all shared vehicles of this front engine to the group id_g */
- FOR_ALL_VEHICLES(v) {
- if (v->type == type && v->IsPrimaryVehicle()) {
- if (v->group_id != id_g) continue;
+ /* Create group and set name */
+ CommandCost ret = CmdCreateGroup(0, flags, v->type, 0, NULL);
+ if (ret.Failed()) return ret;
+ GroupID new_g = _new_group_id;
+ CmdAlterGroup(0, flags, new_g, 0, str);
- /* For each shared vehicles add it to the group */
- for (Vehicle *v2 = v->FirstShared(); v2 != NULL; v2 = v2->NextShared()) {
- if (v2->group_id != id_g) DoCommand(tile, id_g, v2->index, flags, CMD_ADD_VEHICLE_GROUP, text);
- }
- }
- }
+ /* If execute flag is set, add vehicles to groups */
+ if (flags & DC_EXEC) {
+ AddVehicleToGroup(v, new_g);
- InvalidateWindowData(GetWindowClassForVehicleType(type), VehicleListIdentifier(VL_GROUP_LIST, type, _current_company).Pack());
- }
+ if (HasBit(p1, 31)) { // Add vehicles in the shared order list as well.
+ for (Vehicle *v2 = v->FirstShared(); v2 != NULL; v2 = v2->NextShared()) {
+ if (v2->group_id != new_g) AddVehicleToGroup(v2, new_g);
+ }
+ }
- return CommandCost();
+ GroupStatistics::UpdateAutoreplace(v->owner);
+
+ /* Update the Replace Vehicle Windows */
+ SetWindowDirty(WC_REPLACE_VEHICLE, v->type);
+ InvalidateWindowData(GetWindowClassForVehicleType(v->type), VehicleListIdentifier(VL_GROUP_LIST, v->type, _current_company).Pack());
+ }
+
+ return CommandCost();
+}
+
+/**
+ * Add all shared vehicles of all vehicles from a group
+ * @param tile unused
+ * @param flags type of operation
+ * @param p1 index of group array
+ * - p1 bit 0-15 : GroupID
+ * @param p2 type of vehicles
+ * @param text unused
+ * @return the cost of this operation or an error
+ */
+CommandCost CmdAddSharedVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
+{
+ VehicleType type = Extract<VehicleType, 0, 3>(p2);
+ GroupID id_g = p1;
+ if (!Group::IsValidID(id_g) || !IsCompanyBuildableVehicleType(type)) return CMD_ERROR;
+
+ if (flags & DC_EXEC) {
+ Vehicle *v;
+
+ /* Find the first front engine which belong to the group id_g
+ * then add all shared vehicles of this front engine to the group id_g */
+ FOR_ALL_VEHICLES(v) {
+ if (v->type == type && v->IsPrimaryVehicle()) {
+ if (v->group_id != id_g) continue;
+
+ /* For each shared vehicles add it to the group */
+ for (Vehicle *v2 = v->FirstShared(); v2 != NULL; v2 = v2->NextShared()) {
+ if (v2->group_id != id_g) DoCommand(tile, id_g, v2->index, flags, CMD_ADD_VEHICLE_GROUP, text);
+ }
+ }
+ }
+
+ InvalidateWindowData(GetWindowClassForVehicleType(type), VehicleListIdentifier(VL_GROUP_LIST, type, _current_company).Pack());
+ }
+
+ return CommandCost();
}
@@ -552,28 +777,82 @@ CommandCost CmdAddSharedVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32
*/
CommandCost CmdRemoveAllVehiclesGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
- GroupID old_g = p1;
- Group *g = Group::GetIfValid(old_g);
+ GroupID old_g = p1;
+ Group *g = Group::GetIfValid(old_g);
- if (g == NULL || g->owner != _current_company) return CMD_ERROR;
+ if (g == NULL || g->owner != _current_company) return CMD_ERROR;
- if (flags & DC_EXEC) {
- Vehicle *v;
+ if (flags & DC_EXEC) {
+ Vehicle *v;
- /* Find each Vehicle that belongs to the group old_g and add it to the default group */
- FOR_ALL_VEHICLES(v) {
- if (v->IsPrimaryVehicle()) {
- if (v->group_id != old_g) continue;
+ /* Find each Vehicle that belongs to the group old_g and add it to the default group */
+ FOR_ALL_VEHICLES(v) {
+ if (v->IsPrimaryVehicle()) {
+ if (v->group_id != old_g) continue;
- /* Add The Vehicle to the default group */
- DoCommand(tile, DEFAULT_GROUP, v->index, flags, CMD_ADD_VEHICLE_GROUP, text);
- }
- }
+ /* Add The Vehicle to the default group */
+ DoCommand(tile, DEFAULT_GROUP, v->index, flags, CMD_ADD_VEHICLE_GROUP, text);
+ }
+ }
- InvalidateWindowData(GetWindowClassForVehicleType(g->vehicle_type), VehicleListIdentifier(VL_GROUP_LIST, g->vehicle_type, _current_company).Pack());
- }
+ InvalidateWindowData(GetWindowClassForVehicleType(g->vehicle_type), VehicleListIdentifier(VL_GROUP_LIST, g->vehicle_type, _current_company).Pack());
+ }
- return CommandCost();
+ return CommandCost();
+}
+
+CommandCost CmdAutoGroupVehiclesGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
+{
+ VehicleType type = Extract<VehicleType, 0, 3>(p2);
+ GroupID old_g_id = p1;
+ Group *old_g = Group::GetIfValid(old_g_id);
+
+ if (old_g_id != ALL_GROUP && old_g_id != DEFAULT_GROUP && (old_g == NULL || old_g->owner != _current_company)) return CMD_ERROR;
+
+ if (flags & DC_EXEC) {
+ Vehicle *v;
+
+ /* Find each Vehicle that belongs to the group old_g and add it to the default group */
+ FOR_ALL_VEHICLES(v) {
+ if (v->type == type && v->IsPrimaryVehicle()) {
+ if (old_g_id != ALL_GROUP && v->group_id != old_g_id) continue;
+
+ /* Create name */
+ char str[MAX_LENGTH_GROUP_NAME_CHARS+1] = { "" };
+ if (!GroupSpecificName(v, str, lastof(str))) {
+ /* Get group */
+ const Group *new_g = GetGroup(str, v->type);
+
+ /* Check group name */
+ GroupID new_g_id;
+ if (new_g == NULL) {
+ if (Utf8StringLength(str) >= MAX_LENGTH_GROUP_NAME_CHARS) return CMD_ERROR;
+
+ /* Create group and set name */
+ CommandCost ret = CmdCreateGroup(0, flags, v->type, 0, NULL);
+ if (ret.Failed()) return ret;
+ new_g_id = _new_group_id;
+ CmdAlterGroup(0, flags, new_g_id, 0, str);
+ } else {
+ new_g_id = new_g->index;
+ }
+
+ /* Add vehicle to group */
+ AddVehicleToGroup(v, new_g_id);
+
+ GroupStatistics::UpdateAutoreplace(v->owner);
+ } else {
+ // TODO How to handle errors ?
+ }
+ }
+ }
+
+ /* Update the Replace Vehicle Windows */
+ SetWindowDirty(WC_REPLACE_VEHICLE, type);
+ InvalidateWindowData(GetWindowClassForVehicleType(type), VehicleListIdentifier(VL_GROUP_LIST, type, _current_company).Pack());
+ }
+
+ return CommandCost();
}
/**
@@ -583,12 +862,12 @@ CommandCost CmdRemoveAllVehiclesGroup(TileIndex tile, DoCommandFlag flags, uint3
*/
static void SetGroupReplaceProtection(Group *g, bool protect)
{
- g->replace_protection = protect;
+ g->replace_protection = protect;
- Group *pg;
- FOR_ALL_GROUPS(pg) {
- if (pg->parent == g->index) SetGroupReplaceProtection(pg, protect);
- }
+ Group *pg;
+ FOR_ALL_GROUPS(pg) {
+ if (pg->parent == g->index) SetGroupReplaceProtection(pg, protect);
+ }
}
/**
@@ -605,21 +884,21 @@ static void SetGroupReplaceProtection(Group *g, bool protect)
*/
CommandCost CmdSetGroupReplaceProtection(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
- Group *g = Group::GetIfValid(p1);
- if (g == NULL || g->owner != _current_company) return CMD_ERROR;
+ Group *g = Group::GetIfValid(p1);
+ if (g == NULL || g->owner != _current_company) return CMD_ERROR;
- if (flags & DC_EXEC) {
- if (HasBit(p2, 1)) {
- SetGroupReplaceProtection(g, HasBit(p2, 0));
- } else {
- g->replace_protection = HasBit(p2, 0);
- }
+ if (flags & DC_EXEC) {
+ if (HasBit(p2, 1)) {
+ SetGroupReplaceProtection(g, HasBit(p2, 0));
+ } else {
+ g->replace_protection = HasBit(p2, 0);
+ }
- SetWindowDirty(GetWindowClassForVehicleType(g->vehicle_type), VehicleListIdentifier(VL_GROUP_LIST, g->vehicle_type, _current_company).Pack());
- InvalidateWindowData(WC_REPLACE_VEHICLE, g->vehicle_type);
- }
+ SetWindowDirty(GetWindowClassForVehicleType(g->vehicle_type), VehicleListIdentifier(VL_GROUP_LIST, g->vehicle_type, _current_company).Pack());
+ InvalidateWindowData(WC_REPLACE_VEHICLE, g->vehicle_type);
+ }
- return CommandCost();
+ return CommandCost();
}
/**
@@ -629,9 +908,9 @@ CommandCost CmdSetGroupReplaceProtection(TileIndex tile, DoCommandFlag flags, ui
*/
void RemoveVehicleFromGroup(const Vehicle *v)
{
- if (!v->IsPrimaryVehicle()) return;
+ if (!v->IsPrimaryVehicle()) return;
- if (!IsDefaultGroupID(v->group_id)) GroupStatistics::CountVehicle(v, -1);
+ if (!IsDefaultGroupID(v->group_id)) GroupStatistics::CountVehicle(v, -1);
}
@@ -643,19 +922,19 @@ void RemoveVehicleFromGroup(const Vehicle *v)
*/
void SetTrainGroupID(Train *v, GroupID new_g)
{
- if (!Group::IsValidID(new_g) && !IsDefaultGroupID(new_g)) return;
+ if (!Group::IsValidID(new_g) && !IsDefaultGroupID(new_g)) return;
- assert(v->IsFrontEngine() || IsDefaultGroupID(new_g));
+ assert(v->IsFrontEngine() || IsDefaultGroupID(new_g));
- for (Vehicle *u = v; u != NULL; u = u->Next()) {
- if (u->IsEngineCountable()) UpdateNumEngineGroup(u, u->group_id, new_g);
+ for (Vehicle *u = v; u != NULL; u = u->Next()) {
+ if (u->IsEngineCountable()) UpdateNumEngineGroup(u, u->group_id, new_g);
- u->group_id = new_g;
- }
+ u->group_id = new_g;
+ }
- /* Update the Replace Vehicle Windows */
- GroupStatistics::UpdateAutoreplace(v->owner);
- SetWindowDirty(WC_REPLACE_VEHICLE, VEH_TRAIN);
+ /* Update the Replace Vehicle Windows */
+ GroupStatistics::UpdateAutoreplace(v->owner);
+ SetWindowDirty(WC_REPLACE_VEHICLE, VEH_TRAIN);
}
@@ -668,18 +947,18 @@ void SetTrainGroupID(Train *v, GroupID new_g)
*/
void UpdateTrainGroupID(Train *v)
{
- assert(v->IsFrontEngine() || v->IsFreeWagon());
+ assert(v->IsFrontEngine() || v->IsFreeWagon());
- GroupID new_g = v->IsFrontEngine() ? v->group_id : (GroupID)DEFAULT_GROUP;
- for (Vehicle *u = v; u != NULL; u = u->Next()) {
- if (u->IsEngineCountable()) UpdateNumEngineGroup(u, u->group_id, new_g);
+ GroupID new_g = v->IsFrontEngine() ? v->group_id : (GroupID)DEFAULT_GROUP;
+ for (Vehicle *u = v; u != NULL; u = u->Next()) {
+ if (u->IsEngineCountable()) UpdateNumEngineGroup(u, u->group_id, new_g);
- u->group_id = new_g;
- }
+ u->group_id = new_g;
+ }
- /* Update the Replace Vehicle Windows */
- GroupStatistics::UpdateAutoreplace(v->owner);
- SetWindowDirty(WC_REPLACE_VEHICLE, VEH_TRAIN);
+ /* Update the Replace Vehicle Windows */
+ GroupStatistics::UpdateAutoreplace(v->owner);
+ SetWindowDirty(WC_REPLACE_VEHICLE, VEH_TRAIN);
}
/**
@@ -692,22 +971,22 @@ void UpdateTrainGroupID(Train *v)
*/
uint GetGroupNumEngines(CompanyID company, GroupID id_g, EngineID id_e)
{
- uint count = 0;
- const Engine *e = Engine::Get(id_e);
- const Group *g;
- FOR_ALL_GROUPS(g) {
- if (g->parent == id_g) count += GetGroupNumEngines(company, g->index, id_e);
- }
- return count + GroupStatistics::Get(company, id_g, e->type).num_engines[id_e];
+ uint count = 0;
+ const Engine *e = Engine::Get(id_e);
+ const Group *g;
+ FOR_ALL_GROUPS(g) {
+ if (g->parent == id_g) count += GetGroupNumEngines(company, g->index, id_e);
+ }
+ return count + GroupStatistics::Get(company, id_g, e->type).num_engines[id_e];
}
void RemoveAllGroupsForCompany(const CompanyID company)
{
- Group *g;
+ Group *g;
- FOR_ALL_GROUPS(g) {
- if (company == g->owner) delete g;
- }
+ FOR_ALL_GROUPS(g) {
+ if (company == g->owner) delete g;
+ }
}
@@ -719,12 +998,12 @@ void RemoveAllGroupsForCompany(const CompanyID company)
*/
bool GroupIsInGroup(GroupID search, GroupID group)
{
- if (!Group::IsValidID(search)) return search == group;
+ if (!Group::IsValidID(search)) return search == group;
- do {
- if (search == group) return true;
- search = Group::Get(search)->parent;
- } while (search != INVALID_GROUP);
+ do {
+ if (search == group) return true;
+ search = Group::Get(search)->parent;
+ } while (search != INVALID_GROUP);
- return false;
+ return false;
}
diff --git a/src/group_gui.cpp b/src/group_gui.cpp
index 361ab53..b1a9a9e 100644
--- a/src/group_gui.cpp
+++ b/src/group_gui.cpp
@@ -748,8 +748,18 @@ 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_SPECIFIC_NAME | CMD_MSG(STR_ERROR_GROUP_CAN_T_CREATE_SPECIFIC_NAME), NULL);
+
+ break;
}
}
+ }
virtual void OnDragDrop(Point pt, int widget)
{
@@ -801,6 +811,9 @@ public:
DoCommandP(0, this->vli.index, 0, CMD_REMOVE_ALL_VEHICLES_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_REMOVE_ALL_VEHICLES));
break;
+ case ADI_AUTO_GROUP: // Automatically group all vehicles
+ DoCommandP(0, this->vli.index, this->vli.vtype, CMD_AUTO_GROUP_VEHICLES_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_AUTO_GROUP_VEHICLES));
+ break;
default: NOT_REACHED();
}
break;
diff --git a/src/lang/english.txt b/src/lang/english.txt
index 0b8406e..7dc0b2d 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -1213,6 +1213,10 @@ STR_CONFIG_SETTING_SIGNALSIDE_DRIVING_SIDE :On the driving
STR_CONFIG_SETTING_SIGNALSIDE_RIGHT :On the right
STR_CONFIG_SETTING_SHOWFINANCES :Show finances window at the end of the year: {STRING2}
STR_CONFIG_SETTING_SHOWFINANCES_HELPTEXT :If enabled, the finances window pops up at the end of each year to allow easy inspection of the financial status of the company
+STR_CONFIG_SETTING_SPECIFIC_GROUP_NAME :Use {STRING2} names for specific group name
+STR_CONFIG_SETTING_SPECIFIC_GROUP_NAME_HELPTEXT :Uses the selected name from the first and last order of a vehicle to create a specific group name
+STR_CONFIG_SETTING_SPECIFIC_GROUP_NAME_TOWN :town
+STR_CONFIG_SETTING_SPECIFIC_GROUP_NAME_STATION :station
STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT :New orders are 'non-stop' by default: {STRING2}
STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT_HELPTEXT :Normally, a vehicle will stop at every station it passes. By enabling this setting, it will drive through all station on the way to its final destination without stopping. Note, that this setting only defines a default value for new orders. Individual orders can be set explicitly to either behaviour nevertheless
STR_CONFIG_SETTING_STOP_LOCATION :New train orders stop by default at the {STRING2} of the platform
@@ -3361,8 +3365,12 @@ STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Are you
STR_GROUP_ADD_SHARED_VEHICLE :Add shared vehicles
STR_GROUP_REMOVE_ALL_VEHICLES :Remove all vehicles
+STR_GROUP_AUTO_GROUP_VEHICLES :Auto group all vehicles
STR_GROUP_RENAME_CAPTION :{BLACK}Rename a group
+STR_GROUP_SPECIFIC_NAME_STATION :{RAW_STRING} - {RAW_STRING}
+STR_GROUP_SPECIFIC_NAME_TOWN :{TOWN} - {TOWN}
+STR_GROUP_SPECIFIC_NAME_TOWN_LOCAL :Local {TOWN}
# Build vehicle window
STR_BUY_VEHICLE_TRAIN_RAIL_CAPTION :New Rail Vehicles
@@ -4365,6 +4373,9 @@ STR_ERROR_GROUP_CAN_T_SET_PARENT :{WHITE}Can't se
STR_ERROR_GROUP_CAN_T_REMOVE_ALL_VEHICLES :{WHITE}Can't remove all vehicles from this group...
STR_ERROR_GROUP_CAN_T_ADD_VEHICLE :{WHITE}Can't add the vehicle to this group...
STR_ERROR_GROUP_CAN_T_ADD_SHARED_VEHICLE :{WHITE}Can't add shared vehicles to group...
+STR_ERROR_GROUP_CAN_T_AUTO_GROUP_VEHICLES :{WHITE}Can't auto group all vehicles...
+STR_ERROR_GROUP_CAN_T_CREATE_SPECIFIC_NAME :{WHITE}Can't create group with specific name...
+STR_ERROR_GROUP_CAN_T_CREATE_NAME :{WHITE}Can't create group name...
# Generic vehicle errors
STR_ERROR_TRAIN_IN_THE_WAY :{WHITE}Train in the way
diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp
index 0652d1b..e4180c9 100644
--- a/src/settings_gui.cpp
+++ b/src/settings_gui.cpp
@@ -1576,6 +1576,7 @@ static SettingsContainer &GetSettingsTree()
company->Add(new SettingEntry("gui.default_signal_type"));
company->Add(new SettingEntry("gui.cycle_signal_types"));
company->Add(new SettingEntry("gui.drag_signals_fixed_distance"));
+ company->Add(new SettingEntry("gui.specific_group_name"));
company->Add(new SettingEntry("gui.new_nonstop"));
company->Add(new SettingEntry("gui.stop_location"));
company->Add(new SettingEntry("company.engine_renew"));
diff --git a/src/settings_type.h b/src/settings_type.h
index 41366a7..91e49b1 100644
--- a/src/settings_type.h
+++ b/src/settings_type.h
@@ -78,6 +78,7 @@ struct GUISettings {
uint8 order_review_system; ///< perform order reviews on vehicles
bool vehicle_income_warn; ///< if a vehicle isn't generating income, show a warning
bool show_finances; ///< show finances at end of year
+ uint8 specific_group_name; ///< use station or town names for specific group names
bool sg_new_nonstop; ///< ttdpatch compatible nonstop handling read from pre v93 savegames
bool new_nonstop; ///< ttdpatch compatible nonstop handling
uint8 stop_location; ///< what is the default stop location of trains?
diff --git a/src/table/settings.ini b/src/table/settings.ini
index f314f21..3f2fcc4 100644
--- a/src/table/settings.ini
+++ b/src/table/settings.ini
@@ -2950,6 +2950,20 @@ strhelp = STR_CONFIG_SETTING_DISABLE_UNSUITABLE_BUILDING_HELPTEXT
proc = RedrawScreen
cat = SC_EXPERT
+[SDTC_VAR]
+var = gui.specific_group_name
+type = SLE_UINT8
+flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
+guiflags = SGF_MULTISTRING
+def = 0
+min = 0
+max = 1
+interval = 1
+str = STR_CONFIG_SETTING_SPECIFIC_GROUP_NAME
+strhelp = STR_CONFIG_SETTING_SPECIFIC_GROUP_NAME_HELPTEXT
+strval = STR_CONFIG_SETTING_SPECIFIC_GROUP_NAME_TOWN
+cat = SC_BASIC
+
[SDTC_BOOL]
var = gui.new_nonstop
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp
index 8ea8cda..bc52e31 100644
--- a/src/vehicle_gui.cpp
+++ b/src/vehicle_gui.cpp
@@ -177,6 +177,8 @@ DropDownList *BaseVehicleListWindow::BuildActionDropdownList(bool show_autorepla
*list->Append() = new DropDownListStringItem(STR_GROUP_REMOVE_ALL_VEHICLES, ADI_REMOVE_ALL, false);
}
+ *list->Append() = new DropDownListStringItem(STR_GROUP_AUTO_GROUP_VEHICLES, ADI_AUTO_GROUP, false);
+
return list;
}
diff --git a/src/vehicle_gui_base.h b/src/vehicle_gui_base.h
index 5755c7f..cf267bd 100644
--- a/src/vehicle_gui_base.h
+++ b/src/vehicle_gui_base.h
@@ -32,6 +32,7 @@ struct BaseVehicleListWindow : public Window {
ADI_DEPOT,
ADI_ADD_SHARED,
ADI_REMOVE_ALL,
+ ADI_AUTO_GROUP,
};
static const StringID vehicle_depot_name[];