OpenTTD
vehiclelist.cpp
Go to the documentation of this file.
1 /* $Id: vehiclelist.cpp 26679 2014-07-08 20:07:21Z frosch $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #include "stdafx.h"
13 #include "train.h"
14 #include "vehiclelist.h"
15 #include "group.h"
16 
17 #include "safeguards.h"
18 
24 {
25  byte c = this->company == OWNER_NONE ? 0xF : (byte)this->company;
26  assert(c < (1 << 4));
27  assert(this->vtype < (1 << 2));
28  assert(this->index < (1 << 20));
29  assert(this->type < VLT_END);
30  assert_compile(VLT_END <= (1 << 3));
31 
32  return c << 28 | this->type << 23 | this->vtype << 26 | this->index;
33 }
34 
41 {
42  byte c = GB(data, 28, 4);
43  this->company = c == 0xF ? OWNER_NONE : (CompanyID)c;
44  this->type = (VehicleListType)GB(data, 23, 3);
45  this->vtype = (VehicleType)GB(data, 26, 2);
46  this->index = GB(data, 0, 20);
47 
48  return this->type < VLT_END;
49 }
50 
56 {
57  bool ret = this->Unpack(data);
58  assert(ret);
59 }
60 
69 void BuildDepotVehicleList(VehicleType type, TileIndex tile, VehicleList *engines, VehicleList *wagons, bool individual_wagons)
70 {
71  engines->Clear();
72  if (wagons != NULL && wagons != engines) wagons->Clear();
73 
74  const Vehicle *v;
75  FOR_ALL_VEHICLES(v) {
76  /* General tests for all vehicle types */
77  if (v->type != type) continue;
78  if (v->tile != tile) continue;
79 
80  switch (type) {
81  case VEH_TRAIN: {
82  const Train *t = Train::From(v);
83  if (t->IsArticulatedPart() || t->IsRearDualheaded()) continue;
84  if (t->track != TRACK_BIT_DEPOT) continue;
85  if (wagons != NULL && t->First()->IsFreeWagon()) {
86  if (individual_wagons || t->IsFreeWagon()) *wagons->Append() = t;
87  continue;
88  }
89  break;
90  }
91 
92  default:
93  if (!v->IsInDepot()) continue;
94  break;
95  }
96 
97  if (!v->IsPrimaryVehicle()) continue;
98 
99  *engines->Append() = v;
100  }
101 
102  /* Ensure the lists are not wasting too much space. If the lists are fresh
103  * (i.e. built within a command) then this will actually do nothing. */
104  engines->Compact();
105  if (wagons != NULL && wagons != engines) wagons->Compact();
106 }
107 
115 {
116  list->Clear();
117 
118  const Vehicle *v;
119 
120  switch (vli.type) {
121  case VL_STATION_LIST:
122  FOR_ALL_VEHICLES(v) {
123  if (v->type == vli.vtype && v->IsPrimaryVehicle()) {
124  const Order *order;
125 
126  FOR_VEHICLE_ORDERS(v, order) {
127  if ((order->IsType(OT_GOTO_STATION) || order->IsType(OT_GOTO_WAYPOINT) || order->IsType(OT_IMPLICIT))
128  && order->GetDestination() == vli.index) {
129  *list->Append() = v;
130  break;
131  }
132  }
133  }
134  }
135  break;
136 
137  case VL_SHARED_ORDERS:
138  /* Add all vehicles from this vehicle's shared order list */
139  v = Vehicle::GetIfValid(vli.index);
140  if (v == NULL || v->type != vli.vtype || !v->IsPrimaryVehicle()) return false;
141 
142  for (; v != NULL; v = v->NextShared()) {
143  *list->Append() = v;
144  }
145  break;
146 
147  case VL_GROUP_LIST:
148  if (vli.index != ALL_GROUP) {
149  FOR_ALL_VEHICLES(v) {
150  if (v->type == vli.vtype && v->IsPrimaryVehicle() &&
151  v->owner == vli.company && GroupIsInGroup(v->group_id, vli.index)) {
152  *list->Append() = v;
153  }
154  }
155  break;
156  }
157  /* FALL THROUGH */
158 
159  case VL_STANDARD:
160  FOR_ALL_VEHICLES(v) {
161  if (v->type == vli.vtype && v->owner == vli.company && v->IsPrimaryVehicle()) {
162  *list->Append() = v;
163  }
164  }
165  break;
166 
167  case VL_DEPOT_LIST:
168  FOR_ALL_VEHICLES(v) {
169  if (v->type == vli.vtype && v->IsPrimaryVehicle()) {
170  const Order *order;
171 
172  FOR_VEHICLE_ORDERS(v, order) {
173  if (order->IsType(OT_GOTO_DEPOT) && !(order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) && order->GetDestination() == vli.index) {
174  *list->Append() = v;
175  break;
176  }
177  }
178  }
179  }
180  break;
181 
182  default: return false;
183  }
184 
185  list->Compact();
186  return true;
187 }