summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorpeter1138 <peter1138@openttd.org>2014-04-08 21:09:06 +0000
committerpeter1138 <peter1138@openttd.org>2014-04-08 21:09:06 +0000
commit567d0ff3a7286fe830bf188c2911e3d10d70eb8c (patch)
treef61a570d4fb3a9bb1419b0eee818692686d75462 /src
parent3e9c10f9e11935a82d33fd5c66592d795c279777 (diff)
downloadopenttd-567d0ff3a7286fe830bf188c2911e3d10d70eb8c.tar.xz
(svn r26450) -Feature: Hierarchical vehicle subgroups.
Diffstat (limited to 'src')
-rw-r--r--src/autoreplace.cpp2
-rw-r--r--src/command.cpp4
-rw-r--r--src/command_type.h2
-rw-r--r--src/group.h3
-rw-r--r--src/group_cmd.cpp106
-rw-r--r--src/group_gui.cpp138
-rw-r--r--src/lang/english.txt3
-rw-r--r--src/saveload/group_sl.cpp3
-rw-r--r--src/saveload/saveload.cpp3
-rw-r--r--src/script/api/script_group.cpp2
-rw-r--r--src/vehiclelist.cpp3
11 files changed, 218 insertions, 51 deletions
diff --git a/src/autoreplace.cpp b/src/autoreplace.cpp
index 0cb8d997f..0788fccb3 100644
--- a/src/autoreplace.cpp
+++ b/src/autoreplace.cpp
@@ -28,7 +28,7 @@ static EngineRenew *GetEngineReplacement(EngineRenewList erl, EngineID engine, G
EngineRenew *er = (EngineRenew *)erl;
while (er != NULL) {
- if (er->from == engine && er->group_id == group) return er;
+ if (er->from == engine && GroupIsInGroup(group, er->group_id)) return er;
er = er->next;
}
return NULL;
diff --git a/src/command.cpp b/src/command.cpp
index 2891a06af..34d5ab61e 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -180,7 +180,7 @@ CommandProc CmdDepotSellAllVehicles;
CommandProc CmdDepotMassAutoReplace;
CommandProc CmdCreateGroup;
-CommandProc CmdRenameGroup;
+CommandProc CmdAlterGroup;
CommandProc CmdDeleteGroup;
CommandProc CmdAddVehicleGroup;
CommandProc CmdAddSharedVehicleGroup;
@@ -338,7 +338,7 @@ static const Command _command_proc_table[] = {
DEF_CMD(CmdDepotMassAutoReplace, 0, CMDT_VEHICLE_CONSTRUCTION ), // CMD_DEPOT_MASS_AUTOREPLACE
DEF_CMD(CmdCreateGroup, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_CREATE_GROUP
DEF_CMD(CmdDeleteGroup, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_DELETE_GROUP
- DEF_CMD(CmdRenameGroup, 0, CMDT_OTHER_MANAGEMENT ), // CMD_RENAME_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
diff --git a/src/command_type.h b/src/command_type.h
index b4a49bd9f..a369be665 100644
--- a/src/command_type.h
+++ b/src/command_type.h
@@ -314,7 +314,7 @@ enum Commands {
CMD_CREATE_GROUP, ///< create a new group
CMD_DELETE_GROUP, ///< delete a group
- CMD_RENAME_GROUP, ///< rename 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
diff --git a/src/group.h b/src/group.h
index d8680c294..91ee77e60 100644
--- a/src/group.h
+++ b/src/group.h
@@ -71,6 +71,8 @@ struct Group : GroupPool::PoolItem<&_group_pool> {
bool replace_protection; ///< If set to true, the global autoreplace have no effect on the group
GroupStatistics statistics; ///< NOSAVE: Statistics and caches on the vehicles in the group.
+ GroupID parent; ///< Parent group
+
Group(CompanyID owner = INVALID_COMPANY);
~Group();
};
@@ -101,6 +103,7 @@ void SetTrainGroupID(Train *v, GroupID grp);
void UpdateTrainGroupID(Train *v);
void RemoveVehicleFromGroup(const Vehicle *v);
void RemoveAllGroupsForCompany(const CompanyID company);
+bool GroupIsInGroup(GroupID search, GroupID group);
extern GroupID _new_group_id;
diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp
index e86b9de28..77e0b0d38 100644
--- a/src/group_cmd.cpp
+++ b/src/group_cmd.cpp
@@ -285,6 +285,7 @@ CommandCost CmdCreateGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
Group *g = new Group(_current_company);
g->replace_protection = false;
g->vehicle_type = vt;
+ g->parent = INVALID_GROUP;
_new_group_id = g->index;
@@ -313,6 +314,14 @@ CommandCost CmdDeleteGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
/* 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);
+ }
+ }
+
if (flags & DC_EXEC) {
/* Update backupped orders if needed */
OrderBackup::ClearGroup(g->index);
@@ -352,33 +361,60 @@ static bool IsUniqueGroupNameForVehicleType(const char *name, VehicleType type)
}
/**
- * Rename a group
+ * Alter a group
* @param tile unused
* @param flags type of operation
* @param p1 index of array group
* - p1 bit 0-15 : GroupID
- * @param p2 unused
+ * - p1 bit 16: 0 - Rename grouop
+ * 1 - Set group parent
+ * @param p2 parent group index
* @param text the new name or an empty string when resetting to the default
* @return the cost of this operation or an error
*/
-CommandCost CmdRenameGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
+CommandCost CmdAlterGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
- Group *g = Group::GetIfValid(p1);
+ Group *g = Group::GetIfValid(GB(p1, 0, 16));
if (g == NULL || g->owner != _current_company) return CMD_ERROR;
- bool reset = StrEmpty(text);
+ 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 (!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 : strdup(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. */
+ const Group *looptest = pg;
+ while (looptest->parent != INVALID_GROUP) {
+ if (looptest->parent == g->index) return CMD_ERROR;
+ looptest = Group::Get(looptest->parent);
+ }
+ }
+
+ if (flags & DC_EXEC) {
+ g->parent = (pg == NULL) ? INVALID_GROUP : pg->index;
+ }
}
if (flags & DC_EXEC) {
- /* Delete the old name */
- free(g->name);
- /* Assign the new one */
- g->name = reset ? NULL : strdup(text);
-
SetWindowDirty(WC_REPLACE_VEHICLE, g->vehicle_type);
InvalidateWindowData(GetWindowClassForVehicleType(g->vehicle_type), VehicleListIdentifier(VL_GROUP_LIST, g->vehicle_type, _current_company).Pack());
}
@@ -542,6 +578,20 @@ CommandCost CmdRemoveAllVehiclesGroup(TileIndex tile, DoCommandFlag flags, uint3
return CommandCost();
}
+/**
+ * Set replace protection for a group and its sub-groups.
+ * @param g initial group.
+ * @param protect 1 to set or 0 to clear protection.
+ */
+static void SetGroupReplaceProtection(Group *g, bool protect)
+{
+ g->replace_protection = protect;
+
+ Group *pg;
+ FOR_ALL_GROUPS(pg) {
+ if (pg->parent == g->index) SetGroupReplaceProtection(pg, protect);
+ }
+}
/**
* (Un)set global replace protection from a group
@@ -551,6 +601,7 @@ CommandCost CmdRemoveAllVehiclesGroup(TileIndex tile, DoCommandFlag flags, uint3
* - p1 bit 0-15 : GroupID
* @param p2
* - p2 bit 0 : 1 to set or 0 to clear protection.
+ * - p2 bit 1 : 1 to apply to sub-groups.
* @param text unused
* @return the cost of this operation or an error
*/
@@ -560,7 +611,11 @@ CommandCost CmdSetGroupReplaceProtection(TileIndex tile, DoCommandFlag flags, ui
if (g == NULL || g->owner != _current_company) return CMD_ERROR;
if (flags & DC_EXEC) {
- g->replace_protection = HasBit(p2, 0);
+ 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);
@@ -639,8 +694,13 @@ void UpdateTrainGroupID(Train *v)
*/
uint GetGroupNumEngines(CompanyID company, GroupID id_g, EngineID id_e)
{
+ uint count = 0;
const Engine *e = Engine::Get(id_e);
- return GroupStatistics::Get(company, id_g, e->type).num_engines[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)
@@ -651,3 +711,19 @@ void RemoveAllGroupsForCompany(const CompanyID company)
if (company == g->owner) delete g;
}
}
+
+
+bool GroupIsInGroup(GroupID search, GroupID group)
+{
+ if (search == NEW_GROUP ||
+ search == ALL_GROUP ||
+ search == DEFAULT_GROUP ||
+ search == INVALID_GROUP) return search == group;
+
+ do {
+ if (search == group) return true;
+ search = Group::Get(search)->parent;
+ } while (search != INVALID_GROUP);
+
+ return false;
+}
diff --git a/src/group_gui.cpp b/src/group_gui.cpp
index ed3176e27..698f9a71f 100644
--- a/src/group_gui.cpp
+++ b/src/group_gui.cpp
@@ -30,6 +30,8 @@
#include "table/sprites.h"
+static const int LEVEL_WIDTH = 10; ///< Indenting width of a sub-group in pixels
+
typedef GUIList<const Group*> GUIGroupList;
static const NWidgetPart _nested_group_widgets[] = {
@@ -105,34 +107,26 @@ private:
};
VehicleID vehicle_sel; ///< Selected vehicle
+ GroupID group_sel; ///< Selected group (for drag/drop)
GroupID group_rename; ///< Group being renamed, INVALID_GROUP if none
GroupID group_over; ///< Group over which a vehicle is dragged, INVALID_GROUP if none
GUIGroupList groups; ///< List of groups
uint tiny_step_height; ///< Step height for the group list
Scrollbar *group_sb;
+ SmallVector<int, 16> indents; ///< Indentation levels
+
Dimension column_size[VGC_END]; ///< Size of the columns in the group list.
- /**
- * (Re)Build the group list.
- *
- * @param owner The owner of the window
- */
- void BuildGroupList(Owner owner)
+ void AddParents(GUIGroupList *source, GroupID parent, int indent)
{
- if (!this->groups.NeedRebuild()) return;
-
- this->groups.Clear();
-
- const Group *g;
- FOR_ALL_GROUPS(g) {
- if (g->owner == owner && g->vehicle_type == this->vli.vtype) {
- *this->groups.Append() = g;
+ for (const Group **g = source->Begin(); g != source->End(); g++) {
+ if ((*g)->parent == parent) {
+ *this->groups.Append() = *g;
+ *this->indents.Append() = indent;
+ AddParents(source, (*g)->index, indent + 1);
}
}
-
- this->groups.Compact();
- this->groups.RebuildDone();
}
/** Sort the groups by their name */
@@ -159,6 +153,36 @@ private:
}
/**
+ * (Re)Build the group list.
+ *
+ * @param owner The owner of the window
+ */
+ void BuildGroupList(Owner owner)
+ {
+ if (!this->groups.NeedRebuild()) return;
+
+ this->groups.Clear();
+ this->indents.Clear();
+
+ GUIGroupList list;
+
+ const Group *g;
+ FOR_ALL_GROUPS(g) {
+ if (g->owner == owner && g->vehicle_type == this->vli.vtype) {
+ *list.Append() = g;
+ }
+ }
+
+ list.ForceResort();
+ list.Sort(&GroupNameSorter);
+
+ AddParents(&list, INVALID_GROUP, 0);
+
+ this->groups.Compact();
+ this->groups.RebuildDone();
+ }
+
+ /**
* Compute tiny_step_height and column_size
* @return Total width required for the group list.
*/
@@ -204,9 +228,10 @@ private:
* @param left Left of the row.
* @param right Right of the row.
* @param g_id Group to list.
+ * @param indent Indentation level.
* @param protection Whether autoreplace protection is set.
*/
- void DrawGroupInfo(int y, int left, int right, GroupID g_id, bool protection = false) const
+ void DrawGroupInfo(int y, int left, int right, GroupID g_id, int indent = 0, bool protection = false) const
{
/* Highlight the group if a vehicle is dragged over it */
if (g_id == this->group_over) {
@@ -231,7 +256,7 @@ private:
str = STR_GROUP_NAME;
}
int x = rtl ? right - WD_FRAMERECT_RIGHT - 8 - this->column_size[VGC_NAME].width + 1 : left + WD_FRAMERECT_LEFT + 8;
- DrawString(x, x + this->column_size[VGC_NAME].width - 1, y + (this->tiny_step_height - this->column_size[VGC_NAME].height) / 2, str, colour);
+ DrawString(x + indent * LEVEL_WIDTH, x + this->column_size[VGC_NAME].width - 1, y + (this->tiny_step_height - this->column_size[VGC_NAME].height) / 2, str, colour);
/* draw autoreplace protection */
x = rtl ? x - 8 - this->column_size[VGC_PROTECT].width : x + 8 + this->column_size[VGC_NAME].width;
@@ -295,6 +320,7 @@ public:
this->vli.index = ALL_GROUP;
this->vehicle_sel = INVALID_VEHICLE;
+ this->group_sel = INVALID_GROUP;
this->group_rename = INVALID_GROUP;
this->group_over = INVALID_GROUP;
@@ -308,7 +334,6 @@ public:
this->groups.ForceRebuild();
this->groups.NeedResort();
this->BuildGroupList(vli.company);
- this->groups.Sort(&GroupNameSorter);
this->GetWidget<NWidgetCore>(WID_GL_CAPTION)->widget_data = STR_VEHICLE_LIST_TRAIN_CAPTION + this->vli.vtype;
this->GetWidget<NWidgetCore>(WID_GL_LIST_VEHICLE)->tool_tip = STR_VEHICLE_LIST_TRAIN_LIST_TOOLTIP + this->vli.vtype;
@@ -442,7 +467,6 @@ public:
this->SortVehicleList();
this->BuildGroupList(this->owner);
- this->groups.Sort(&GroupNameSorter);
this->group_sb->SetCount(this->groups.Length());
this->vscroll->SetCount(this->vehicles.Length());
@@ -508,7 +532,7 @@ public:
assert(g->owner == this->owner);
- DrawGroupInfo(y1, r.left, r.right, g->index, g->replace_protection);
+ DrawGroupInfo(y1, r.left, r.right, g->index, this->indents[i], g->replace_protection);
y1 += this->tiny_step_height;
}
@@ -523,6 +547,19 @@ public:
break;
case WID_GL_LIST_VEHICLE:
+ if (this->vli.index != ALL_GROUP) {
+ /* Mark vehicles which are in sub-groups */
+ int y = r.top;
+ uint max = min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->vehicles.Length());
+ for (uint i = this->vscroll->GetPosition(); i < max; ++i) {
+ const Vehicle *v = this->vehicles[i];
+ if (v->group_id != this->vli.index) {
+ GfxFillRect(r.left + 1, y + 1, r.right - 1, y + this->resize.step_height - 2, _colour_gradient[COLOUR_GREY][3], FILLRECT_CHECKER);
+ }
+ y += this->resize.step_height;
+ }
+ }
+
this->DrawVehicleListItems(this->vehicle_sel, this->resize.step_height, r);
break;
}
@@ -560,7 +597,9 @@ public:
uint id_g = this->group_sb->GetScrolledRowFromWidget(pt.y, this, WID_GL_LIST_GROUP, 0, this->tiny_step_height);
if (id_g >= this->groups.Length()) return;
- this->vli.index = this->groups[id_g]->index;
+ this->group_sel = this->vli.index = this->groups[id_g]->index;
+
+ SetObjectToPlaceWnd(SPR_CURSOR_MOUSE, PAL_NONE, HT_DRAG, this);
this->vehicles.ForceRebuild();
this->SetDirty();
@@ -620,14 +659,46 @@ public:
case WID_GL_REPLACE_PROTECTION: {
const Group *g = Group::GetIfValid(this->vli.index);
if (g != NULL) {
- DoCommandP(0, this->vli.index, !g->replace_protection, CMD_SET_GROUP_REPLACE_PROTECTION);
+ DoCommandP(0, this->vli.index, !g->replace_protection | (_ctrl_pressed << 1), CMD_SET_GROUP_REPLACE_PROTECTION);
}
break;
}
}
}
- virtual void OnDragDrop(Point pt, int widget)
+ void OnDragDrop_Group(Point pt, int widget)
+ {
+ const Group *g = Group::Get(this->group_sel);
+
+ switch (widget) {
+ case WID_GL_ALL_VEHICLES: // All vehicles
+ case WID_GL_DEFAULT_VEHICLES: // Ungroupd vehicles
+ if (g->parent != INVALID_GROUP) {
+ DoCommandP(0, this->group_sel | (1 << 16), INVALID_GROUP, CMD_ALTER_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_SET_PARENT));
+ }
+
+ this->group_sel = INVALID_GROUP;
+ this->group_over = INVALID_GROUP;
+ this->SetDirty();
+ break;
+
+ case WID_GL_LIST_GROUP: { // Matrix group
+ uint id_g = this->group_sb->GetScrolledRowFromWidget(pt.y, this, WID_GL_LIST_GROUP, 0, this->tiny_step_height);
+ GroupID new_g = id_g >= this->groups.Length() ? INVALID_GROUP : this->groups[id_g]->index;
+
+ if (this->group_sel != new_g && g->parent != new_g) {
+ DoCommandP(0, this->group_sel | (1 << 16), new_g, CMD_ALTER_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_SET_PARENT));
+ }
+
+ this->group_sel = INVALID_GROUP;
+ this->group_over = INVALID_GROUP;
+ this->SetDirty();
+ break;
+ }
+ }
+ }
+
+ void OnDragDrop_Vehicle(Point pt, int widget)
{
switch (widget) {
case WID_GL_DEFAULT_VEHICLES: // Ungrouped vehicles
@@ -668,12 +739,19 @@ public:
break;
}
}
+ }
+
+ virtual void OnDragDrop(Point pt, int widget)
+ {
+ if (this->vehicle_sel != INVALID_VEHICLE) OnDragDrop_Vehicle(pt, widget);
+ if (this->group_sel != INVALID_GROUP) OnDragDrop_Group(pt, widget);
+
_cursor.vehchain = false;
}
virtual void OnQueryTextFinished(char *str)
{
- if (str != NULL) DoCommandP(0, this->group_rename, 0, CMD_RENAME_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_RENAME), NULL, str);
+ if (str != NULL) DoCommandP(0, this->group_rename, 0, CMD_ALTER_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_RENAME), NULL, str);
this->group_rename = INVALID_GROUP;
}
@@ -742,7 +820,7 @@ public:
virtual void OnMouseDrag(Point pt, int widget)
{
- if (this->vehicle_sel == INVALID_VEHICLE) return;
+ if (this->vehicle_sel == INVALID_VEHICLE && this->group_sel == INVALID_GROUP) return;
/* A vehicle is dragged over... */
GroupID new_group_over = INVALID_GROUP;
@@ -759,7 +837,11 @@ public:
}
/* Do not highlight when dragging over the current group */
- if (Vehicle::Get(vehicle_sel)->group_id == new_group_over) new_group_over = INVALID_GROUP;
+ if (this->vehicle_sel != INVALID_VEHICLE) {
+ if (Vehicle::Get(vehicle_sel)->group_id == new_group_over) new_group_over = INVALID_GROUP;
+ } else if (this->group_sel != INVALID_GROUP) {
+ if (this->group_sel == new_group_over || Group::Get(this->group_sel)->parent == new_group_over) new_group_over = INVALID_GROUP;
+ }
/* Mark widgets as dirty if the group changed. */
if (new_group_over != this->group_over) {
diff --git a/src/lang/english.txt b/src/lang/english.txt
index 198515a34..7bf97aaa3 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -3297,7 +3297,7 @@ STR_GROUP_DEFAULT_ROAD_VEHICLES :Ungrouped road
STR_GROUP_DEFAULT_SHIPS :Ungrouped ships
STR_GROUP_DEFAULT_AIRCRAFTS :Ungrouped aircraft
-STR_GROUPS_CLICK_ON_GROUP_FOR_TOOLTIP :{BLACK}Groups - click on a group to list all vehicles of this group
+STR_GROUPS_CLICK_ON_GROUP_FOR_TOOLTIP :{BLACK}Groups - click on a group to list all vehicles of this group. Drag and drop groups to arrange hierarchy.
STR_GROUP_CREATE_TOOLTIP :{BLACK}Click to create a group
STR_GROUP_DELETE_TOOLTIP :{BLACK}Delete the selected group
STR_GROUP_RENAME_TOOLTIP :{BLACK}Rename the selected group
@@ -4276,6 +4276,7 @@ STR_ERROR_YOU_ALREADY_OWN_IT :{WHITE}... you
STR_ERROR_GROUP_CAN_T_CREATE :{WHITE}Can't create group...
STR_ERROR_GROUP_CAN_T_DELETE :{WHITE}Can't delete this group...
STR_ERROR_GROUP_CAN_T_RENAME :{WHITE}Can't rename group...
+STR_ERROR_GROUP_CAN_T_SET_PARENT :{WHITE}Can't set parent group...
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...
diff --git a/src/saveload/group_sl.cpp b/src/saveload/group_sl.cpp
index 1e006a218..891d6ea6f 100644
--- a/src/saveload/group_sl.cpp
+++ b/src/saveload/group_sl.cpp
@@ -21,6 +21,7 @@ static const SaveLoad _group_desc[] = {
SLE_VAR(Group, owner, SLE_UINT8),
SLE_VAR(Group, vehicle_type, SLE_UINT8),
SLE_VAR(Group, replace_protection, SLE_BOOL),
+ SLE_CONDVAR(Group, parent, SLE_UINT16, 189, SL_MAX_VERSION),
SLE_END()
};
@@ -42,6 +43,8 @@ static void Load_GRPS()
while ((index = SlIterateArray()) != -1) {
Group *g = new (index) Group();
SlObject(g, _group_desc);
+
+ if (IsSavegameVersionBefore(189)) g->parent = INVALID_GROUP;
}
}
diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp
index e1daaf405..ab3e4a290 100644
--- a/src/saveload/saveload.cpp
+++ b/src/saveload/saveload.cpp
@@ -254,8 +254,9 @@
* 186 25833
* 187 25899
* 188 26169 1.4.x
+ * 189 26450
*/
-extern const uint16 SAVEGAME_VERSION = 188; ///< Current savegame version of OpenTTD.
+extern const uint16 SAVEGAME_VERSION = 189; ///< Current savegame version of OpenTTD.
SavegameType _savegame_type; ///< type of savegame we are loading
diff --git a/src/script/api/script_group.cpp b/src/script/api/script_group.cpp
index 01569d824..89cbf2c71 100644
--- a/src/script/api/script_group.cpp
+++ b/src/script/api/script_group.cpp
@@ -57,7 +57,7 @@
EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_GROUP_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);
- return ScriptObject::DoCommand(0, group_id, 0, CMD_RENAME_GROUP, text);
+ return ScriptObject::DoCommand(0, group_id, 0, CMD_ALTER_GROUP, text);
}
/* static */ char *ScriptGroup::GetName(GroupID group_id)
diff --git a/src/vehiclelist.cpp b/src/vehiclelist.cpp
index e74f28f0f..fca9c5e46 100644
--- a/src/vehiclelist.cpp
+++ b/src/vehiclelist.cpp
@@ -12,6 +12,7 @@
#include "stdafx.h"
#include "train.h"
#include "vehiclelist.h"
+#include "group.h"
/**
* Pack a VehicleListIdentifier in a single uint32.
@@ -145,7 +146,7 @@ bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli
if (vli.index != ALL_GROUP) {
FOR_ALL_VEHICLES(v) {
if (v->type == vli.vtype && v->IsPrimaryVehicle() &&
- v->owner == vli.company && v->group_id == vli.index) {
+ v->owner == vli.company && GroupIsInGroup(v->group_id, vli.index)) {
*list->Append() = v;
}
}