OpenTTD Source: src/group_cmd.cpp Source File

OpenTTD Source 15.0-RC2

group_cmd.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
10#include "stdafx.h"
11#include "command_func.h"
12#include "train.h"
13#include "vehiclelist.h"
14#include "vehicle_func.h"
15#include "autoreplace_base.h"
16#include "autoreplace_func.h"
17#include "string_func.h"
18#include "company_func.h"
19#include "core/pool_func.hpp"
20#include "order_backup.h"
21#include "group_cmd.h"
22
23#include "table/strings.h"
24
25#include "safeguards.h"
26
27 GroupPool _group_pool("Group");
28 INSTANTIATE_POOL_METHODS(Group)
29
30
33void GroupStatistics::Clear()
34{
35 this->num_vehicle = 0;
36 this->profit_last_year = 0;
37 this->num_vehicle_min_age = 0;
38 this->profit_last_year_min_age = 0;
39
40 /* This is also called when NewGRF change. So the number of engines might have changed. Reset. */
41 this->num_engines.clear();
42}
43
47 void UpdateGroupChildren()
48{
49 for (const Group *g : Group::Iterate()) {
50 if (g->parent != GroupID::Invalid()) Group::Get(g->parent)->children.insert(g->index);
51 }
52}
53
59uint16_t GroupStatistics::GetNumEngines(EngineID engine) const
60{
61 auto found = this->num_engines.find(engine);
62 if (found != std::end(this->num_engines)) return found->second;
63 return 0;
64}
65
73/* static */ GroupStatistics &GroupStatistics::Get(CompanyID company, GroupID id_g, VehicleType type)
74{
75 if (Group::IsValidID(id_g)) {
76 Group *g = Group::Get(id_g);
77 assert(g->owner == company);
78 assert(g->vehicle_type == type);
79 return g->statistics;
80 }
81
82 if (IsDefaultGroupID(id_g)) return Company::Get(company)->group_default[type];
83 if (IsAllGroupID(id_g)) return Company::Get(company)->group_all[type];
84
85 NOT_REACHED();
86}
87
93/* static */ GroupStatistics &GroupStatistics::Get(const Vehicle *v)
94{
95 return GroupStatistics::Get(v->owner, v->group_id, v->type);
96}
97
103/* static */ GroupStatistics &GroupStatistics::GetAllGroup(const Vehicle *v)
104{
105 return GroupStatistics::Get(v->owner, ALL_GROUP, v->type);
106}
107
111/* static */ void GroupStatistics::UpdateAfterLoad()
112{
113 /* Set up the engine count for all companies */
114 for (Company *c : Company::Iterate()) {
115 for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
116 c->group_all[type].Clear();
117 c->group_default[type].Clear();
118 }
119 }
120
121 /* Recalculate */
122 for (Group *g : Group::Iterate()) {
123 g->statistics.Clear();
124 }
125
126 for (const Vehicle *v : Vehicle::Iterate()) {
127 if (!v->IsEngineCountable()) continue;
128
129 GroupStatistics::CountEngine(v, 1);
130 if (v->IsPrimaryVehicle()) GroupStatistics::CountVehicle(v, 1);
131 }
132
133 for (const Company *c : Company::Iterate()) {
134 GroupStatistics::UpdateAutoreplace(c->index);
135 }
136}
137
143/* static */ void GroupStatistics::CountVehicle(const Vehicle *v, int delta)
144{
145 assert(delta == 1 || delta == -1);
146
147 GroupStatistics &stats_all = GroupStatistics::GetAllGroup(v);
148 GroupStatistics &stats = GroupStatistics::Get(v);
149
150 stats_all.num_vehicle += delta;
151 stats_all.profit_last_year += v->GetDisplayProfitLastYear() * delta;
152 stats.num_vehicle += delta;
153 stats.profit_last_year += v->GetDisplayProfitLastYear() * delta;
154
155 if (v->economy_age > VEHICLE_PROFIT_MIN_AGE) {
156 stats_all.num_vehicle_min_age += delta;
157 stats_all.profit_last_year_min_age += v->GetDisplayProfitLastYear() * delta;
158 stats.num_vehicle_min_age += delta;
159 stats.profit_last_year_min_age += v->GetDisplayProfitLastYear() * delta;
160 }
161}
162
168/* static */ void GroupStatistics::CountEngine(const Vehicle *v, int delta)
169{
170 assert(delta == 1 || delta == -1);
171 GroupStatistics::GetAllGroup(v).num_engines[v->engine_type] += delta;
172 GroupStatistics::Get(v).num_engines[v->engine_type] += delta;
173}
174
178/* static */ void GroupStatistics::AddProfitLastYear(const Vehicle *v)
179{
180 GroupStatistics &stats_all = GroupStatistics::GetAllGroup(v);
181 GroupStatistics &stats = GroupStatistics::Get(v);
182
183 stats_all.profit_last_year += v->GetDisplayProfitLastYear();
184 stats.profit_last_year += v->GetDisplayProfitLastYear();
185}
186
190/* static */ void GroupStatistics::VehicleReachedMinAge(const Vehicle *v)
191{
192 GroupStatistics &stats_all = GroupStatistics::GetAllGroup(v);
193 GroupStatistics &stats = GroupStatistics::Get(v);
194
195 stats_all.num_vehicle_min_age++;
196 stats_all.profit_last_year_min_age += v->GetDisplayProfitLastYear();
197 stats.num_vehicle_min_age++;
198 stats.profit_last_year_min_age += v->GetDisplayProfitLastYear();
199}
200
204/* static */ void GroupStatistics::UpdateProfits()
205{
206 /* Set up the engine count for all companies */
207 for (Company *c : Company::Iterate()) {
208 for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
209 c->group_all[type].ClearProfits();
210 c->group_default[type].ClearProfits();
211 }
212 }
213
214 /* Recalculate */
215 for (Group *g : Group::Iterate()) {
216 g->statistics.ClearProfits();
217 }
218
219 for (const Vehicle *v : Vehicle::Iterate()) {
220 if (v->IsPrimaryVehicle()) {
221 GroupStatistics::AddProfitLastYear(v);
222 if (v->economy_age > VEHICLE_PROFIT_MIN_AGE) GroupStatistics::VehicleReachedMinAge(v);
223 }
224 }
225}
226
231/* static */ void GroupStatistics::UpdateAutoreplace(CompanyID company)
232{
233 /* Set up the engine count for all companies */
234 Company *c = Company::Get(company);
235 for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
236 c->group_all[type].ClearAutoreplace();
237 c->group_default[type].ClearAutoreplace();
238 }
239
240 /* Recalculate */
241 for (Group *g : Group::Iterate()) {
242 if (g->owner != company) continue;
243 g->statistics.ClearAutoreplace();
244 }
245
246 for (EngineRenewList erl = c->engine_renew_list; erl != nullptr; erl = erl->next) {
247 const Engine *e = Engine::Get(erl->from);
248 GroupStatistics &stats = GroupStatistics::Get(company, erl->group_id, e->type);
249 if (!stats.autoreplace_defined) {
250 stats.autoreplace_defined = true;
251 stats.autoreplace_finished = true;
252 }
253 if (GetGroupNumEngines(company, erl->group_id, erl->from) > 0) stats.autoreplace_finished = false;
254 }
255}
256
264 static inline void UpdateNumEngineGroup(const Vehicle *v, GroupID old_g, GroupID new_g)
265{
266 if (old_g != new_g) {
267 /* Decrease the num engines in the old group */
268 GroupStatistics::Get(v->owner, old_g, v->type).num_engines[v->engine_type]--;
269
270 /* Increase the num engines in the new group */
271 GroupStatistics::Get(v->owner, new_g, v->type).num_engines[v->engine_type]++;
272 }
273}
274
275
276const Livery *GetParentLivery(const Group *g)
277{
278 if (g->parent == GroupID::Invalid()) {
279 const Company *c = Company::Get(g->owner);
280 return &c->livery[LS_DEFAULT];
281 }
282
283 const Group *pg = Group::Get(g->parent);
284 return &pg->livery;
285}
286
287
293 static void PropagateChildLivery(const Group *g, bool reset_cache)
294{
295 if (reset_cache) {
296 /* Company colour data is indirectly cached. */
297 for (Vehicle *v : Vehicle::Iterate()) {
298 if (v->group_id == g->index && (!v->IsGroundVehicle() || v->IsFrontEngine())) {
299 for (Vehicle *u = v; u != nullptr; u = u->Next()) {
300 u->colourmap = PAL_NONE;
301 u->InvalidateNewGRFCache();
302 }
303 }
304 }
305 }
306
307 for (const GroupID &childgroup : g->children) {
308 Group *cg = Group::Get(childgroup);
309 if (!cg->livery.in_use.Test(Livery::Flag::Primary)) cg->livery.colour1 = g->livery.colour1;
310 if (!cg->livery.in_use.Test(Livery::Flag::Secondary)) cg->livery.colour2 = g->livery.colour2;
311 PropagateChildLivery(cg, reset_cache);
312 }
313}
314
320 void UpdateCompanyGroupLiveries(const Company *c)
321{
322 for (Group *g : Group::Iterate()) {
323 if (g->owner == c->index && g->parent == GroupID::Invalid()) {
324 if (!g->livery.in_use.Test(Livery::Flag::Primary)) g->livery.colour1 = c->livery[LS_DEFAULT].colour1;
325 if (!g->livery.in_use.Test(Livery::Flag::Secondary)) g->livery.colour2 = c->livery[LS_DEFAULT].colour2;
326 PropagateChildLivery(g, false);
327 }
328 }
329}
330
331
339std::tuple<CommandCost, GroupID> CmdCreateGroup(DoCommandFlags flags, VehicleType vt, GroupID parent_group)
340{
341 if (!IsCompanyBuildableVehicleType(vt)) return { CMD_ERROR, GroupID::Invalid() };
342
343 if (!Group::CanAllocateItem()) return { CMD_ERROR, GroupID::Invalid() };
344
345 Group *pg = Group::GetIfValid(parent_group);
346 if (pg != nullptr) {
347 if (pg->owner != _current_company) return { CMD_ERROR, GroupID::Invalid() };
348 if (pg->vehicle_type != vt) return { CMD_ERROR, GroupID::Invalid() };
349 }
350
351 if (flags.Test(DoCommandFlag::Execute)) {
352 Group *g = new Group(_current_company, vt);
353
354 Company *c = Company::Get(g->owner);
355 g->number = c->freegroups.UseID(c->freegroups.NextID());
356 if (pg == nullptr) {
357 g->livery.colour1 = c->livery[LS_DEFAULT].colour1;
358 g->livery.colour2 = c->livery[LS_DEFAULT].colour2;
359 if (c->settings.renew_keep_length) g->flags.Set(GroupFlag::ReplaceWagonRemoval);
360 } else {
361 g->parent = pg->index;
362 g->livery.colour1 = pg->livery.colour1;
363 g->livery.colour2 = pg->livery.colour2;
364 g->flags = pg->flags;
365 pg->children.insert(g->index);
366 }
367
368 InvalidateWindowData(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_GROUP_LIST, vt, _current_company).ToWindowNumber());
369 InvalidateWindowData(WC_COMPANY_COLOUR, g->owner, g->vehicle_type);
370
371 return { CommandCost(), g->index };
372 }
373
374 return { CommandCost(), GroupID::Invalid()};
375}
376
377
384 CommandCost CmdDeleteGroup(DoCommandFlags flags, GroupID group_id)
385{
386 Group *g = Group::GetIfValid(group_id);
387 if (g == nullptr || g->owner != _current_company) return CMD_ERROR;
388
389 /* Remove all vehicles from the group */
390 Command<CMD_REMOVE_ALL_VEHICLES_GROUP>::Do(flags, group_id);
391
392 /* Delete sub-groups */
393 for (const GroupID &childgroup : g->children) {
394 Command<CMD_DELETE_GROUP>::Do(flags, childgroup);
395 }
396
397 if (flags.Test(DoCommandFlag::Execute)) {
398 /* Update backupped orders if needed */
399 OrderBackup::ClearGroup(g->index);
400
401 if (g->owner < MAX_COMPANIES) {
402 Company *c = Company::Get(g->owner);
403
404 /* If we set an autoreplace for the group we delete, remove it. */
405 for (const EngineRenew *er : EngineRenew::Iterate()) {
406 if (er->group_id == g->index) RemoveEngineReplacementForCompany(c, er->from, g->index, flags);
407 }
408
409 c->freegroups.ReleaseID(g->number);
410 }
411
412 if (g->parent != GroupID::Invalid()) {
413 Group *pg = Group::Get(g->parent);
414 pg->children.erase(g->index);
415 }
416
417 VehicleType vt = g->vehicle_type;
418
419 /* Delete the Replace Vehicle Windows */
420 CloseWindowById(WC_REPLACE_VEHICLE, g->vehicle_type);
421 delete g;
422
423 InvalidateWindowData(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_GROUP_LIST, vt, _current_company).ToWindowNumber());
424 InvalidateWindowData(WC_COMPANY_COLOUR, _current_company, vt);
425 }
426
427 return CommandCost();
428}
429
439 CommandCost CmdAlterGroup(DoCommandFlags flags, AlterGroupMode mode, GroupID group_id, GroupID parent_id, const std::string &text)
440{
441 Group *g = Group::GetIfValid(group_id);
442 if (g == nullptr || g->owner != _current_company) return CMD_ERROR;
443
444 if (mode == AlterGroupMode::Rename) {
445 /* Rename group */
446 bool reset = text.empty();
447
448 if (!reset) {
449 if (Utf8StringLength(text) >= MAX_LENGTH_GROUP_NAME_CHARS) return CMD_ERROR;
450 }
451
452 if (flags.Test(DoCommandFlag::Execute)) {
453 /* Assign the new one */
454 if (reset) {
455 g->name.clear();
456 } else {
457 g->name = text;
458 }
459 }
460 } else if (mode == AlterGroupMode::SetParent) {
461 /* Do nothing if the parent group isn't actually changed. */
462 if (g->parent == parent_id) return CommandCost();
463
464 /* Set group parent */
465 const Group *pg = Group::GetIfValid(parent_id);
466
467 if (pg != nullptr) {
468 if (pg->owner != _current_company) return CMD_ERROR;
469 if (pg->vehicle_type != g->vehicle_type) return CMD_ERROR;
470
471 /* Ensure request parent isn't child of group.
472 * This is the only place that infinite loops are prevented. */
473 if (GroupIsInGroup(pg->index, g->index)) return CommandCost(STR_ERROR_GROUP_CAN_T_SET_PARENT_RECURSION);
474 }
475
476 if (flags.Test(DoCommandFlag::Execute)) {
477 if (g->parent != GroupID::Invalid()) Group::Get(g->parent)->children.erase(g->index);
478 g->parent = (pg == nullptr) ? GroupID::Invalid() : pg->index;
479 if (g->parent != GroupID::Invalid()) Group::Get(g->parent)->children.insert(g->index);
480
481 GroupStatistics::UpdateAutoreplace(g->owner);
482
483 if (!g->livery.in_use.All({Livery::Flag::Primary, Livery::Flag::Secondary})) {
484 /* Update livery with new parent's colours if either colour is default. */
485 const Livery *livery = GetParentLivery(g);
486 if (!g->livery.in_use.Test(Livery::Flag::Primary)) g->livery.colour1 = livery->colour1;
487 if (!g->livery.in_use.Test(Livery::Flag::Secondary)) g->livery.colour2 = livery->colour2;
488
489 PropagateChildLivery(g, true);
490 MarkWholeScreenDirty();
491 }
492 }
493 } else {
494 return CMD_ERROR;
495 }
496
497 if (flags.Test(DoCommandFlag::Execute)) {
498 InvalidateWindowData(WC_REPLACE_VEHICLE, g->vehicle_type, 1);
499 InvalidateWindowData(GetWindowClassForVehicleType(g->vehicle_type), VehicleListIdentifier(VL_GROUP_LIST, g->vehicle_type, _current_company).ToWindowNumber());
500 InvalidateWindowData(WC_COMPANY_COLOUR, g->owner, g->vehicle_type);
501 InvalidateWindowClassesData(WC_VEHICLE_VIEW);
502 InvalidateWindowClassesData(WC_VEHICLE_DETAILS);
503 }
504
505 return CommandCost();
506}
507
508
514 static void AddVehicleToGroup(Vehicle *v, GroupID new_g)
515{
516 GroupStatistics::CountVehicle(v, -1);
517
518 switch (v->type) {
519 default: NOT_REACHED();
520 case VEH_TRAIN:
521 SetTrainGroupID(Train::From(v), new_g);
522 break;
523
524 case VEH_ROAD:
525 case VEH_SHIP:
526 case VEH_AIRCRAFT:
527 if (v->IsEngineCountable()) UpdateNumEngineGroup(v, v->group_id, new_g);
528 v->group_id = new_g;
529 for (Vehicle *u = v; u != nullptr; u = u->Next()) {
530 u->colourmap = PAL_NONE;
531 u->InvalidateNewGRFCache();
532 u->UpdateViewport(true);
533 }
534 break;
535 }
536
537 InvalidateWindowData(WC_VEHICLE_VIEW, v->index);
538 InvalidateWindowData(WC_VEHICLE_DETAILS, v->index);
539
540 GroupStatistics::CountVehicle(v, 1);
541}
542
551std::tuple<CommandCost, GroupID> CmdAddVehicleGroup(DoCommandFlags flags, GroupID group_id, VehicleID veh_id, bool add_shared, const VehicleListIdentifier &vli)
552{
553 GroupID new_g = group_id;
554 if (!Group::IsValidID(new_g) && !IsDefaultGroupID(new_g) && new_g != NEW_GROUP) return { CMD_ERROR, GroupID::Invalid() };
555
556 VehicleList list;
557 if (veh_id == VehicleID::Invalid() && vli.Valid()) {
558 if (!GenerateVehicleSortList(&list, vli) || list.empty()) return { CMD_ERROR, GroupID::Invalid() };
559 } else {
560 const Vehicle *v = Vehicle::GetIfValid(veh_id);
561 if (v == nullptr) return { CMD_ERROR, GroupID::Invalid() };
562 list.push_back(v);
563 }
564
565 VehicleType vtype = list.front()->type;
566 for (const Vehicle *v : list) {
567 if (v->owner != _current_company || !v->IsPrimaryVehicle()) return { CMD_ERROR, GroupID::Invalid() };
568 }
569
570 if (Group::IsValidID(new_g)) {
571 const Group *g = Group::Get(new_g);
572 if (g->owner != _current_company || g->vehicle_type != vtype) return { CMD_ERROR, GroupID::Invalid() };
573 }
574
575 if (new_g == NEW_GROUP) {
576 /* Create new group. */
577 auto [ret, new_group_id] = CmdCreateGroup(flags, vtype, GroupID::Invalid());
578 if (ret.Failed()) return { ret, new_group_id };
579
580 new_g = new_group_id;
581 }
582
583 if (flags.Test(DoCommandFlag::Execute)) {
584 for (const Vehicle *vc : list) {
585 /* VehicleList is const but we need to modify the vehicle. */
586 Vehicle *v = Vehicle::Get(vc->index);
587 AddVehicleToGroup(v, new_g);
588
589 if (add_shared) {
590 /* Add vehicles in the shared order list as well. */
591 for (Vehicle *v2 = v->FirstShared(); v2 != nullptr; v2 = v2->NextShared()) {
592 if (v2->group_id != new_g) AddVehicleToGroup(v2, new_g);
593 }
594 }
595
596 SetWindowDirty(WC_VEHICLE_DEPOT, v->tile);
597 }
598
599 GroupStatistics::UpdateAutoreplace(_current_company);
600
601 /* Update the Replace Vehicle Windows */
602 SetWindowDirty(WC_REPLACE_VEHICLE, vtype);
603 InvalidateWindowData(GetWindowClassForVehicleType(vtype), VehicleListIdentifier(VL_GROUP_LIST, vtype, _current_company).ToWindowNumber());
604 }
605
606 return { CommandCost(), new_g };
607}
608
616 CommandCost CmdAddSharedVehicleGroup(DoCommandFlags flags, GroupID id_g, VehicleType type)
617{
618 if (!Group::IsValidID(id_g) || !IsCompanyBuildableVehicleType(type)) return CMD_ERROR;
619
620 if (flags.Test(DoCommandFlag::Execute)) {
621 /* Find the first front engine which belong to the group id_g
622 * then add all shared vehicles of this front engine to the group id_g */
623 for (const Vehicle *v : Vehicle::Iterate()) {
624 if (v->type == type && v->IsPrimaryVehicle()) {
625 if (v->group_id != id_g) continue;
626
627 /* For each shared vehicles add it to the group */
628 for (Vehicle *v2 = v->FirstShared(); v2 != nullptr; v2 = v2->NextShared()) {
629 if (v2->group_id != id_g) Command<CMD_ADD_VEHICLE_GROUP>::Do(flags, id_g, v2->index, false, VehicleListIdentifier{});
630 }
631 }
632 }
633
634 InvalidateWindowData(GetWindowClassForVehicleType(type), VehicleListIdentifier(VL_GROUP_LIST, type, _current_company).ToWindowNumber());
635 }
636
637 return CommandCost();
638}
639
640
647 CommandCost CmdRemoveAllVehiclesGroup(DoCommandFlags flags, GroupID group_id)
648{
649 const Group *g = Group::GetIfValid(group_id);
650
651 if (g == nullptr || g->owner != _current_company) return CMD_ERROR;
652
653 if (flags.Test(DoCommandFlag::Execute)) {
654 /* Find each Vehicle that belongs to the group old_g and add it to the default group */
655 for (const Vehicle *v : Vehicle::Iterate()) {
656 if (v->IsPrimaryVehicle()) {
657 if (v->group_id != group_id) continue;
658
659 /* Add The Vehicle to the default group */
660 Command<CMD_ADD_VEHICLE_GROUP>::Do(flags, DEFAULT_GROUP, v->index, false, VehicleListIdentifier{});
661 }
662 }
663
664 InvalidateWindowData(GetWindowClassForVehicleType(g->vehicle_type), VehicleListIdentifier(VL_GROUP_LIST, g->vehicle_type, _current_company).ToWindowNumber());
665 }
666
667 return CommandCost();
668}
669
677 CommandCost CmdSetGroupLivery(DoCommandFlags flags, GroupID group_id, bool primary, Colours colour)
678{
679 Group *g = Group::GetIfValid(group_id);
680
681 if (g == nullptr || g->owner != _current_company) return CMD_ERROR;
682
683 if (colour >= COLOUR_END && colour != INVALID_COLOUR) return CMD_ERROR;
684
685 if (flags.Test(DoCommandFlag::Execute)) {
686 if (primary) {
687 g->livery.in_use.Set(Livery::Flag::Primary, colour != INVALID_COLOUR);
688 if (colour == INVALID_COLOUR) colour = GetParentLivery(g)->colour1;
689 g->livery.colour1 = colour;
690 } else {
691 g->livery.in_use.Set(Livery::Flag::Secondary, colour != INVALID_COLOUR);
692 if (colour == INVALID_COLOUR) colour = GetParentLivery(g)->colour2;
693 g->livery.colour2 = colour;
694 }
695
696 PropagateChildLivery(g, true);
697 MarkWholeScreenDirty();
698 }
699
700 return CommandCost();
701}
702
708 static void SetGroupFlag(Group *g, GroupFlag flag, bool set, bool children)
709{
710 if (set) {
711 g->flags.Set(flag);
712 } else {
713 g->flags.Reset(flag);
714 }
715
716 if (!children) return;
717
718 for (const GroupID &childgroup : g->children) {
719 SetGroupFlag(Group::Get(childgroup), flag, set, true);
720 }
721}
722
732 CommandCost CmdSetGroupFlag(DoCommandFlags flags, GroupID group_id, GroupFlag flag, bool value, bool recursive)
733{
734 Group *g = Group::GetIfValid(group_id);
735 if (g == nullptr || g->owner != _current_company) return CMD_ERROR;
736
737 if (flag != GroupFlag::ReplaceProtection && flag != GroupFlag::ReplaceWagonRemoval) return CMD_ERROR;
738
739 if (flags.Test(DoCommandFlag::Execute)) {
740 SetGroupFlag(g, flag, value, recursive);
741
742 SetWindowDirty(GetWindowClassForVehicleType(g->vehicle_type), VehicleListIdentifier(VL_GROUP_LIST, g->vehicle_type, _current_company).ToWindowNumber());
743 InvalidateWindowData(WC_REPLACE_VEHICLE, g->vehicle_type);
744 }
745
746 return CommandCost();
747}
748
755 void SetTrainGroupID(Train *v, GroupID new_g)
756{
757 if (!Group::IsValidID(new_g) && !IsDefaultGroupID(new_g)) return;
758
759 assert(v->IsFrontEngine() || IsDefaultGroupID(new_g));
760
761 for (Vehicle *u = v; u != nullptr; u = u->Next()) {
762 if (u->IsEngineCountable()) UpdateNumEngineGroup(u, u->group_id, new_g);
763
764 u->group_id = new_g;
765 u->colourmap = PAL_NONE;
766 u->InvalidateNewGRFCache();
767 u->UpdateViewport(true);
768 }
769
770 /* Update the Replace Vehicle Windows */
771 GroupStatistics::UpdateAutoreplace(v->owner);
772 SetWindowDirty(WC_REPLACE_VEHICLE, VEH_TRAIN);
773}
774
775
783 void UpdateTrainGroupID(Train *v)
784{
785 assert(v->IsFrontEngine() || v->IsFreeWagon());
786
787 GroupID new_g = v->IsFrontEngine() ? v->group_id : (GroupID)DEFAULT_GROUP;
788 for (Vehicle *u = v; u != nullptr; u = u->Next()) {
789 if (u->IsEngineCountable()) UpdateNumEngineGroup(u, u->group_id, new_g);
790
791 u->group_id = new_g;
792 u->colourmap = PAL_NONE;
793 u->InvalidateNewGRFCache();
794 }
795
796 /* Update the Replace Vehicle Windows */
797 GroupStatistics::UpdateAutoreplace(v->owner);
798 SetWindowDirty(WC_REPLACE_VEHICLE, VEH_TRAIN);
799}
800
809uint GetGroupNumEngines(CompanyID company, GroupID id_g, EngineID id_e)
810{
811 uint count = 0;
812
813 if (const Group *g = Group::GetIfValid(id_g); g != nullptr) {
814 for (const GroupID &childgroup : g->children) {
815 count += GetGroupNumEngines(company, childgroup, id_e);
816 }
817 }
818
819 return count + GroupStatistics::Get(company, id_g, Engine::Get(id_e)->type).GetNumEngines(id_e);
820}
821
830uint GetGroupNumVehicle(CompanyID company, GroupID id_g, VehicleType type)
831{
832 uint count = 0;
833
834 if (const Group *g = Group::GetIfValid(id_g); g != nullptr) {
835 for (const GroupID &childgroup : g->children) {
836 count += GetGroupNumVehicle(company, childgroup, type);
837 }
838 }
839
840 return count + GroupStatistics::Get(company, id_g, type).num_vehicle;
841}
842
851uint GetGroupNumVehicleMinAge(CompanyID company, GroupID id_g, VehicleType type)
852{
853 uint count = 0;
854
855 if (const Group *g = Group::GetIfValid(id_g); g != nullptr) {
856 for (const GroupID &childgroup : g->children) {
857 count += GetGroupNumVehicleMinAge(company, childgroup, type);
858 }
859 }
860
861 return count + GroupStatistics::Get(company, id_g, type).num_vehicle_min_age;
862}
863
872 Money GetGroupProfitLastYearMinAge(CompanyID company, GroupID id_g, VehicleType type)
873{
874 Money sum = 0;
875
876 if (const Group *g = Group::GetIfValid(id_g); g != nullptr) {
877 for (const GroupID &childgroup : g->children) {
878 sum += GetGroupProfitLastYearMinAge(company, childgroup, type);
879 }
880 }
881
882 return sum + GroupStatistics::Get(company, id_g, type).profit_last_year_min_age;
883}
884
885void RemoveAllGroupsForCompany(const CompanyID company)
886{
887 for (Group *g : Group::Iterate()) {
888 if (company == g->owner) delete g;
889 }
890}
891
892
899 bool GroupIsInGroup(GroupID search, GroupID group)
900{
901 if (!Group::IsValidID(search)) return search == group;
902
903 do {
904 if (search == group) return true;
905 search = Group::Get(search)->parent;
906 } while (search != GroupID::Invalid());
907
908 return false;
909}
autoreplace_base.h
Base class for autoreplaces/autorenews.
autoreplace_func.h
Functions related to autoreplacing.
RemoveEngineReplacementForCompany
CommandCost RemoveEngineReplacementForCompany(Company *c, EngineID engine, GroupID group, DoCommandFlags flags)
Remove an engine replacement for the company.
Definition autoreplace_func.h:93
BaseBitSet::All
constexpr bool All(const Timpl &other) const
Test if all of the values are set.
Definition base_bitset_type.hpp:151
BaseBitSet::Test
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Definition base_bitset_type.hpp:141
BaseBitSet::Reset
constexpr Timpl & Reset()
Reset all bits.
Definition base_bitset_type.hpp:83
BaseBitSet::Set
constexpr Timpl & Set()
Set all bits.
Definition base_bitset_type.hpp:40
CommandCost
Common return value for all commands.
Definition command_type.h:24
Engine
Definition engine_base.h:38
Engine::type
VehicleType type
Vehicle type, ie VEH_ROAD, VEH_TRAIN, etc.
Definition engine_base.h:62
EnumBitSet
Enum-as-bit-set wrapper.
Definition enum_type.hpp:177
FreeUnitIDGenerator::UseID
UnitID UseID(UnitID index)
Use a unit number.
Definition vehicle.cpp:1844
FreeUnitIDGenerator::ReleaseID
void ReleaseID(UnitID index)
Release a unit number.
Definition vehicle.cpp:1861
FreeUnitIDGenerator::NextID
UnitID NextID() const
Find first unused unit number.
Definition vehicle.cpp:1829
OverflowSafeInt< int64_t >
command_func.h
Functions related to commands.
CMD_ERROR
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition command_func.h:28
DoCommandFlag::Execute
@ Execute
execute the given command
_current_company
CompanyID _current_company
Company currently doing an action.
Definition company_cmd.cpp:56
company_func.h
Functions related to companies.
GroupFlag
GroupFlag
Definition group.h:66
GroupFlag::ReplaceProtection
@ ReplaceProtection
If set, the global autoreplace has no effect on the group.
GroupFlag::ReplaceWagonRemoval
@ ReplaceWagonRemoval
If set, autoreplace will perform wagon removal on vehicles in this group.
GetGroupNumEngines
uint GetGroupNumEngines(CompanyID company, GroupID id_g, EngineID id_e)
Get the number of engines with EngineID id_e in the group with GroupID id_g and its sub-groups.
Definition group_cmd.cpp:809
_group_pool
GroupPool _group_pool
Pool of groups.
IsAllGroupID
bool IsAllGroupID(GroupID id_g)
Checks if a GroupID stands for all vehicles of a company.
Definition group.h:103
GetGroupProfitLastYearMinAge
Money GetGroupProfitLastYearMinAge(CompanyID company, GroupID id_g, VehicleType type)
Get last year's profit of vehicles above minimum age for the group with GroupID id_g and its sub-grou...
Definition group_cmd.cpp:872
CmdAddSharedVehicleGroup
CommandCost CmdAddSharedVehicleGroup(DoCommandFlags flags, GroupID id_g, VehicleType type)
Add all shared vehicles of all vehicles from a group.
Definition group_cmd.cpp:616
CmdSetGroupFlag
CommandCost CmdSetGroupFlag(DoCommandFlags flags, GroupID group_id, GroupFlag flag, bool value, bool recursive)
(Un)set group flag from a group
Definition group_cmd.cpp:732
CmdCreateGroup
std::tuple< CommandCost, GroupID > CmdCreateGroup(DoCommandFlags flags, VehicleType vt, GroupID parent_group)
Create a new vehicle group.
Definition group_cmd.cpp:339
SetGroupFlag
static void SetGroupFlag(Group *g, GroupFlag flag, bool set, bool children)
Set group flag for a group and its sub-groups.
Definition group_cmd.cpp:708
UpdateCompanyGroupLiveries
void UpdateCompanyGroupLiveries(const Company *c)
Update group liveries for a company.
Definition group_cmd.cpp:320
CmdAlterGroup
CommandCost CmdAlterGroup(DoCommandFlags flags, AlterGroupMode mode, GroupID group_id, GroupID parent_id, const std::string &text)
Alter a group.
Definition group_cmd.cpp:439
SetTrainGroupID
void SetTrainGroupID(Train *v, GroupID new_g)
Affect the groupID of a train to new_g.
Definition group_cmd.cpp:755
UpdateGroupChildren
void UpdateGroupChildren()
Update children list for each group.
Definition group_cmd.cpp:47
CmdSetGroupLivery
CommandCost CmdSetGroupLivery(DoCommandFlags flags, GroupID group_id, bool primary, Colours colour)
Set the livery for a vehicle group.
Definition group_cmd.cpp:677
CmdRemoveAllVehiclesGroup
CommandCost CmdRemoveAllVehiclesGroup(DoCommandFlags flags, GroupID group_id)
Remove all vehicles from a group.
Definition group_cmd.cpp:647
UpdateTrainGroupID
void UpdateTrainGroupID(Train *v)
Recalculates the groupID of a train.
Definition group_cmd.cpp:783
CmdDeleteGroup
CommandCost CmdDeleteGroup(DoCommandFlags flags, GroupID group_id)
Add all vehicles in the given group to the default group and then deletes the group.
Definition group_cmd.cpp:384
GetGroupNumEngines
uint GetGroupNumEngines(CompanyID company, GroupID id_g, EngineID id_e)
Get the number of engines with EngineID id_e in the group with GroupID id_g and its sub-groups.
Definition group_cmd.cpp:809
UpdateNumEngineGroup
static void UpdateNumEngineGroup(const Vehicle *v, GroupID old_g, GroupID new_g)
Update the num engines of a groupID.
Definition group_cmd.cpp:264
CmdAddVehicleGroup
std::tuple< CommandCost, GroupID > CmdAddVehicleGroup(DoCommandFlags flags, GroupID group_id, VehicleID veh_id, bool add_shared, const VehicleListIdentifier &vli)
Add a vehicle to a group.
Definition group_cmd.cpp:551
AddVehicleToGroup
static void AddVehicleToGroup(Vehicle *v, GroupID new_g)
Do add a vehicle to a group.
Definition group_cmd.cpp:514
PropagateChildLivery
static void PropagateChildLivery(const Group *g, bool reset_cache)
Propagate a livery change to a group's children, and optionally update cached vehicle colourmaps.
Definition group_cmd.cpp:293
GetGroupNumVehicle
uint GetGroupNumVehicle(CompanyID company, GroupID id_g, VehicleType type)
Get the number of vehicles in the group with GroupID id_g and its sub-groups.
Definition group_cmd.cpp:830
GetGroupNumVehicleMinAge
uint GetGroupNumVehicleMinAge(CompanyID company, GroupID id_g, VehicleType type)
Get the number of vehicles above profit minimum age in the group with GroupID id_g and its sub-groups...
Definition group_cmd.cpp:851
GroupIsInGroup
bool GroupIsInGroup(GroupID search, GroupID group)
Test if GroupID group is a descendant of (or is) GroupID search.
Definition group_cmd.cpp:899
group_cmd.h
Command definitions related to engine groups.
AlterGroupMode
AlterGroupMode
Action for CmdAlterGroup.
Definition group_cmd.h:23
AlterGroupMode::Rename
@ Rename
Change group name.
AlterGroupMode::SetParent
@ SetParent
Change group parent.
MarkWholeScreenDirty
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1546
DEFAULT_GROUP
static constexpr GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition group_type.h:18
ALL_GROUP
static constexpr GroupID ALL_GROUP
All vehicles are in this group.
Definition group_type.h:17
NEW_GROUP
static constexpr GroupID NEW_GROUP
Sentinel for a to-be-created group.
Definition group_type.h:16
MAX_LENGTH_GROUP_NAME_CHARS
static const uint MAX_LENGTH_GROUP_NAME_CHARS
The maximum length of a group name in characters including '\0'.
Definition group_type.h:20
order_backup.h
Functions related to order backups.
pool_func.hpp
Some methods of Pool are placed here in order to reduce compilation time and binary size.
INSTANTIATE_POOL_METHODS
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
Definition pool_func.hpp:210
safeguards.h
A number of safeguards to prevent using unsafe methods.
stdafx.h
Definition of base types and functions in a cross-platform compatible way.
Utf8StringLength
size_t Utf8StringLength(std::string_view str)
Get the length of an UTF-8 encoded string in number of characters and thus not the number of bytes th...
Definition string.cpp:349
string_func.h
Functions related to low-level strings.
BaseVehicle::type
VehicleType type
Type of vehicle.
Definition vehicle_type.h:51
CommandHelper
Definition command_func.h:83
CompanyProperties::settings
CompanySettings settings
settings specific for each company
Definition company_base.h:124
CompanyProperties::engine_renew_list
EngineRenewList engine_renew_list
Engine renewals of this company.
Definition company_base.h:123
CompanySettings::renew_keep_length
bool renew_keep_length
sell some wagons if after autoreplace the train is longer than before
Definition settings_type.h:614
Company
Definition company_base.h:127
Company::group_default
std::array< GroupStatistics, VEH_COMPANY_END > group_default
NOSAVE: Statistics for the DEFAULT_GROUP group.
Definition company_base.h:139
Company::group_all
std::array< GroupStatistics, VEH_COMPANY_END > group_all
NOSAVE: Statistics for the ALL_GROUP group.
Definition company_base.h:138
EngineRenew
Struct to store engine replacements.
Definition autoreplace_base.h:33
GroundVehicle::IsFreeWagon
bool IsFreeWagon() const
Check if the vehicle is a free wagon (got no engine in front of it).
Definition ground_vehicle.hpp:312
GroupStatistics
Statistics and caches on the vehicles in a group.
Definition group.h:25
GroupStatistics::CountVehicle
static void CountVehicle(const Vehicle *v, int delta)
Update num_vehicle when adding or removing a vehicle.
Definition group_cmd.cpp:143
GroupStatistics::AddProfitLastYear
static void AddProfitLastYear(const Vehicle *v)
Add a vehicle's last year profit to the profit sum of its group.
Definition group_cmd.cpp:178
GroupStatistics::VehicleReachedMinAge
static void VehicleReachedMinAge(const Vehicle *v)
Add a vehicle to the profit sum of its group.
Definition group_cmd.cpp:190
GroupStatistics::GetNumEngines
uint16_t GetNumEngines(EngineID engine) const
Get number of vehicles of a specific engine ID.
Definition group_cmd.cpp:59
GroupStatistics::profit_last_year
Money profit_last_year
Sum of profits for all vehicles.
Definition group.h:26
GroupStatistics::GetAllGroup
static GroupStatistics & GetAllGroup(const Vehicle *v)
Returns the GroupStatistic for the ALL_GROUP of a vehicle type.
Definition group_cmd.cpp:103
GroupStatistics::UpdateAfterLoad
static void UpdateAfterLoad()
Update all caches after loading a game, changing NewGRF, etc.
Definition group_cmd.cpp:111
GroupStatistics::CountEngine
static void CountEngine(const Vehicle *v, int delta)
Update num_engines when adding/removing an engine.
Definition group_cmd.cpp:168
GroupStatistics::num_vehicle
uint16_t num_vehicle
Number of vehicles.
Definition group.h:29
GroupStatistics::profit_last_year_min_age
Money profit_last_year_min_age
Sum of profits for vehicles considered for profit statistics.
Definition group.h:27
GroupStatistics::UpdateAutoreplace
static void UpdateAutoreplace(CompanyID company)
Update autoreplace_defined and autoreplace_finished of all statistics of a company.
Definition group_cmd.cpp:231
GroupStatistics::UpdateProfits
static void UpdateProfits()
Recompute the profits for all groups.
Definition group_cmd.cpp:204
GroupStatistics::autoreplace_defined
bool autoreplace_defined
Are any autoreplace rules set?
Definition group.h:31
GroupStatistics::Get
static GroupStatistics & Get(CompanyID company, GroupID id_g, VehicleType type)
Returns the GroupStatistics for a specific group.
Definition group_cmd.cpp:73
GroupStatistics::autoreplace_finished
bool autoreplace_finished
Have all autoreplacement finished?
Definition group.h:32
GroupStatistics::num_engines
std::map< EngineID, uint16_t > num_engines
Caches the number of engines of each type the company owns.
Definition group.h:28
GroupStatistics::num_vehicle_min_age
uint16_t num_vehicle_min_age
Number of vehicles considered for profit statistics;.
Definition group.h:30
Group
Group data.
Definition group.h:73
Group::flags
GroupFlags flags
Group flags.
Definition group.h:78
Group::livery
Livery livery
Custom colour scheme for vehicles in this group.
Definition group.h:79
Group::parent
GroupID parent
Parent group.
Definition group.h:85
Group::statistics
GroupStatistics statistics
NOSAVE: Statistics and caches on the vehicles in the group.
Definition group.h:80
Group::vehicle_type
VehicleType vehicle_type
Vehicle type of the group.
Definition group.h:76
Group::name
std::string name
Group Name.
Definition group.h:74
Group::number
uint16_t number
Per-company group number.
Definition group.h:86
Group::owner
Owner owner
Group Owner.
Definition group.h:75
Group::children
FlatSet< GroupID > children
NOSAVE: child groups belonging to this group.
Definition group.h:82
Livery
Information about a particular livery.
Definition livery.h:79
Livery::in_use
Flags in_use
Livery flags.
Definition livery.h:86
Livery::colour2
Colours colour2
Second colour, for vehicles with 2CC support.
Definition livery.h:88
Livery::colour1
Colours colour1
First colour, for all vehicles.
Definition livery.h:87
Livery::Flag::Primary
@ Primary
Primary colour is set.
Livery::Flag::Secondary
@ Secondary
Secondary colour is set.
OrderBackup::ClearGroup
static void ClearGroup(GroupID group)
Clear the group of all backups having this group ID.
Definition order_backup.cpp:196
PoolID< uint16_t, struct EngineIDTag, 64000, 0xFFFF >
Pool::PoolItem<&_group_pool >::Iterate
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition pool_type.hpp:436
Pool::PoolItem<&_group_pool >::Get
static Titem * Get(auto index)
Returns Titem with given index.
Definition pool_type.hpp:387
Pool::PoolItem::index
Tindex index
Index of this pool item.
Definition pool_type.hpp:286
Pool::PoolItem<&_group_pool >::CanAllocateItem
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition pool_type.hpp:357
Pool::PoolItem<&_group_pool >::IsValidID
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition pool_type.hpp:376
Pool::PoolItem<&_group_pool >::GetIfValid
static Titem * GetIfValid(auto index)
Returns Titem with given index.
Definition pool_type.hpp:398
Pool
Base class for all pools.
Definition pool_type.hpp:133
SpecializedVehicle::Next
T * Next() const
Get next vehicle in the chain.
Definition vehicle_base.h:1049
SpecializedVehicle::From
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
Definition vehicle_base.h:1134
Train
'Train' is either a loco or a wagon.
Definition train.h:91
VehicleListIdentifier
The information about a vehicle list.
Definition vehiclelist.h:32
VehicleListIdentifier::ToWindowNumber
WindowNumber ToWindowNumber() const
Pack a VehicleListIdentifier in 32 bits so it can be used as unique WindowNumber.
Definition vehiclelist.cpp:23
Vehicle
Vehicle data structure.
Definition vehicle_base.h:205
Vehicle::engine_type
EngineID engine_type
The type of engine used for this vehicle.
Definition vehicle_base.h:278
Vehicle::economy_age
TimerGameEconomy::Date economy_age
Age in economy days.
Definition vehicle_base.h:254
Vehicle::group_id
GroupID group_id
Index of group Pool array.
Definition vehicle_base.h:321
Vehicle::IsEngineCountable
bool IsEngineCountable() const
Check if a vehicle is counted in num_engines in each company struct.
Definition vehicle.cpp:685
Vehicle::Next
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition vehicle_base.h:587
Vehicle::NextShared
Vehicle * NextShared() const
Get the next vehicle of the shared vehicle chain.
Definition vehicle_base.h:681
Vehicle::GetDisplayProfitLastYear
Money GetDisplayProfitLastYear() const
Gets the profit vehicle had last year.
Definition vehicle_base.h:578
Vehicle::IsFrontEngine
bool IsFrontEngine() const
Check if the vehicle is a front engine.
Definition vehicle_base.h:913
Vehicle::FirstShared
Vehicle * FirstShared() const
Get the first vehicle of this vehicle chain.
Definition vehicle_base.h:693
Vehicle::tile
TileIndex tile
Current tile index.
Definition vehicle_base.h:225
Vehicle::owner
Owner owner
Which company owns the vehicle?
Definition vehicle_base.h:270
train.h
Base for the train class.
vehicle_func.h
Functions related to vehicles.
VEHICLE_PROFIT_MIN_AGE
static const TimerGameEconomy::Date VEHICLE_PROFIT_MIN_AGE
Only vehicles older than this have a meaningful profit.
Definition vehicle_func.h:37
IsCompanyBuildableVehicleType
bool IsCompanyBuildableVehicleType(VehicleType type)
Is the given vehicle type buildable by a company?
Definition vehicle_func.h:228
GetWindowClassForVehicleType
WindowClass GetWindowClassForVehicleType(VehicleType vt)
Get WindowClass for vehicle list of given vehicle type.
Definition vehicle_gui.h:97
VehicleType
VehicleType
Available vehicle types.
Definition vehicle_type.h:22
VEH_ROAD
@ VEH_ROAD
Road vehicle type.
Definition vehicle_type.h:26
VEH_AIRCRAFT
@ VEH_AIRCRAFT
Aircraft vehicle type.
Definition vehicle_type.h:28
VEH_SHIP
@ VEH_SHIP
Ship vehicle type.
Definition vehicle_type.h:27
VEH_TRAIN
@ VEH_TRAIN
Train vehicle type.
Definition vehicle_type.h:25
VEH_COMPANY_END
@ VEH_COMPANY_END
Last company-ownable type.
Definition vehicle_type.h:30
GenerateVehicleSortList
bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli)
Generate a list of vehicles based on window type.
Definition vehiclelist.cpp:70
vehiclelist.h
Functions and type for generating vehicle lists.
VehicleList
std::vector< const Vehicle * > VehicleList
A list of vehicles.
Definition vehiclelist.h:68
VL_GROUP_LIST
@ VL_GROUP_LIST
Index is the group.
Definition vehiclelist.h:27
WaterTileType::Clear
@ Clear
Plain water.
CloseWindowById
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition window.cpp:1193
InvalidateWindowData
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition window.cpp:3294
SetWindowDirty
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3176
InvalidateWindowClassesData
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition window.cpp:3311
WC_COMPANY_COLOUR
@ WC_COMPANY_COLOUR
Company colour selection; Window numbers:
Definition window_type.h:235
WC_VEHICLE_DEPOT
@ WC_VEHICLE_DEPOT
Depot view; Window numbers:
Definition window_type.h:356
WC_REPLACE_VEHICLE
@ WC_REPLACE_VEHICLE
Replace vehicle window; Window numbers:
Definition window_type.h:223
WC_VEHICLE_DETAILS
@ WC_VEHICLE_DETAILS
Vehicle details; Window numbers:
Definition window_type.h:205
WC_VEHICLE_VIEW
@ WC_VEHICLE_VIEW
Vehicle view; Window numbers:
Definition window_type.h:344