OpenTTD Source 20241224-master-gf74b0cf984
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 <http://www.gnu.org/licenses/>.
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
27GroupPool _group_pool("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
50{
51 auto found = this->num_engines.find(engine);
52 if (found != std::end(this->num_engines)) return found->second;
53 return 0;
54}
55
64{
65 if (Group::IsValidID(id_g)) {
66 Group *g = Group::Get(id_g);
67 assert(g->owner == company);
68 assert(g->vehicle_type == type);
69 return g->statistics;
70 }
71
72 if (IsDefaultGroupID(id_g)) return Company::Get(company)->group_default[type];
73 if (IsAllGroupID(id_g)) return Company::Get(company)->group_all[type];
74
75 NOT_REACHED();
76}
77
84{
85 return GroupStatistics::Get(v->owner, v->group_id, v->type);
86}
87
97
102{
103 /* Set up the engine count for all companies */
104 for (Company *c : Company::Iterate()) {
105 for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
106 c->group_all[type].Clear();
107 c->group_default[type].Clear();
108 }
109 }
110
111 /* Recalculate */
112 for (Group *g : Group::Iterate()) {
113 g->statistics.Clear();
114 }
115
116 for (const Vehicle *v : Vehicle::Iterate()) {
117 if (!v->IsEngineCountable()) continue;
118
120 if (v->IsPrimaryVehicle()) GroupStatistics::CountVehicle(v, 1);
121 }
122
123 for (const Company *c : Company::Iterate()) {
125 }
126}
127
133/* static */ void GroupStatistics::CountVehicle(const Vehicle *v, int delta)
134{
135 assert(delta == 1 || delta == -1);
136
139
140 stats_all.num_vehicle += delta;
141 stats_all.profit_last_year += v->GetDisplayProfitLastYear() * delta;
142 stats.num_vehicle += delta;
143 stats.profit_last_year += v->GetDisplayProfitLastYear() * delta;
144
146 stats_all.num_vehicle_min_age += delta;
147 stats_all.profit_last_year_min_age += v->GetDisplayProfitLastYear() * delta;
148 stats.num_vehicle_min_age += delta;
150 }
151}
152
158/* static */ void GroupStatistics::CountEngine(const Vehicle *v, int delta)
159{
160 assert(delta == 1 || delta == -1);
163}
164
176
190
195{
196 /* Set up the engine count for all companies */
197 for (Company *c : Company::Iterate()) {
198 for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
199 c->group_all[type].ClearProfits();
200 c->group_default[type].ClearProfits();
201 }
202 }
203
204 /* Recalculate */
205 for (Group *g : Group::Iterate()) {
206 g->statistics.ClearProfits();
207 }
208
209 for (const Vehicle *v : Vehicle::Iterate()) {
210 if (v->IsPrimaryVehicle()) {
213 }
214 }
215}
216
222{
223 /* Set up the engine count for all companies */
224 Company *c = Company::Get(company);
225 for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
226 c->group_all[type].ClearAutoreplace();
227 c->group_default[type].ClearAutoreplace();
228 }
229
230 /* Recalculate */
231 for (Group *g : Group::Iterate()) {
232 if (g->owner != company) continue;
233 g->statistics.ClearAutoreplace();
234 }
235
236 for (EngineRenewList erl = c->engine_renew_list; erl != nullptr; erl = erl->next) {
237 const Engine *e = Engine::Get(erl->from);
238 GroupStatistics &stats = GroupStatistics::Get(company, erl->group_id, e->type);
239 if (!stats.autoreplace_defined) {
240 stats.autoreplace_defined = true;
241 stats.autoreplace_finished = true;
242 }
243 if (GetGroupNumEngines(company, erl->group_id, erl->from) > 0) stats.autoreplace_finished = false;
244 }
245}
246
254static inline void UpdateNumEngineGroup(const Vehicle *v, GroupID old_g, GroupID new_g)
255{
256 if (old_g != new_g) {
257 /* Decrease the num engines in the old group */
259
260 /* Increase the num engines in the new group */
262 }
263}
264
265
266const Livery *GetParentLivery(const Group *g)
267{
268 if (g->parent == INVALID_GROUP) {
269 const Company *c = Company::Get(g->owner);
270 return &c->livery[LS_DEFAULT];
271 }
272
273 const Group *pg = Group::Get(g->parent);
274 return &pg->livery;
275}
276
277
283static void PropagateChildLivery(const Group *g, bool reset_cache)
284{
285 if (reset_cache) {
286 /* Company colour data is indirectly cached. */
287 for (Vehicle *v : Vehicle::Iterate()) {
288 if (v->group_id == g->index && (!v->IsGroundVehicle() || v->IsFrontEngine())) {
289 for (Vehicle *u = v; u != nullptr; u = u->Next()) {
290 u->colourmap = PAL_NONE;
291 u->InvalidateNewGRFCache();
292 }
293 }
294 }
295 }
296
297 for (Group *cg : Group::Iterate()) {
298 if (cg->parent == g->index) {
299 if (!HasBit(cg->livery.in_use, 0)) cg->livery.colour1 = g->livery.colour1;
300 if (!HasBit(cg->livery.in_use, 1)) cg->livery.colour2 = g->livery.colour2;
301 PropagateChildLivery(cg, reset_cache);
302 }
303 }
304}
305
312{
313 for (Group *g : Group::Iterate()) {
314 if (g->owner == c->index && g->parent == INVALID_GROUP) {
315 if (!HasBit(g->livery.in_use, 0)) g->livery.colour1 = c->livery[LS_DEFAULT].colour1;
316 if (!HasBit(g->livery.in_use, 1)) g->livery.colour2 = c->livery[LS_DEFAULT].colour2;
317 PropagateChildLivery(g, false);
318 }
319 }
320}
321
322Group::Group(Owner owner)
323{
324 this->owner = owner;
325 this->folded = false;
326}
327
328
336std::tuple<CommandCost, GroupID> CmdCreateGroup(DoCommandFlag flags, VehicleType vt, GroupID parent_group)
337{
339
341
342 const Group *pg = Group::GetIfValid(parent_group);
343 if (pg != nullptr) {
344 if (pg->owner != _current_company) return { CMD_ERROR, INVALID_GROUP };
345 if (pg->vehicle_type != vt) return { CMD_ERROR, INVALID_GROUP };
346 }
347
348 if (flags & DC_EXEC) {
349 Group *g = new Group(_current_company);
350 g->vehicle_type = vt;
352
353 Company *c = Company::Get(g->owner);
354 g->number = c->freegroups.UseID(c->freegroups.NextID());
355 if (pg == nullptr) {
356 g->livery.colour1 = c->livery[LS_DEFAULT].colour1;
357 g->livery.colour2 = c->livery[LS_DEFAULT].colour2;
359 } else {
360 g->parent = pg->index;
361 g->livery.colour1 = pg->livery.colour1;
362 g->livery.colour2 = pg->livery.colour2;
363 g->flags = pg->flags;
364 }
365
368
369 return { CommandCost(), g->index };
370 }
371
372 return { CommandCost(), INVALID_GROUP};
373}
374
375
383{
384 Group *g = Group::GetIfValid(group_id);
385 if (g == nullptr || g->owner != _current_company) return CMD_ERROR;
386
387 /* Remove all vehicles from the group */
389
390 /* Delete sub-groups */
391 for (const Group *gp : Group::Iterate()) {
392 if (gp->parent == g->index) {
393 Command<CMD_DELETE_GROUP>::Do(flags, gp->index);
394 }
395 }
396
397 if (flags & DC_EXEC) {
398 /* Update backupped orders if needed */
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 (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
413
414 /* Delete the Replace Vehicle Windows */
416 delete g;
417
420 }
421
422 return CommandCost();
423}
424
434CommandCost CmdAlterGroup(DoCommandFlag flags, AlterGroupMode mode, GroupID group_id, GroupID parent_id, const std::string &text)
435{
436 Group *g = Group::GetIfValid(group_id);
437 if (g == nullptr || g->owner != _current_company) return CMD_ERROR;
438
439 if (mode == AlterGroupMode::Rename) {
440 /* Rename group */
441 bool reset = text.empty();
442
443 if (!reset) {
445 }
446
447 if (flags & DC_EXEC) {
448 /* Assign the new one */
449 if (reset) {
450 g->name.clear();
451 } else {
452 g->name = text;
453 }
454 }
455 } else if (mode == AlterGroupMode::SetParent) {
456 /* Set group parent */
457 const Group *pg = Group::GetIfValid(parent_id);
458
459 if (pg != nullptr) {
460 if (pg->owner != _current_company) return CMD_ERROR;
461 if (pg->vehicle_type != g->vehicle_type) return CMD_ERROR;
462
463 /* Ensure request parent isn't child of group.
464 * This is the only place that infinite loops are prevented. */
465 if (GroupIsInGroup(pg->index, g->index)) return CommandCost(STR_ERROR_GROUP_CAN_T_SET_PARENT_RECURSION);
466 }
467
468 if (flags & DC_EXEC) {
469 g->parent = (pg == nullptr) ? INVALID_GROUP : pg->index;
471
472 if (!HasBit(g->livery.in_use, 0) || !HasBit(g->livery.in_use, 1)) {
473 /* Update livery with new parent's colours if either colour is default. */
474 const Livery *livery = GetParentLivery(g);
475 if (!HasBit(g->livery.in_use, 0)) g->livery.colour1 = livery->colour1;
476 if (!HasBit(g->livery.in_use, 1)) g->livery.colour2 = livery->colour2;
477
478 PropagateChildLivery(g, true);
480 }
481 }
482 } else {
483 return CMD_ERROR;
484 }
485
486 if (flags & DC_EXEC) {
492 }
493
494 return CommandCost();
495}
496
497
503static void AddVehicleToGroup(Vehicle *v, GroupID new_g)
504{
506
507 switch (v->type) {
508 default: NOT_REACHED();
509 case VEH_TRAIN:
510 SetTrainGroupID(Train::From(v), new_g);
511 break;
512
513 case VEH_ROAD:
514 case VEH_SHIP:
515 case VEH_AIRCRAFT:
516 if (v->IsEngineCountable()) UpdateNumEngineGroup(v, v->group_id, new_g);
517 v->group_id = new_g;
518 for (Vehicle *u = v; u != nullptr; u = u->Next()) {
519 u->colourmap = PAL_NONE;
520 u->InvalidateNewGRFCache();
521 u->UpdateViewport(true);
522 }
523 break;
524 }
525
527}
528
537std::tuple<CommandCost, GroupID> CmdAddVehicleGroup(DoCommandFlag flags, GroupID group_id, VehicleID veh_id, bool add_shared, const VehicleListIdentifier &vli)
538{
539 GroupID new_g = group_id;
540 if (!Group::IsValidID(new_g) && !IsDefaultGroupID(new_g) && new_g != NEW_GROUP) return { CMD_ERROR, INVALID_GROUP };
541
542 VehicleList list;
543 if (veh_id == INVALID_VEHICLE && vli.Valid()) {
544 if (!GenerateVehicleSortList(&list, vli) || list.empty()) return { CMD_ERROR, INVALID_GROUP };
545 } else {
546 Vehicle *v = Vehicle::GetIfValid(veh_id);
547 if (v == nullptr) return { CMD_ERROR, INVALID_GROUP };
548 list.push_back(v);
549 }
550
551 VehicleType vtype = list.front()->type;
552 for (const Vehicle *v : list) {
553 if (v->owner != _current_company || !v->IsPrimaryVehicle()) return { CMD_ERROR, INVALID_GROUP };
554 }
555
556 if (Group::IsValidID(new_g)) {
557 Group *g = Group::Get(new_g);
558 if (g->owner != _current_company || g->vehicle_type != vtype) return { CMD_ERROR, INVALID_GROUP };
559 }
560
561 if (new_g == NEW_GROUP) {
562 /* Create new group. */
563 auto [ret, new_group_id] = CmdCreateGroup(flags, vtype, INVALID_GROUP);
564 if (ret.Failed()) return { ret, new_group_id };
565
566 new_g = new_group_id;
567 }
568
569 if (flags & DC_EXEC) {
570 for (const Vehicle *vc : list) {
571 /* VehicleList is const but we need to modify the vehicle. */
572 Vehicle *v = Vehicle::Get(vc->index);
573 AddVehicleToGroup(v, new_g);
574
575 if (add_shared) {
576 /* Add vehicles in the shared order list as well. */
577 for (Vehicle *v2 = v->FirstShared(); v2 != nullptr; v2 = v2->NextShared()) {
578 if (v2->group_id != new_g) AddVehicleToGroup(v2, new_g);
579 }
580 }
581
587 }
588
590
591 /* Update the Replace Vehicle Windows */
594 }
595
596 return { CommandCost(), new_g };
597}
598
607{
608 if (!Group::IsValidID(id_g) || !IsCompanyBuildableVehicleType(type)) return CMD_ERROR;
609
610 if (flags & DC_EXEC) {
611 /* Find the first front engine which belong to the group id_g
612 * then add all shared vehicles of this front engine to the group id_g */
613 for (const Vehicle *v : Vehicle::Iterate()) {
614 if (v->type == type && v->IsPrimaryVehicle()) {
615 if (v->group_id != id_g) continue;
616
617 /* For each shared vehicles add it to the group */
618 for (Vehicle *v2 = v->FirstShared(); v2 != nullptr; v2 = v2->NextShared()) {
619 if (v2->group_id != id_g) Command<CMD_ADD_VEHICLE_GROUP>::Do(flags, id_g, v2->index, false, VehicleListIdentifier{});
620 }
621 }
622 }
623
625 }
626
627 return CommandCost();
628}
629
630
638{
639 Group *g = Group::GetIfValid(group_id);
640
641 if (g == nullptr || g->owner != _current_company) return CMD_ERROR;
642
643 if (flags & DC_EXEC) {
644 /* Find each Vehicle that belongs to the group old_g and add it to the default group */
645 for (const Vehicle *v : Vehicle::Iterate()) {
646 if (v->IsPrimaryVehicle()) {
647 if (v->group_id != group_id) continue;
648
649 /* Add The Vehicle to the default group */
651 }
652 }
653
655 }
656
657 return CommandCost();
658}
659
667CommandCost CmdSetGroupLivery(DoCommandFlag flags, GroupID group_id, bool primary, Colours colour)
668{
669 Group *g = Group::GetIfValid(group_id);
670
671 if (g == nullptr || g->owner != _current_company) return CMD_ERROR;
672
673 if (colour >= COLOUR_END && colour != INVALID_COLOUR) return CMD_ERROR;
674
675 if (flags & DC_EXEC) {
676 if (primary) {
677 AssignBit(g->livery.in_use, 0, colour != INVALID_COLOUR);
678 if (colour == INVALID_COLOUR) colour = GetParentLivery(g)->colour1;
679 g->livery.colour1 = colour;
680 } else {
681 AssignBit(g->livery.in_use, 1, colour != INVALID_COLOUR);
682 if (colour == INVALID_COLOUR) colour = GetParentLivery(g)->colour2;
683 g->livery.colour2 = colour;
684 }
685
686 PropagateChildLivery(g, true);
688 }
689
690 return CommandCost();
691}
692
698static void SetGroupFlag(Group *g, GroupFlags flag, bool set, bool children)
699{
700 if (set) {
701 SetBit(g->flags, flag);
702 } else {
703 ClrBit(g->flags, flag);
704 }
705
706 if (!children) return;
707
708 for (Group *pg : Group::Iterate()) {
709 if (pg->parent == g->index) SetGroupFlag(pg, flag, set, true);
710 }
711}
712
722CommandCost CmdSetGroupFlag(DoCommandFlag flags, GroupID group_id, GroupFlags flag, bool value, bool recursive)
723{
724 Group *g = Group::GetIfValid(group_id);
725 if (g == nullptr || g->owner != _current_company) return CMD_ERROR;
726
727 if (flag >= GroupFlags::GF_END) return CMD_ERROR;
728
729 if (flags & DC_EXEC) {
730 SetGroupFlag(g, flag, value, recursive);
731
734 }
735
736 return CommandCost();
737}
738
746{
747 if (!Group::IsValidID(new_g) && !IsDefaultGroupID(new_g)) return;
748
749 assert(v->IsFrontEngine() || IsDefaultGroupID(new_g));
750
751 for (Vehicle *u = v; u != nullptr; u = u->Next()) {
752 if (u->IsEngineCountable()) UpdateNumEngineGroup(u, u->group_id, new_g);
753
754 u->group_id = new_g;
755 u->colourmap = PAL_NONE;
756 u->InvalidateNewGRFCache();
757 u->UpdateViewport(true);
758 }
759
760 /* Update the Replace Vehicle Windows */
763}
764
765
774{
775 assert(v->IsFrontEngine() || v->IsFreeWagon());
776
778 for (Vehicle *u = v; u != nullptr; u = u->Next()) {
779 if (u->IsEngineCountable()) UpdateNumEngineGroup(u, u->group_id, new_g);
780
781 u->group_id = new_g;
782 u->colourmap = PAL_NONE;
783 u->InvalidateNewGRFCache();
784 }
785
786 /* Update the Replace Vehicle Windows */
789}
790
800{
801 uint count = 0;
802 const Engine *e = Engine::Get(id_e);
803 for (const Group *g : Group::Iterate()) {
804 if (g->parent == id_g) count += GetGroupNumEngines(company, g->index, id_e);
805 }
806 return count + GroupStatistics::Get(company, id_g, e->type).GetNumEngines(id_e);
807}
808
818{
819 uint count = 0;
820 for (const Group *g : Group::Iterate()) {
821 if (g->parent == id_g) count += GetGroupNumVehicle(company, g->index, type);
822 }
823 return count + GroupStatistics::Get(company, id_g, type).num_vehicle;
824}
825
835{
836 uint count = 0;
837 for (const Group *g : Group::Iterate()) {
838 if (g->parent == id_g) count += GetGroupNumVehicleMinAge(company, g->index, type);
839 }
840 return count + GroupStatistics::Get(company, id_g, type).num_vehicle_min_age;
841}
842
852{
853 Money sum = 0;
854 for (const Group *g : Group::Iterate()) {
855 if (g->parent == id_g) sum += GetGroupProfitLastYearMinAge(company, g->index, type);
856 }
857 return sum + GroupStatistics::Get(company, id_g, type).profit_last_year_min_age;
858}
859
860void RemoveAllGroupsForCompany(const CompanyID company)
861{
862 for (Group *g : Group::Iterate()) {
863 if (company == g->owner) delete g;
864 }
865}
866
867
874bool GroupIsInGroup(GroupID search, GroupID group)
875{
876 if (!Group::IsValidID(search)) return search == group;
877
878 do {
879 if (search == group) return true;
880 search = Group::Get(search)->parent;
881 } while (search != INVALID_GROUP);
882
883 return false;
884}
Base class for autoreplaces/autorenews.
Functions related to autoreplacing.
CommandCost RemoveEngineReplacementForCompany(Company *c, EngineID engine, GroupID group, DoCommandFlag flags)
Remove an engine replacement for the company.
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T AssignBit(T &x, const uint8_t y, bool value)
Assigns a bit in a variable.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
Common return value for all commands.
UnitID UseID(UnitID index)
Use a unit number.
Definition vehicle.cpp:1863
void ReleaseID(UnitID index)
Release a unit number.
Definition vehicle.cpp:1880
UnitID NextID() const
Find first unused unit number.
Definition vehicle.cpp:1848
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
DoCommandFlag
List of flags for a command.
@ DC_EXEC
execute the given command
CompanyID _current_company
Company currently doing an action.
Functions related to companies.
Owner
Enum for all companies/owners.
@ MAX_COMPANIES
Maximum number of companies.
uint16_t EngineID
Unique identification number of an engine.
Definition engine_type.h:21
GroupFlags
Definition group.h:65
@ GF_REPLACE_WAGON_REMOVAL
If set, autoreplace will perform wagon removal on vehicles in this group.
Definition group.h:67
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.
GroupPool _group_pool
Pool of groups.
bool IsAllGroupID(GroupID id_g)
Checks if a GroupID stands for all vehicles of a company.
Definition group.h:100
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...
CommandCost CmdAlterGroup(DoCommandFlag flags, AlterGroupMode mode, GroupID group_id, GroupID parent_id, const std::string &text)
Alter a group.
CommandCost CmdSetGroupFlag(DoCommandFlag flags, GroupID group_id, GroupFlags flag, bool value, bool recursive)
(Un)set group flag from a group
CommandCost CmdRemoveAllVehiclesGroup(DoCommandFlag flags, GroupID group_id)
Remove all vehicles from a group.
void UpdateCompanyGroupLiveries(const Company *c)
Update group liveries for a company.
CommandCost CmdDeleteGroup(DoCommandFlag flags, GroupID group_id)
Add all vehicles in the given group to the default group and then deletes the group.
void SetTrainGroupID(Train *v, GroupID new_g)
Affect the groupID of a train to new_g.
std::tuple< CommandCost, GroupID > CmdAddVehicleGroup(DoCommandFlag flags, GroupID group_id, VehicleID veh_id, bool add_shared, const VehicleListIdentifier &vli)
Add a vehicle to a group.
std::tuple< CommandCost, GroupID > CmdCreateGroup(DoCommandFlag flags, VehicleType vt, GroupID parent_group)
Create a new vehicle group.
void UpdateTrainGroupID(Train *v)
Recalculates the groupID of a train.
static void SetGroupFlag(Group *g, GroupFlags flag, bool set, bool children)
Set group flag for a group and its sub-groups.
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.
static void UpdateNumEngineGroup(const Vehicle *v, GroupID old_g, GroupID new_g)
Update the num engines of a groupID.
CommandCost CmdAddSharedVehicleGroup(DoCommandFlag flags, GroupID id_g, VehicleType type)
Add all shared vehicles of all vehicles from a group.
static void AddVehicleToGroup(Vehicle *v, GroupID new_g)
Do add a vehicle to a group.
static void PropagateChildLivery(const Group *g, bool reset_cache)
Propagate a livery change to a group's children, and optionally update cached vehicle colourmaps.
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.
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...
bool GroupIsInGroup(GroupID search, GroupID group)
Test if GroupID group is a descendant of (or is) GroupID search.
CommandCost CmdSetGroupLivery(DoCommandFlag flags, GroupID group_id, bool primary, Colours colour)
Set the livery for a vehicle group.
Command definitions related to engine groups.
AlterGroupMode
Action for CmdAlterGroup.
Definition group_cmd.h:23
@ Rename
Change group name.
@ SetParent
Change group parent.
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1529
uint16_t GroupID
Type for all group identifiers.
Definition group_type.h:13
static const GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition group_type.h:17
static const GroupID NEW_GROUP
Sentinel for a to-be-created group.
Definition group_type.h:15
static const uint MAX_LENGTH_GROUP_NAME_CHARS
The maximum length of a group name in characters including '\0'.
Definition group_type.h:20
static const GroupID INVALID_GROUP
Sentinel for invalid groups.
Definition group_type.h:18
static const GroupID ALL_GROUP
All vehicles are in this group.
Definition group_type.h:16
Functions related to order backups.
Some methods of Pool are placed here in order to reduce compilation time and binary size.
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
A number of safeguards to prevent using unsafe methods.
Definition of base types and functions in a cross-platform compatible way.
size_t Utf8StringLength(const char *s)
Get the length of an UTF-8 encoded string in number of characters and thus not the number of bytes th...
Definition string.cpp:359
Functions related to low-level strings.
VehicleType type
Type of vehicle.
CompanySettings settings
settings specific for each company
EngineRenewList engine_renew_list
Engine renewals of this company.
bool renew_keep_length
sell some wagons if after autoreplace the train is longer than before
GroupStatistics group_default[VEH_COMPANY_END]
NOSAVE: Statistics for the DEFAULT_GROUP group.
GroupStatistics group_all[VEH_COMPANY_END]
NOSAVE: Statistics for the ALL_GROUP group.
Struct to store engine replacements.
VehicleType type
Vehicle type, ie VEH_ROAD, VEH_TRAIN, etc.
Definition engine_base.h:60
bool IsFreeWagon() const
Check if the vehicle is a free wagon (got no engine in front of it).
Statistics and caches on the vehicles in a group.
Definition group.h:24
static void CountVehicle(const Vehicle *v, int delta)
Update num_vehicle when adding or removing a vehicle.
static void AddProfitLastYear(const Vehicle *v)
Add a vehicle's last year profit to the profit sum of its group.
static void VehicleReachedMinAge(const Vehicle *v)
Add a vehicle to the profit sum of its group.
uint16_t GetNumEngines(EngineID engine) const
Get number of vehicles of a specific engine ID.
Definition group_cmd.cpp:49
Money profit_last_year
Sum of profits for all vehicles.
Definition group.h:25
static GroupStatistics & GetAllGroup(const Vehicle *v)
Returns the GroupStatistic for the ALL_GROUPO of a vehicle type.
Definition group_cmd.cpp:93
static void UpdateAfterLoad()
Update all caches after loading a game, changing NewGRF, etc.
static void CountEngine(const Vehicle *v, int delta)
Update num_engines when adding/removing an engine.
uint16_t num_vehicle
Number of vehicles.
Definition group.h:28
Money profit_last_year_min_age
Sum of profits for vehicles considered for profit statistics.
Definition group.h:26
static void UpdateAutoreplace(CompanyID company)
Update autoreplace_defined and autoreplace_finished of all statistics of a company.
static void UpdateProfits()
Recompute the profits for all groups.
bool autoreplace_defined
Are any autoreplace rules set?
Definition group.h:30
static GroupStatistics & Get(CompanyID company, GroupID id_g, VehicleType type)
Returns the GroupStatistics for a specific group.
Definition group_cmd.cpp:63
bool autoreplace_finished
Have all autoreplacement finished?
Definition group.h:31
std::map< EngineID, uint16_t > num_engines
Caches the number of engines of each type the company owns.
Definition group.h:27
uint16_t num_vehicle_min_age
Number of vehicles considered for profit statistics;.
Definition group.h:29
Group data.
Definition group.h:72
Livery livery
Custom colour scheme for vehicles in this group.
Definition group.h:78
GroupID parent
Parent group.
Definition group.h:83
GroupStatistics statistics
NOSAVE: Statistics and caches on the vehicles in the group.
Definition group.h:79
VehicleType vehicle_type
Vehicle type of the group.
Definition group.h:75
bool folded
NOSAVE: Is this group folded in the group view?
Definition group.h:81
std::string name
Group Name.
Definition group.h:73
uint16_t number
Per-company group number.
Definition group.h:84
Owner owner
Group Owner.
Definition group.h:74
uint8_t flags
Group flags.
Definition group.h:77
Information about a particular livery.
Definition livery.h:78
Colours colour2
Second colour, for vehicles with 2CC support.
Definition livery.h:81
Colours colour1
First colour, for all vehicles.
Definition livery.h:80
uint8_t in_use
Bit 0 set if this livery should override the default livery first colour, Bit 1 for the second colour...
Definition livery.h:79
static void ClearGroup(GroupID group)
Clear the group of all backups having this group ID.
Tindex index
Index of this pool item.
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
static Titem * Get(size_t index)
Returns Titem with given index.
Base class for all pools.
Definition pool_type.hpp:80
T * Next() const
Get next vehicle in the chain.
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
'Train' is either a loco or a wagon.
Definition train.h:89
The information about a vehicle list.
Definition vehiclelist.h:28
uint32_t Pack() const
Pack a VehicleListIdentifier in a single uint32.
Vehicle data structure.
EngineID engine_type
The type of engine used for this vehicle.
TimerGameEconomy::Date economy_age
Age in economy days.
GroupID group_id
Index of group Pool array.
bool IsEngineCountable() const
Check if a vehicle is counted in num_engines in each company struct.
Definition vehicle.cpp:714
debug_inline bool IsFrontEngine() const
Check if the vehicle is a front engine.
Vehicle * Next() const
Get the next vehicle of this vehicle.
Vehicle * NextShared() const
Get the next vehicle of the shared vehicle chain.
Money GetDisplayProfitLastYear() const
Gets the profit vehicle had last year.
Vehicle * FirstShared() const
Get the first vehicle of this vehicle chain.
TileIndex tile
Current tile index.
Owner owner
Which company owns the vehicle?
Base for the train class.
Functions related to vehicles.
static const TimerGameEconomy::Date VEHICLE_PROFIT_MIN_AGE
Only vehicles older than this have a meaningful profit.
bool IsCompanyBuildableVehicleType(VehicleType type)
Is the given vehicle type buildable by a company?
WindowClass GetWindowClassForVehicleType(VehicleType vt)
Get WindowClass for vehicle list of given vehicle type.
Definition vehicle_gui.h:97
VehicleType
Available vehicle types.
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_TRAIN
Train vehicle type.
@ VEH_COMPANY_END
Last company-ownable type.
uint32_t VehicleID
The type all our vehicle IDs have.
static const VehicleID INVALID_VEHICLE
Constant representing a non-existing vehicle.
bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli)
Generate a list of vehicles based on window type.
Functions and type for generating vehicle lists.
std::vector< const Vehicle * > VehicleList
A list of vehicles.
Definition vehiclelist.h:54
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:1140
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:3219
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3101
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:3236
@ WC_COMPANY_COLOUR
Company colour selection; Window numbers:
@ WC_VEHICLE_DEPOT
Depot view; Window numbers:
@ WC_REPLACE_VEHICLE
Replace vehicle window; Window numbers:
@ WC_VEHICLE_DETAILS
Vehicle details; Window numbers:
@ WC_VEHICLE_VIEW
Vehicle view; Window numbers: