OpenTTD
vehicle.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 "error.h"
12 #include "roadveh.h"
13 #include "ship.h"
14 #include "spritecache.h"
15 #include "timetable.h"
16 #include "viewport_func.h"
17 #include "news_func.h"
18 #include "command_func.h"
19 #include "company_func.h"
20 #include "train.h"
21 #include "aircraft.h"
22 #include "newgrf_debug.h"
23 #include "newgrf_sound.h"
24 #include "newgrf_station.h"
25 #include "group_gui.h"
26 #include "strings_func.h"
27 #include "zoom_func.h"
28 #include "date_func.h"
29 #include "vehicle_func.h"
30 #include "autoreplace_func.h"
31 #include "autoreplace_gui.h"
32 #include "station_base.h"
33 #include "ai/ai.hpp"
34 #include "depot_func.h"
35 #include "network/network.h"
36 #include "core/pool_func.hpp"
37 #include "economy_base.h"
38 #include "articulated_vehicles.h"
39 #include "roadstop_base.h"
40 #include "core/random_func.hpp"
41 #include "core/backup_type.hpp"
42 #include "order_backup.h"
43 #include "sound_func.h"
44 #include "effectvehicle_func.h"
45 #include "effectvehicle_base.h"
46 #include "vehiclelist.h"
47 #include "bridge_map.h"
48 #include "tunnel_map.h"
49 #include "depot_map.h"
50 #include "gamelog.h"
51 #include "linkgraph/linkgraph.h"
52 #include "linkgraph/refresh.h"
53 #include "framerate_type.h"
54 
55 #include "table/strings.h"
56 
57 #include "safeguards.h"
58 
59 /* Number of bits in the hash to use from each vehicle coord */
60 static const uint GEN_HASHX_BITS = 6;
61 static const uint GEN_HASHY_BITS = 6;
62 
63 /* Size of each hash bucket */
64 static const uint GEN_HASHX_BUCKET_BITS = 7;
65 static const uint GEN_HASHY_BUCKET_BITS = 6;
66 
67 /* Compute hash for vehicle coord */
68 #define GEN_HASHX(x) GB((x), GEN_HASHX_BUCKET_BITS + ZOOM_LVL_SHIFT, GEN_HASHX_BITS)
69 #define GEN_HASHY(y) (GB((y), GEN_HASHY_BUCKET_BITS + ZOOM_LVL_SHIFT, GEN_HASHY_BITS) << GEN_HASHX_BITS)
70 #define GEN_HASH(x, y) (GEN_HASHY(y) + GEN_HASHX(x))
71 
72 /* Maximum size until hash repeats */
73 static const int GEN_HASHX_SIZE = 1 << (GEN_HASHX_BUCKET_BITS + GEN_HASHX_BITS + ZOOM_LVL_SHIFT);
74 static const int GEN_HASHY_SIZE = 1 << (GEN_HASHY_BUCKET_BITS + GEN_HASHY_BITS + ZOOM_LVL_SHIFT);
75 
76 /* Increments to reach next bucket in hash table */
77 static const int GEN_HASHX_INC = 1;
78 static const int GEN_HASHY_INC = 1 << GEN_HASHX_BITS;
79 
80 /* Mask to wrap-around buckets */
81 static const uint GEN_HASHX_MASK = (1 << GEN_HASHX_BITS) - 1;
82 static const uint GEN_HASHY_MASK = ((1 << GEN_HASHY_BITS) - 1) << GEN_HASHX_BITS;
83 
84 VehicleID _new_vehicle_id;
87 
88 
90 VehiclePool _vehicle_pool("Vehicle");
92 
93 
94 
98 void VehicleSpriteSeq::GetBounds(Rect *bounds) const
99 {
100  bounds->left = bounds->top = bounds->right = bounds->bottom = 0;
101  for (uint i = 0; i < this->count; ++i) {
102  const Sprite *spr = GetSprite(this->seq[i].sprite, ST_NORMAL);
103  if (i == 0) {
104  bounds->left = spr->x_offs;
105  bounds->top = spr->y_offs;
106  bounds->right = spr->width + spr->x_offs - 1;
107  bounds->bottom = spr->height + spr->y_offs - 1;
108  } else {
109  if (spr->x_offs < bounds->left) bounds->left = spr->x_offs;
110  if (spr->y_offs < bounds->top) bounds->top = spr->y_offs;
111  int right = spr->width + spr->x_offs - 1;
112  int bottom = spr->height + spr->y_offs - 1;
113  if (right > bounds->right) bounds->right = right;
114  if (bottom > bounds->bottom) bounds->bottom = bottom;
115  }
116  }
117 }
118 
126 void VehicleSpriteSeq::Draw(int x, int y, PaletteID default_pal, bool force_pal) const
127 {
128  for (uint i = 0; i < this->count; ++i) {
129  PaletteID pal = force_pal || !this->seq[i].pal ? default_pal : this->seq[i].pal;
130  DrawSprite(this->seq[i].sprite, pal, x, y);
131  }
132 }
133 
140 bool Vehicle::NeedsAutorenewing(const Company *c, bool use_renew_setting) const
141 {
142  /* We can always generate the Company pointer when we have the vehicle.
143  * However this takes time and since the Company pointer is often present
144  * when this function is called then it's faster to pass the pointer as an
145  * argument rather than finding it again. */
146  assert(c == Company::Get(this->owner));
147 
148  if (use_renew_setting && !c->settings.engine_renew) return false;
149  if (this->age - this->max_age < (c->settings.engine_renew_months * 30)) return false;
150 
151  /* Only engines need renewing */
152  if (this->type == VEH_TRAIN && !Train::From(this)->IsEngine()) return false;
153 
154  return true;
155 }
156 
163 {
164  assert(v != nullptr);
165  SetWindowDirty(WC_VEHICLE_DETAILS, v->index); // ensure that last service date and reliability are updated
166 
167  do {
170  v->reliability = v->GetEngine()->reliability;
171  /* Prevent vehicles from breaking down directly after exiting the depot. */
172  v->breakdown_chance /= 4;
173  v = v->Next();
174  } while (v != nullptr && v->HasEngineType());
175 }
176 
184 {
185  /* Stopped or crashed vehicles will not move, as such making unmovable
186  * vehicles to go for service is lame. */
187  if (this->vehstatus & (VS_STOPPED | VS_CRASHED)) return false;
188 
189  /* Are we ready for the next service cycle? */
190  const Company *c = Company::Get(this->owner);
191  if (this->ServiceIntervalIsPercent() ?
192  (this->reliability >= this->GetEngine()->reliability * (100 - this->GetServiceInterval()) / 100) :
193  (this->date_of_last_service + this->GetServiceInterval() >= _date)) {
194  return false;
195  }
196 
197  /* If we're servicing anyway, because we have not disabled servicing when
198  * there are no breakdowns or we are playing with breakdowns, bail out. */
201  return true;
202  }
203 
204  /* Test whether there is some pending autoreplace.
205  * Note: We do this after the service-interval test.
206  * There are a lot more reasons for autoreplace to fail than we can test here reasonably. */
207  bool pending_replace = false;
208  Money needed_money = c->settings.engine_renew_money;
209  if (needed_money > c->money) return false;
210 
211  for (const Vehicle *v = this; v != nullptr; v = (v->type == VEH_TRAIN) ? Train::From(v)->GetNextUnit() : nullptr) {
212  bool replace_when_old = false;
213  EngineID new_engine = EngineReplacementForCompany(c, v->engine_type, v->group_id, &replace_when_old);
214 
215  /* Check engine availability */
216  if (new_engine == INVALID_ENGINE || !HasBit(Engine::Get(new_engine)->company_avail, v->owner)) continue;
217  /* Is the vehicle old if we are not always replacing? */
218  if (replace_when_old && !v->NeedsAutorenewing(c, false)) continue;
219 
220  /* Check refittability */
221  CargoTypes available_cargo_types, union_mask;
222  GetArticulatedRefitMasks(new_engine, true, &union_mask, &available_cargo_types);
223  /* Is there anything to refit? */
224  if (union_mask != 0) {
225  CargoID cargo_type;
226  /* We cannot refit to mixed cargoes in an automated way */
227  if (IsArticulatedVehicleCarryingDifferentCargoes(v, &cargo_type)) continue;
228 
229  /* Did the old vehicle carry anything? */
230  if (cargo_type != CT_INVALID) {
231  /* We can't refit the vehicle to carry the cargo we want */
232  if (!HasBit(available_cargo_types, cargo_type)) continue;
233  }
234  }
235 
236  /* Check money.
237  * We want 2*(the price of the new vehicle) without looking at the value of the vehicle we are going to sell. */
238  pending_replace = true;
239  needed_money += 2 * Engine::Get(new_engine)->GetCost();
240  if (needed_money > c->money) return false;
241  }
242 
243  return pending_replace;
244 }
245 
252 {
253  if (this->HasDepotOrder()) return false;
254  if (this->current_order.IsType(OT_LOADING)) return false;
255  if (this->current_order.IsType(OT_GOTO_DEPOT) && this->current_order.GetDepotOrderType() != ODTFB_SERVICE) return false;
256  return NeedsServicing();
257 }
258 
259 uint Vehicle::Crash(bool flooded)
260 {
261  assert((this->vehstatus & VS_CRASHED) == 0);
262  assert(this->Previous() == nullptr); // IsPrimaryVehicle fails for free-wagon-chains
263 
264  uint pass = 0;
265  /* Stop the vehicle. */
266  if (this->IsPrimaryVehicle()) this->vehstatus |= VS_STOPPED;
267  /* crash all wagons, and count passengers */
268  for (Vehicle *v = this; v != nullptr; v = v->Next()) {
269  /* We do not transfer reserver cargo back, so TotalCount() instead of StoredCount() */
270  if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) pass += v->cargo.TotalCount();
271  v->vehstatus |= VS_CRASHED;
272  v->MarkAllViewportsDirty();
273  }
274 
275  /* Dirty some windows */
278  SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
279  SetWindowDirty(WC_VEHICLE_DEPOT, this->tile);
280 
281  delete this->cargo_payment;
282  assert(this->cargo_payment == nullptr); // cleared by ~CargoPayment
283 
284  return RandomRange(pass + 1); // Randomise deceased passengers.
285 }
286 
287 
296 void ShowNewGrfVehicleError(EngineID engine, StringID part1, StringID part2, GRFBugs bug_type, bool critical)
297 {
298  const Engine *e = Engine::Get(engine);
299  GRFConfig *grfconfig = GetGRFConfig(e->GetGRFID());
300 
301  /* Missing GRF. Nothing useful can be done in this situation. */
302  if (grfconfig == nullptr) return;
303 
304  if (!HasBit(grfconfig->grf_bugs, bug_type)) {
305  SetBit(grfconfig->grf_bugs, bug_type);
306  SetDParamStr(0, grfconfig->GetName());
307  SetDParam(1, engine);
308  ShowErrorMessage(part1, part2, WL_CRITICAL);
310  }
311 
312  /* debug output */
313  char buffer[512];
314 
315  SetDParamStr(0, grfconfig->GetName());
316  GetString(buffer, part1, lastof(buffer));
317  DEBUG(grf, 0, "%s", buffer + 3);
318 
319  SetDParam(1, engine);
320  GetString(buffer, part2, lastof(buffer));
321  DEBUG(grf, 0, "%s", buffer + 3);
322 }
323 
330 {
331  /* show a warning once for each engine in whole game and once for each GRF after each game load */
332  const Engine *engine = u->GetEngine();
333  uint32 grfid = engine->grf_prop.grffile->grfid;
334  GRFConfig *grfconfig = GetGRFConfig(grfid);
335  if (GamelogGRFBugReverse(grfid, engine->grf_prop.local_id) || !HasBit(grfconfig->grf_bugs, GBUG_VEH_LENGTH)) {
336  ShowNewGrfVehicleError(u->engine_type, STR_NEWGRF_BROKEN, STR_NEWGRF_BROKEN_VEHICLE_LENGTH, GBUG_VEH_LENGTH, true);
337  }
338 }
339 
345 {
346  this->type = type;
347  this->coord.left = INVALID_COORD;
348  this->group_id = DEFAULT_GROUP;
349  this->fill_percent_te_id = INVALID_TE_ID;
350  this->first = this;
351  this->colourmap = PAL_NONE;
352  this->cargo_age_counter = 1;
353  this->last_station_visited = INVALID_STATION;
354  this->last_loading_station = INVALID_STATION;
355 }
356 
362 {
363  return GB(Random(), 0, 8);
364 }
365 
366 /* Size of the hash, 6 = 64 x 64, 7 = 128 x 128. Larger sizes will (in theory) reduce hash
367  * lookup times at the expense of memory usage. */
368 const int HASH_BITS = 7;
369 const int HASH_SIZE = 1 << HASH_BITS;
370 const int HASH_MASK = HASH_SIZE - 1;
371 const int TOTAL_HASH_SIZE = 1 << (HASH_BITS * 2);
372 const int TOTAL_HASH_MASK = TOTAL_HASH_SIZE - 1;
373 
374 /* Resolution of the hash, 0 = 1*1 tile, 1 = 2*2 tiles, 2 = 4*4 tiles, etc.
375  * Profiling results show that 0 is fastest. */
376 const int HASH_RES = 0;
377 
378 static Vehicle *_vehicle_tile_hash[TOTAL_HASH_SIZE];
379 
380 static Vehicle *VehicleFromTileHash(int xl, int yl, int xu, int yu, void *data, VehicleFromPosProc *proc, bool find_first)
381 {
382  for (int y = yl; ; y = (y + (1 << HASH_BITS)) & (HASH_MASK << HASH_BITS)) {
383  for (int x = xl; ; x = (x + 1) & HASH_MASK) {
384  Vehicle *v = _vehicle_tile_hash[(x + y) & TOTAL_HASH_MASK];
385  for (; v != nullptr; v = v->hash_tile_next) {
386  Vehicle *a = proc(v, data);
387  if (find_first && a != nullptr) return a;
388  }
389  if (x == xu) break;
390  }
391  if (y == yu) break;
392  }
393 
394  return nullptr;
395 }
396 
397 
409 static Vehicle *VehicleFromPosXY(int x, int y, void *data, VehicleFromPosProc *proc, bool find_first)
410 {
411  const int COLL_DIST = 6;
412 
413  /* Hash area to scan is from xl,yl to xu,yu */
414  int xl = GB((x - COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS);
415  int xu = GB((x + COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS);
416  int yl = GB((y - COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS) << HASH_BITS;
417  int yu = GB((y + COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS) << HASH_BITS;
418 
419  return VehicleFromTileHash(xl, yl, xu, yu, data, proc, find_first);
420 }
421 
436 void FindVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
437 {
438  VehicleFromPosXY(x, y, data, proc, false);
439 }
440 
452 bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
453 {
454  return VehicleFromPosXY(x, y, data, proc, true) != nullptr;
455 }
456 
467 static Vehicle *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc, bool find_first)
468 {
469  int x = GB(TileX(tile), HASH_RES, HASH_BITS);
470  int y = GB(TileY(tile), HASH_RES, HASH_BITS) << HASH_BITS;
471 
472  Vehicle *v = _vehicle_tile_hash[(x + y) & TOTAL_HASH_MASK];
473  for (; v != nullptr; v = v->hash_tile_next) {
474  if (v->tile != tile) continue;
475 
476  Vehicle *a = proc(v, data);
477  if (find_first && a != nullptr) return a;
478  }
479 
480  return nullptr;
481 }
482 
496 void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
497 {
498  VehicleFromPos(tile, data, proc, false);
499 }
500 
511 bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
512 {
513  return VehicleFromPos(tile, data, proc, true) != nullptr;
514 }
515 
522 static Vehicle *EnsureNoVehicleProcZ(Vehicle *v, void *data)
523 {
524  int z = *(int*)data;
525 
526  if (v->type == VEH_DISASTER || (v->type == VEH_AIRCRAFT && v->subtype == AIR_SHADOW)) return nullptr;
527  if (v->z_pos > z) return nullptr;
528 
529  return v;
530 }
531 
538 {
539  int z = GetTileMaxPixelZ(tile);
540 
541  /* Value v is not safe in MP games, however, it is used to generate a local
542  * error message only (which may be different for different machines).
543  * Such a message does not affect MP synchronisation.
544  */
545  Vehicle *v = VehicleFromPos(tile, &z, &EnsureNoVehicleProcZ, true);
546  if (v != nullptr) return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
547  return CommandCost();
548 }
549 
552 {
553  if (v->type != VEH_TRAIN && v->type != VEH_ROAD && v->type != VEH_SHIP) return nullptr;
554  if (v == (const Vehicle *)data) return nullptr;
555 
556  return v;
557 }
558 
567 {
568  /* Value v is not safe in MP games, however, it is used to generate a local
569  * error message only (which may be different for different machines).
570  * Such a message does not affect MP synchronisation.
571  */
572  Vehicle *v = VehicleFromPos(tile, const_cast<Vehicle *>(ignore), &GetVehicleTunnelBridgeProc, true);
573  if (v == nullptr) v = VehicleFromPos(endtile, const_cast<Vehicle *>(ignore), &GetVehicleTunnelBridgeProc, true);
574 
575  if (v != nullptr) return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
576  return CommandCost();
577 }
578 
579 static Vehicle *EnsureNoTrainOnTrackProc(Vehicle *v, void *data)
580 {
581  TrackBits rail_bits = *(TrackBits *)data;
582 
583  if (v->type != VEH_TRAIN) return nullptr;
584 
585  Train *t = Train::From(v);
586  if ((t->track != rail_bits) && !TracksOverlap(t->track | rail_bits)) return nullptr;
587 
588  return v;
589 }
590 
600 {
601  /* Value v is not safe in MP games, however, it is used to generate a local
602  * error message only (which may be different for different machines).
603  * Such a message does not affect MP synchronisation.
604  */
605  Vehicle *v = VehicleFromPos(tile, &track_bits, &EnsureNoTrainOnTrackProc, true);
606  if (v != nullptr) return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
607  return CommandCost();
608 }
609 
610 static void UpdateVehicleTileHash(Vehicle *v, bool remove)
611 {
612  Vehicle **old_hash = v->hash_tile_current;
613  Vehicle **new_hash;
614 
615  if (remove) {
616  new_hash = nullptr;
617  } else {
618  int x = GB(TileX(v->tile), HASH_RES, HASH_BITS);
619  int y = GB(TileY(v->tile), HASH_RES, HASH_BITS) << HASH_BITS;
620  new_hash = &_vehicle_tile_hash[(x + y) & TOTAL_HASH_MASK];
621  }
622 
623  if (old_hash == new_hash) return;
624 
625  /* Remove from the old position in the hash table */
626  if (old_hash != nullptr) {
627  if (v->hash_tile_next != nullptr) v->hash_tile_next->hash_tile_prev = v->hash_tile_prev;
629  }
630 
631  /* Insert vehicle at beginning of the new position in the hash table */
632  if (new_hash != nullptr) {
633  v->hash_tile_next = *new_hash;
634  if (v->hash_tile_next != nullptr) v->hash_tile_next->hash_tile_prev = &v->hash_tile_next;
635  v->hash_tile_prev = new_hash;
636  *new_hash = v;
637  }
638 
639  /* Remember current hash position */
640  v->hash_tile_current = new_hash;
641 }
642 
643 static Vehicle *_vehicle_viewport_hash[1 << (GEN_HASHX_BITS + GEN_HASHY_BITS)];
644 
645 static void UpdateVehicleViewportHash(Vehicle *v, int x, int y)
646 {
647  Vehicle **old_hash, **new_hash;
648  int old_x = v->coord.left;
649  int old_y = v->coord.top;
650 
651  new_hash = (x == INVALID_COORD) ? nullptr : &_vehicle_viewport_hash[GEN_HASH(x, y)];
652  old_hash = (old_x == INVALID_COORD) ? nullptr : &_vehicle_viewport_hash[GEN_HASH(old_x, old_y)];
653 
654  if (old_hash == new_hash) return;
655 
656  /* remove from hash table? */
657  if (old_hash != nullptr) {
660  }
661 
662  /* insert into hash table? */
663  if (new_hash != nullptr) {
664  v->hash_viewport_next = *new_hash;
666  v->hash_viewport_prev = new_hash;
667  *new_hash = v;
668  }
669 }
670 
671 void ResetVehicleHash()
672 {
673  for (Vehicle *v : Vehicle::Iterate()) { v->hash_tile_current = nullptr; }
674  memset(_vehicle_viewport_hash, 0, sizeof(_vehicle_viewport_hash));
675  memset(_vehicle_tile_hash, 0, sizeof(_vehicle_tile_hash));
676 }
677 
678 void ResetVehicleColourMap()
679 {
680  for (Vehicle *v : Vehicle::Iterate()) { v->colourmap = PAL_NONE; }
681 }
682 
688 static AutoreplaceMap _vehicles_to_autoreplace;
689 
690 void InitializeVehicles()
691 {
692  _vehicles_to_autoreplace.clear();
693  _vehicles_to_autoreplace.shrink_to_fit();
694  ResetVehicleHash();
695 }
696 
697 uint CountVehiclesInChain(const Vehicle *v)
698 {
699  uint count = 0;
700  do count++; while ((v = v->Next()) != nullptr);
701  return count;
702 }
703 
709 {
710  switch (this->type) {
711  case VEH_AIRCRAFT: return Aircraft::From(this)->IsNormalAircraft(); // don't count plane shadows and helicopter rotors
712  case VEH_TRAIN:
713  return !this->IsArticulatedPart() && // tenders and other articulated parts
714  !Train::From(this)->IsRearDualheaded(); // rear parts of multiheaded engines
715  case VEH_ROAD: return RoadVehicle::From(this)->IsFrontEngine();
716  case VEH_SHIP: return true;
717  default: return false; // Only count company buildable vehicles
718  }
719 }
720 
726 {
727  switch (this->type) {
728  case VEH_AIRCRAFT: return Aircraft::From(this)->IsNormalAircraft();
729  case VEH_TRAIN:
730  case VEH_ROAD:
731  case VEH_SHIP: return true;
732  default: return false;
733  }
734 }
735 
742 {
743  return Engine::Get(this->engine_type);
744 }
745 
751 const GRFFile *Vehicle::GetGRF() const
752 {
753  return this->GetEngine()->GetGRF();
754 }
755 
761 uint32 Vehicle::GetGRFID() const
762 {
763  return this->GetEngine()->GetGRFID();
764 }
765 
773 void Vehicle::HandlePathfindingResult(bool path_found)
774 {
775  if (path_found) {
776  /* Route found, is the vehicle marked with "lost" flag? */
777  if (!HasBit(this->vehicle_flags, VF_PATHFINDER_LOST)) return;
778 
779  /* Clear the flag as the PF's problem was solved. */
780  ClrBit(this->vehicle_flags, VF_PATHFINDER_LOST);
781  /* Delete the news item. */
782  DeleteVehicleNews(this->index, STR_NEWS_VEHICLE_IS_LOST);
783  return;
784  }
785 
786  /* Were we already lost? */
787  if (HasBit(this->vehicle_flags, VF_PATHFINDER_LOST)) return;
788 
789  /* It is first time the problem occurred, set the "lost" flag. */
790  SetBit(this->vehicle_flags, VF_PATHFINDER_LOST);
791  /* Notify user about the event. */
792  AI::NewEvent(this->owner, new ScriptEventVehicleLost(this->index));
793  if (_settings_client.gui.lost_vehicle_warn && this->owner == _local_company) {
794  SetDParam(0, this->index);
795  AddVehicleAdviceNewsItem(STR_NEWS_VEHICLE_IS_LOST, this->index);
796  }
797 }
798 
801 {
802  if (CleaningPool()) return;
803 
804  if (Station::IsValidID(this->last_station_visited)) {
805  Station *st = Station::Get(this->last_station_visited);
806  st->loading_vehicles.remove(this);
807 
808  HideFillingPercent(&this->fill_percent_te_id);
809  this->CancelReservation(INVALID_STATION, st);
810  delete this->cargo_payment;
811  assert(this->cargo_payment == nullptr); // cleared by ~CargoPayment
812  }
813 
814  if (this->IsEngineCountable()) {
816  if (this->IsPrimaryVehicle()) GroupStatistics::CountVehicle(this, -1);
818 
819  if (this->owner == _local_company) InvalidateAutoreplaceWindow(this->engine_type, this->group_id);
821  }
822 
823  if (this->type == VEH_AIRCRAFT && this->IsPrimaryVehicle()) {
824  Aircraft *a = Aircraft::From(this);
826  if (st != nullptr) {
827  const AirportFTA *layout = st->airport.GetFTA()->layout;
828  CLRBITS(st->airport.flags, layout[a->previous_pos].block | layout[a->pos].block);
829  }
830  }
831 
832 
833  if (this->type == VEH_ROAD && this->IsPrimaryVehicle()) {
834  RoadVehicle *v = RoadVehicle::From(this);
835  if (!(v->vehstatus & VS_CRASHED) && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END)) {
836  /* Leave the drive through roadstop, when you have not already left it. */
838  }
839  }
840 
841  if (this->Previous() == nullptr) {
843  }
844 
845  if (this->IsPrimaryVehicle()) {
846  DeleteWindowById(WC_VEHICLE_VIEW, this->index);
847  DeleteWindowById(WC_VEHICLE_ORDERS, this->index);
848  DeleteWindowById(WC_VEHICLE_REFIT, this->index);
849  DeleteWindowById(WC_VEHICLE_DETAILS, this->index);
851  SetWindowDirty(WC_COMPANY, this->owner);
853  }
855 
856  this->cargo.Truncate();
857  DeleteVehicleOrders(this);
859 
860  extern void StopGlobalFollowVehicle(const Vehicle *v);
861  StopGlobalFollowVehicle(this);
862 
864 }
865 
867 {
868  if (CleaningPool()) {
869  this->cargo.OnCleanPool();
870  return;
871  }
872 
873  /* sometimes, eg. for disaster vehicles, when company bankrupts, when removing crashed/flooded vehicles,
874  * it may happen that vehicle chain is deleted when visible */
875  if (!(this->vehstatus & VS_HIDDEN)) this->MarkAllViewportsDirty();
876 
877  Vehicle *v = this->Next();
878  this->SetNext(nullptr);
879 
880  delete v;
881 
882  UpdateVehicleTileHash(this, true);
883  UpdateVehicleViewportHash(this, INVALID_COORD, 0);
884  DeleteVehicleNews(this->index, INVALID_STRING_ID);
885  DeleteNewGRFInspectWindow(GetGrfSpecFeature(this->type), this->index);
886 }
887 
893 {
894  /* Vehicle should stop in the depot if it was in 'stopping' state */
895  _vehicles_to_autoreplace[v] = !(v->vehstatus & VS_STOPPED);
896 
897  /* We ALWAYS set the stopped state. Even when the vehicle does not plan on
898  * stopping in the depot, so we stop it to ensure that it will not reserve
899  * the path out of the depot before we might autoreplace it to a different
900  * engine. The new engine would not own the reserved path we store that we
901  * stopped the vehicle, so autoreplace can start it again */
902  v->vehstatus |= VS_STOPPED;
903 }
904 
910 static void RunVehicleDayProc()
911 {
912  if (_game_mode != GM_NORMAL) return;
913 
914  /* Run the day_proc for every DAY_TICKS vehicle starting at _date_fract. */
915  for (size_t i = _date_fract; i < Vehicle::GetPoolSize(); i += DAY_TICKS) {
916  Vehicle *v = Vehicle::Get(i);
917  if (v == nullptr) continue;
918 
919  /* Call the 32-day callback if needed */
920  if ((v->day_counter & 0x1F) == 0 && v->HasEngineType()) {
921  uint16 callback = GetVehicleCallback(CBID_VEHICLE_32DAY_CALLBACK, 0, 0, v->engine_type, v);
922  if (callback != CALLBACK_FAILED) {
923  if (HasBit(callback, 0)) {
924  TriggerVehicle(v, VEHICLE_TRIGGER_CALLBACK_32); // Trigger vehicle trigger 10
925  }
926 
927  /* After a vehicle trigger, the graphics and properties of the vehicle could change.
928  * Note: MarkDirty also invalidates the palette, which is the meaning of bit 1. So, nothing special there. */
929  if (callback != 0) v->First()->MarkDirty();
930 
931  if (callback & ~3) ErrorUnknownCallbackResult(v->GetGRFID(), CBID_VEHICLE_32DAY_CALLBACK, callback);
932  }
933  }
934 
935  /* This is called once per day for each vehicle, but not in the first tick of the day */
936  v->OnNewDay();
937  }
938 }
939 
940 void CallVehicleTicks()
941 {
942  _vehicles_to_autoreplace.clear();
943 
945 
946  {
948  for (Station *st : Station::Iterate()) LoadUnloadStation(st);
949  }
954 
955  for (Vehicle *v : Vehicle::Iterate()) {
956  size_t vehicle_index = v->index;
957  /* Vehicle could be deleted in this tick */
958  if (!v->Tick()) {
959  assert(Vehicle::Get(vehicle_index) == nullptr);
960  continue;
961  }
962 
963  assert(Vehicle::Get(vehicle_index) == v);
964 
965  switch (v->type) {
966  default: break;
967 
968  case VEH_TRAIN:
969  case VEH_ROAD:
970  case VEH_AIRCRAFT:
971  case VEH_SHIP: {
972  Vehicle *front = v->First();
973 
974  if (v->vcache.cached_cargo_age_period != 0) {
976  if (--v->cargo_age_counter == 0) {
977  v->cargo.AgeCargo();
979  }
980  }
981 
982  /* Do not play any sound when crashed */
983  if (front->vehstatus & VS_CRASHED) continue;
984 
985  /* Do not play any sound when in depot or tunnel */
986  if (v->vehstatus & VS_HIDDEN) continue;
987 
988  /* Do not play any sound when stopped */
989  if ((front->vehstatus & VS_STOPPED) && (front->type != VEH_TRAIN || front->cur_speed == 0)) continue;
990 
991  /* Check vehicle type specifics */
992  switch (v->type) {
993  case VEH_TRAIN:
994  if (Train::From(v)->IsWagon()) continue;
995  break;
996 
997  case VEH_ROAD:
998  if (!RoadVehicle::From(v)->IsFrontEngine()) continue;
999  break;
1000 
1001  case VEH_AIRCRAFT:
1002  if (!Aircraft::From(v)->IsNormalAircraft()) continue;
1003  break;
1004 
1005  default:
1006  break;
1007  }
1008 
1009  v->motion_counter += front->cur_speed;
1010  /* Play a running sound if the motion counter passes 256 (Do we not skip sounds?) */
1011  if (GB(v->motion_counter, 0, 8) < front->cur_speed) PlayVehicleSound(v, VSE_RUNNING);
1012 
1013  /* Play an alternating running sound every 16 ticks */
1014  if (GB(v->tick_counter, 0, 4) == 0) {
1015  /* Play running sound when speed > 0 and not braking */
1016  bool running = (front->cur_speed > 0) && !(front->vehstatus & (VS_STOPPED | VS_TRAIN_SLOWING));
1018  }
1019 
1020  break;
1021  }
1022  }
1023  }
1024 
1025  Backup<CompanyID> cur_company(_current_company, FILE_LINE);
1026  for (auto &it : _vehicles_to_autoreplace) {
1027  Vehicle *v = it.first;
1028  /* Autoreplace needs the current company set as the vehicle owner */
1029  cur_company.Change(v->owner);
1030 
1031  /* Start vehicle if we stopped them in VehicleEnteredDepotThisTick()
1032  * We need to stop them between VehicleEnteredDepotThisTick() and here or we risk that
1033  * they are already leaving the depot again before being replaced. */
1034  if (it.second) v->vehstatus &= ~VS_STOPPED;
1035 
1036  /* Store the position of the effect as the vehicle pointer will become invalid later */
1037  int x = v->x_pos;
1038  int y = v->y_pos;
1039  int z = v->z_pos;
1040 
1045 
1046  if (!IsLocalCompany()) continue;
1047 
1048  if (res.Succeeded()) {
1049  ShowCostOrIncomeAnimation(x, y, z, res.GetCost());
1050  continue;
1051  }
1052 
1053  StringID error_message = res.GetErrorMessage();
1054  if (error_message == STR_ERROR_AUTOREPLACE_NOTHING_TO_DO || error_message == INVALID_STRING_ID) continue;
1055 
1056  if (error_message == STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY) error_message = STR_ERROR_AUTOREPLACE_MONEY_LIMIT;
1057 
1058  StringID message;
1059  if (error_message == STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT) {
1060  message = error_message;
1061  } else {
1062  message = STR_NEWS_VEHICLE_AUTORENEW_FAILED;
1063  }
1064 
1065  SetDParam(0, v->index);
1066  SetDParam(1, error_message);
1067  AddVehicleAdviceNewsItem(message, v->index);
1068  }
1069 
1070  cur_company.Restore();
1071 }
1072 
1077 static void DoDrawVehicle(const Vehicle *v)
1078 {
1079  PaletteID pal = PAL_NONE;
1080 
1082 
1083  /* Check whether the vehicle shall be transparent due to the game state */
1084  bool shadowed = (v->vehstatus & VS_SHADOW) != 0;
1085 
1086  if (v->type == VEH_EFFECT) {
1087  /* Check whether the vehicle shall be transparent/invisible due to GUI settings.
1088  * However, transparent smoke and bubbles look weird, so always hide them. */
1090  if (to != TO_INVALID && (IsTransparencySet(to) || IsInvisibilitySet(to))) return;
1091  }
1092 
1094  for (uint i = 0; i < v->sprite_seq.count; ++i) {
1095  PaletteID pal2 = v->sprite_seq.seq[i].pal;
1096  if (!pal2 || (v->vehstatus & VS_CRASHED)) pal2 = pal;
1097  AddSortableSpriteToDraw(v->sprite_seq.seq[i].sprite, pal2, v->x_pos + v->x_offs, v->y_pos + v->y_offs,
1098  v->x_extent, v->y_extent, v->z_extent, v->z_pos, shadowed, v->x_bb_offs, v->y_bb_offs);
1099  }
1100  EndSpriteCombine();
1101 }
1102 
1108 {
1109  /* The bounding rectangle */
1110  const int l = dpi->left;
1111  const int r = dpi->left + dpi->width;
1112  const int t = dpi->top;
1113  const int b = dpi->top + dpi->height;
1114 
1115  /* The hash area to scan */
1116  int xl, xu, yl, yu;
1117 
1118  if (dpi->width + (MAX_VEHICLE_PIXEL_X * ZOOM_LVL_BASE) < GEN_HASHX_SIZE) {
1119  xl = GEN_HASHX(l - MAX_VEHICLE_PIXEL_X * ZOOM_LVL_BASE);
1120  xu = GEN_HASHX(r);
1121  } else {
1122  /* scan whole hash row */
1123  xl = 0;
1124  xu = GEN_HASHX_MASK;
1125  }
1126 
1127  if (dpi->height + (MAX_VEHICLE_PIXEL_Y * ZOOM_LVL_BASE) < GEN_HASHY_SIZE) {
1128  yl = GEN_HASHY(t - MAX_VEHICLE_PIXEL_Y * ZOOM_LVL_BASE);
1129  yu = GEN_HASHY(b);
1130  } else {
1131  /* scan whole column */
1132  yl = 0;
1133  yu = GEN_HASHY_MASK;
1134  }
1135 
1136  for (int y = yl;; y = (y + GEN_HASHY_INC) & GEN_HASHY_MASK) {
1137  for (int x = xl;; x = (x + GEN_HASHX_INC) & GEN_HASHX_MASK) {
1138  const Vehicle *v = _vehicle_viewport_hash[x + y]; // already masked & 0xFFF
1139 
1140  while (v != nullptr) {
1141  if (!(v->vehstatus & VS_HIDDEN) &&
1142  l <= v->coord.right &&
1143  t <= v->coord.bottom &&
1144  r >= v->coord.left &&
1145  b >= v->coord.top) {
1146  DoDrawVehicle(v);
1147  }
1148  v = v->hash_viewport_next;
1149  }
1150 
1151  if (x == xu) break;
1152  }
1153 
1154  if (y == yu) break;
1155  }
1156 }
1157 
1165 Vehicle *CheckClickOnVehicle(const ViewPort *vp, int x, int y)
1166 {
1167  Vehicle *found = nullptr;
1168  uint dist, best_dist = UINT_MAX;
1169 
1170  if ((uint)(x -= vp->left) >= (uint)vp->width || (uint)(y -= vp->top) >= (uint)vp->height) return nullptr;
1171 
1172  x = ScaleByZoom(x, vp->zoom) + vp->virtual_left;
1173  y = ScaleByZoom(y, vp->zoom) + vp->virtual_top;
1174 
1175  for (Vehicle *v : Vehicle::Iterate()) {
1176  if ((v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0 &&
1177  x >= v->coord.left && x <= v->coord.right &&
1178  y >= v->coord.top && y <= v->coord.bottom) {
1179 
1180  dist = max(
1181  abs(((v->coord.left + v->coord.right) >> 1) - x),
1182  abs(((v->coord.top + v->coord.bottom) >> 1) - y)
1183  );
1184 
1185  if (dist < best_dist) {
1186  found = v;
1187  best_dist = dist;
1188  }
1189  }
1190  }
1191 
1192  return found;
1193 }
1194 
1200 {
1201  v->value -= v->value >> 8;
1203 }
1204 
1205 static const byte _breakdown_chance[64] = {
1206  3, 3, 3, 3, 3, 3, 3, 3,
1207  4, 4, 5, 5, 6, 6, 7, 7,
1208  8, 8, 9, 9, 10, 10, 11, 11,
1209  12, 13, 13, 13, 13, 14, 15, 16,
1210  17, 19, 21, 25, 28, 31, 34, 37,
1211  40, 44, 48, 52, 56, 60, 64, 68,
1212  72, 80, 90, 100, 110, 120, 130, 140,
1213  150, 170, 190, 210, 230, 250, 250, 250,
1214 };
1215 
1216 void CheckVehicleBreakdown(Vehicle *v)
1217 {
1218  int rel, rel_old;
1219 
1220  /* decrease reliability */
1223  v->reliability = rel = max((rel_old = v->reliability) - v->reliability_spd_dec, 0);
1224  if ((rel_old >> 8) != (rel >> 8)) SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
1225  }
1226 
1227  if (v->breakdown_ctr != 0 || (v->vehstatus & VS_STOPPED) ||
1229  v->cur_speed < 5 || _game_mode == GM_MENU) {
1230  return;
1231  }
1232 
1233  uint32 r = Random();
1234 
1235  /* increase chance of failure */
1236  int chance = v->breakdown_chance + 1;
1237  if (Chance16I(1, 25, r)) chance += 25;
1238  v->breakdown_chance = min(255, chance);
1239 
1240  /* calculate reliability value to use in comparison */
1241  rel = v->reliability;
1242  if (v->type == VEH_SHIP) rel += 0x6666;
1243 
1244  /* reduced breakdowns? */
1245  if (_settings_game.difficulty.vehicle_breakdowns == 1) rel += 0x6666;
1246 
1247  /* check if to break down */
1248  if (_breakdown_chance[(uint)min(rel, 0xffff) >> 10] <= v->breakdown_chance) {
1249  v->breakdown_ctr = GB(r, 16, 6) + 0x3F;
1250  v->breakdown_delay = GB(r, 24, 7) + 0x80;
1251  v->breakdown_chance = 0;
1252  }
1253 }
1254 
1262 {
1263  /* Possible states for Vehicle::breakdown_ctr
1264  * 0 - vehicle is running normally
1265  * 1 - vehicle is currently broken down
1266  * 2 - vehicle is going to break down now
1267  * >2 - vehicle is counting down to the actual breakdown event */
1268  switch (this->breakdown_ctr) {
1269  case 0:
1270  return false;
1271 
1272  case 2:
1273  this->breakdown_ctr = 1;
1274 
1275  if (this->breakdowns_since_last_service != 255) {
1276  this->breakdowns_since_last_service++;
1277  }
1278 
1279  if (this->type == VEH_AIRCRAFT) {
1280  /* Aircraft just need this flag, the rest is handled elsewhere */
1281  this->vehstatus |= VS_AIRCRAFT_BROKEN;
1282  } else {
1283  this->cur_speed = 0;
1284 
1285  if (!PlayVehicleSound(this, VSE_BREAKDOWN)) {
1286  bool train_or_ship = this->type == VEH_TRAIN || this->type == VEH_SHIP;
1287  SndPlayVehicleFx((_settings_game.game_creation.landscape != LT_TOYLAND) ?
1288  (train_or_ship ? SND_10_TRAIN_BREAKDOWN : SND_0F_VEHICLE_BREAKDOWN) :
1289  (train_or_ship ? SND_3A_COMEDY_BREAKDOWN_2 : SND_35_COMEDY_BREAKDOWN), this);
1290  }
1291 
1292  if (!(this->vehstatus & VS_HIDDEN) && !HasBit(EngInfo(this->engine_type)->misc_flags, EF_NO_BREAKDOWN_SMOKE)) {
1294  if (u != nullptr) u->animation_state = this->breakdown_delay * 2;
1295  }
1296  }
1297 
1298  this->MarkDirty(); // Update graphics after speed is zeroed
1299  SetWindowDirty(WC_VEHICLE_VIEW, this->index);
1300  SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
1301 
1302  FALLTHROUGH;
1303  case 1:
1304  /* Aircraft breakdowns end only when arriving at the airport */
1305  if (this->type == VEH_AIRCRAFT) return false;
1306 
1307  /* For trains this function is called twice per tick, so decrease v->breakdown_delay at half the rate */
1308  if ((this->tick_counter & (this->type == VEH_TRAIN ? 3 : 1)) == 0) {
1309  if (--this->breakdown_delay == 0) {
1310  this->breakdown_ctr = 0;
1311  this->MarkDirty();
1312  SetWindowDirty(WC_VEHICLE_VIEW, this->index);
1313  }
1314  }
1315  return true;
1316 
1317  default:
1318  if (!this->current_order.IsType(OT_LOADING)) this->breakdown_ctr--;
1319  return false;
1320  }
1321 }
1322 
1328 {
1329  if (v->age < MAX_DAY) {
1330  v->age++;
1332  }
1333 
1334  if (!v->IsPrimaryVehicle() && (v->type != VEH_TRAIN || !Train::From(v)->IsEngine())) return;
1335 
1336  int age = v->age - v->max_age;
1337  if (age == DAYS_IN_LEAP_YEAR * 0 || age == DAYS_IN_LEAP_YEAR * 1 ||
1338  age == DAYS_IN_LEAP_YEAR * 2 || age == DAYS_IN_LEAP_YEAR * 3 || age == DAYS_IN_LEAP_YEAR * 4) {
1339  v->reliability_spd_dec <<= 1;
1340  }
1341 
1343 
1344  /* Don't warn about non-primary or not ours vehicles or vehicles that are crashed */
1345  if (v->Previous() != nullptr || v->owner != _local_company || (v->vehstatus & VS_CRASHED) != 0) return;
1346 
1347  const Company *c = Company::Get(v->owner);
1348  /* Don't warn if a renew is active */
1349  if (c->settings.engine_renew && v->GetEngine()->company_avail != 0) return;
1350  /* Don't warn if a replacement is active */
1351  if (EngineHasReplacementForCompany(c, v->engine_type, v->group_id)) return;
1352 
1353  StringID str;
1354  if (age == -DAYS_IN_LEAP_YEAR) {
1355  str = STR_NEWS_VEHICLE_IS_GETTING_OLD;
1356  } else if (age == 0) {
1357  str = STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD;
1358  } else if (age > 0 && (age % DAYS_IN_LEAP_YEAR) == 0) {
1359  str = STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD_AND;
1360  } else {
1361  return;
1362  }
1363 
1364  SetDParam(0, v->index);
1366 }
1367 
1377 uint8 CalcPercentVehicleFilled(const Vehicle *front, StringID *colour)
1378 {
1379  int count = 0;
1380  int max = 0;
1381  int cars = 0;
1382  int unloading = 0;
1383  bool loading = false;
1384 
1385  bool is_loading = front->current_order.IsType(OT_LOADING);
1386 
1387  /* The station may be nullptr when the (colour) string does not need to be set. */
1388  const Station *st = Station::GetIfValid(front->last_station_visited);
1389  assert(colour == nullptr || (st != nullptr && is_loading));
1390 
1391  bool order_no_load = is_loading && (front->current_order.GetLoadType() & OLFB_NO_LOAD);
1392  bool order_full_load = is_loading && (front->current_order.GetLoadType() & OLFB_FULL_LOAD);
1393 
1394  /* Count up max and used */
1395  for (const Vehicle *v = front; v != nullptr; v = v->Next()) {
1396  count += v->cargo.StoredCount();
1397  max += v->cargo_cap;
1398  if (v->cargo_cap != 0 && colour != nullptr) {
1399  unloading += HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) ? 1 : 0;
1400  loading |= !order_no_load &&
1401  (order_full_load || st->goods[v->cargo_type].HasRating()) &&
1403  cars++;
1404  }
1405  }
1406 
1407  if (colour != nullptr) {
1408  if (unloading == 0 && loading) {
1409  *colour = STR_PERCENT_UP;
1410  } else if (unloading == 0 && !loading) {
1411  *colour = STR_PERCENT_NONE;
1412  } else if (cars == unloading || !loading) {
1413  *colour = STR_PERCENT_DOWN;
1414  } else {
1415  *colour = STR_PERCENT_UP_DOWN;
1416  }
1417  }
1418 
1419  /* Train without capacity */
1420  if (max == 0) return 100;
1421 
1422  /* Return the percentage */
1423  if (count * 2 < max) {
1424  /* Less than 50%; round up, so that 0% means really empty. */
1425  return CeilDiv(count * 100, max);
1426  } else {
1427  /* More than 50%; round down, so that 100% means really full. */
1428  return (count * 100) / max;
1429  }
1430 }
1431 
1437 {
1438  /* Always work with the front of the vehicle */
1439  assert(v == v->First());
1440 
1441  switch (v->type) {
1442  case VEH_TRAIN: {
1443  Train *t = Train::From(v);
1445  /* Clear path reservation */
1446  SetDepotReservation(t->tile, false);
1448 
1450  t->wait_counter = 0;
1451  t->force_proceed = TFP_NONE;
1452  ClrBit(t->flags, VRF_TOGGLE_REVERSE);
1454  break;
1455  }
1456 
1457  case VEH_ROAD:
1459  break;
1460 
1461  case VEH_SHIP: {
1463  Ship *ship = Ship::From(v);
1464  ship->state = TRACK_BIT_DEPOT;
1465  ship->UpdateCache();
1466  ship->UpdateViewport(true, true);
1468  break;
1469  }
1470 
1471  case VEH_AIRCRAFT:
1474  break;
1475  default: NOT_REACHED();
1476  }
1478 
1479  if (v->type != VEH_TRAIN) {
1480  /* Trains update the vehicle list when the first unit enters the depot and calls VehicleEnterDepot() when the last unit enters.
1481  * We only increase the number of vehicles when the first one enters, so we will not need to search for more vehicles in the depot */
1483  }
1485 
1486  v->vehstatus |= VS_HIDDEN;
1487  v->cur_speed = 0;
1488 
1490 
1491  /* After a vehicle trigger, the graphics and properties of the vehicle could change. */
1492  TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
1493  v->MarkDirty();
1494 
1496 
1497  if (v->current_order.IsType(OT_GOTO_DEPOT)) {
1499 
1500  const Order *real_order = v->GetOrder(v->cur_real_order_index);
1501 
1502  /* Test whether we are heading for this depot. If not, do nothing.
1503  * Note: The target depot for nearest-/manual-depot-orders is only updated on junctions, but we want to accept every depot. */
1505  real_order != nullptr && !(real_order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) &&
1506  (v->type == VEH_AIRCRAFT ? v->current_order.GetDestination() != GetStationIndex(v->tile) : v->dest_tile != v->tile)) {
1507  /* We are heading for another depot, keep driving. */
1508  return;
1509  }
1510 
1511  if (v->current_order.IsRefit()) {
1512  Backup<CompanyID> cur_company(_current_company, v->owner, FILE_LINE);
1513  CommandCost cost = DoCommand(v->tile, v->index, v->current_order.GetRefitCargo() | 0xFF << 8, DC_EXEC, GetCmdRefitVeh(v));
1514  cur_company.Restore();
1515 
1516  if (cost.Failed()) {
1517  _vehicles_to_autoreplace[v] = false;
1518  if (v->owner == _local_company) {
1519  /* Notify the user that we stopped the vehicle */
1520  SetDParam(0, v->index);
1521  AddVehicleAdviceNewsItem(STR_NEWS_ORDER_REFIT_FAILED, v->index);
1522  }
1523  } else if (cost.GetCost() != 0) {
1524  v->profit_this_year -= cost.GetCost() << 8;
1525  if (v->owner == _local_company) {
1526  ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
1527  }
1528  }
1529  }
1530 
1532  /* Part of orders */
1534  UpdateVehicleTimetable(v, true);
1536  }
1538  /* Vehicles are always stopped on entering depots. Do not restart this one. */
1539  _vehicles_to_autoreplace[v] = false;
1540  /* Invalidate last_loading_station. As the link from the station
1541  * before the stop to the station after the stop can't be predicted
1542  * we shouldn't construct it when the vehicle visits the next stop. */
1543  v->last_loading_station = INVALID_STATION;
1544  if (v->owner == _local_company) {
1545  SetDParam(0, v->index);
1546  AddVehicleAdviceNewsItem(STR_NEWS_TRAIN_IS_WAITING + v->type, v->index);
1547  }
1548  AI::NewEvent(v->owner, new ScriptEventVehicleWaitingInDepot(v->index));
1549  }
1550  v->current_order.MakeDummy();
1551  }
1552 }
1553 
1554 
1560 {
1561  UpdateVehicleTileHash(this, false);
1562 }
1563 
1569 void Vehicle::UpdateViewport(bool dirty)
1570 {
1571  Rect new_coord;
1572  this->sprite_seq.GetBounds(&new_coord);
1573 
1574  Point pt = RemapCoords(this->x_pos + this->x_offs, this->y_pos + this->y_offs, this->z_pos);
1575  new_coord.left += pt.x;
1576  new_coord.top += pt.y;
1577  new_coord.right += pt.x + 2 * ZOOM_LVL_BASE;
1578  new_coord.bottom += pt.y + 2 * ZOOM_LVL_BASE;
1579 
1580  UpdateVehicleViewportHash(this, new_coord.left, new_coord.top);
1581 
1582  Rect old_coord = this->coord;
1583  this->coord = new_coord;
1584 
1585  if (dirty) {
1586  if (old_coord.left == INVALID_COORD) {
1587  this->MarkAllViewportsDirty();
1588  } else {
1590  min(old_coord.left, this->coord.left),
1591  min(old_coord.top, this->coord.top),
1592  max(old_coord.right, this->coord.right),
1593  max(old_coord.bottom, this->coord.bottom));
1594  }
1595  }
1596 }
1597 
1602 {
1603  this->UpdatePosition();
1604  this->UpdateViewport(true);
1605 }
1606 
1611 {
1612  ::MarkAllViewportsDirty(this->coord.left, this->coord.top, this->coord.right, this->coord.bottom);
1613 }
1614 
1621 {
1622  static const int8 _delta_coord[16] = {
1623  -1,-1,-1, 0, 1, 1, 1, 0, /* x */
1624  -1, 0, 1, 1, 1, 0,-1,-1, /* y */
1625  };
1626 
1627  int x = v->x_pos + _delta_coord[v->direction];
1628  int y = v->y_pos + _delta_coord[v->direction + 8];
1629 
1631  gp.x = x;
1632  gp.y = y;
1633  gp.old_tile = v->tile;
1634  gp.new_tile = TileVirtXY(x, y);
1635  return gp;
1636 }
1637 
1638 static const Direction _new_direction_table[] = {
1639  DIR_N, DIR_NW, DIR_W,
1640  DIR_NE, DIR_SE, DIR_SW,
1641  DIR_E, DIR_SE, DIR_S
1642 };
1643 
1644 Direction GetDirectionTowards(const Vehicle *v, int x, int y)
1645 {
1646  int i = 0;
1647 
1648  if (y >= v->y_pos) {
1649  if (y != v->y_pos) i += 3;
1650  i += 3;
1651  }
1652 
1653  if (x >= v->x_pos) {
1654  if (x != v->x_pos) i++;
1655  i++;
1656  }
1657 
1658  Direction dir = v->direction;
1659 
1660  DirDiff dirdiff = DirDifference(_new_direction_table[i], dir);
1661  if (dirdiff == DIRDIFF_SAME) return dir;
1662  return ChangeDir(dir, dirdiff > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT);
1663 }
1664 
1675 {
1676  return _tile_type_procs[GetTileType(tile)]->vehicle_enter_tile_proc(v, tile, x, y);
1677 }
1678 
1686 FreeUnitIDGenerator::FreeUnitIDGenerator(VehicleType type, CompanyID owner) : cache(nullptr), maxid(0), curid(0)
1687 {
1688  /* Find maximum */
1689  for (const Vehicle *v : Vehicle::Iterate()) {
1690  if (v->type == type && v->owner == owner) {
1691  this->maxid = max<UnitID>(this->maxid, v->unitnumber);
1692  }
1693  }
1694 
1695  if (this->maxid == 0) return;
1696 
1697  /* Reserving 'maxid + 2' because we need:
1698  * - space for the last item (with v->unitnumber == maxid)
1699  * - one free slot working as loop terminator in FreeUnitIDGenerator::NextID() */
1700  this->cache = CallocT<bool>(this->maxid + 2);
1701 
1702  /* Fill the cache */
1703  for (const Vehicle *v : Vehicle::Iterate()) {
1704  if (v->type == type && v->owner == owner) {
1705  this->cache[v->unitnumber] = true;
1706  }
1707  }
1708 }
1709 
1712 {
1713  if (this->maxid <= this->curid) return ++this->curid;
1714 
1715  while (this->cache[++this->curid]) { } // it will stop, we reserved more space than needed
1716 
1717  return this->curid;
1718 }
1719 
1726 {
1727  /* Check whether it is allowed to build another vehicle. */
1728  uint max_veh;
1729  switch (type) {
1730  case VEH_TRAIN: max_veh = _settings_game.vehicle.max_trains; break;
1731  case VEH_ROAD: max_veh = _settings_game.vehicle.max_roadveh; break;
1732  case VEH_SHIP: max_veh = _settings_game.vehicle.max_ships; break;
1733  case VEH_AIRCRAFT: max_veh = _settings_game.vehicle.max_aircraft; break;
1734  default: NOT_REACHED();
1735  }
1736 
1738  if (c->group_all[type].num_vehicle >= max_veh) return UINT16_MAX; // Currently already at the limit, no room to make a new one.
1739 
1741 
1742  return gen.NextID();
1743 }
1744 
1745 
1755 {
1756  assert(IsCompanyBuildableVehicleType(type));
1757 
1758  if (!Company::IsValidID(_local_company)) return false;
1760 
1761  UnitID max;
1762  switch (type) {
1763  case VEH_TRAIN:
1764  if (!HasAnyRailtypesAvail(_local_company)) return false;
1766  break;
1767  case VEH_ROAD:
1768  if (!HasAnyRoadTypesAvail(_local_company, (RoadTramType)subtype)) return false;
1770  break;
1771  case VEH_SHIP: max = _settings_game.vehicle.max_ships; break;
1772  case VEH_AIRCRAFT: max = _settings_game.vehicle.max_aircraft; break;
1773  default: NOT_REACHED();
1774  }
1775 
1776  /* We can build vehicle infrastructure when we may build the vehicle type */
1777  if (max > 0) {
1778  /* Can we actually build the vehicle type? */
1779  for (const Engine *e : Engine::IterateType(type)) {
1780  if (type == VEH_ROAD && GetRoadTramType(e->u.road.roadtype) != (RoadTramType)subtype) continue;
1781  if (HasBit(e->company_avail, _local_company)) return true;
1782  }
1783  return false;
1784  }
1785 
1786  /* We should be able to build infrastructure when we have the actual vehicle type */
1787  for (const Vehicle *v : Vehicle::Iterate()) {
1788  if (type == VEH_ROAD && GetRoadTramType(RoadVehicle::From(v)->roadtype) != (RoadTramType)subtype) continue;
1789  if (v->owner == _local_company && v->type == type) return true;
1790  }
1791 
1792  return false;
1793 }
1794 
1795 
1803 LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_type, const Vehicle *v)
1804 {
1805  CargoID cargo_type = v == nullptr ? (CargoID)CT_INVALID : v->cargo_type;
1806  const Engine *e = Engine::Get(engine_type);
1807  switch (e->type) {
1808  default: NOT_REACHED();
1809  case VEH_TRAIN:
1810  if (v != nullptr && parent_engine_type != INVALID_ENGINE && (UsesWagonOverride(v) || (v->IsArticulatedPart() && e->u.rail.railveh_type != RAILVEH_WAGON))) {
1811  /* Wagonoverrides use the colour scheme of the front engine.
1812  * Articulated parts use the colour scheme of the first part. (Not supported for articulated wagons) */
1813  engine_type = parent_engine_type;
1814  e = Engine::Get(engine_type);
1815  /* Note: Luckily cargo_type is not needed for engines */
1816  }
1817 
1818  if (cargo_type == CT_INVALID) cargo_type = e->GetDefaultCargoType();
1819  if (cargo_type == CT_INVALID) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo
1820  if (e->u.rail.railveh_type == RAILVEH_WAGON) {
1821  if (!CargoSpec::Get(cargo_type)->is_freight) {
1822  if (parent_engine_type == INVALID_ENGINE) {
1823  return LS_PASSENGER_WAGON_STEAM;
1824  } else {
1825  bool is_mu = HasBit(EngInfo(parent_engine_type)->misc_flags, EF_RAIL_IS_MU);
1826  switch (RailVehInfo(parent_engine_type)->engclass) {
1827  default: NOT_REACHED();
1828  case EC_STEAM: return LS_PASSENGER_WAGON_STEAM;
1829  case EC_DIESEL: return is_mu ? LS_DMU : LS_PASSENGER_WAGON_DIESEL;
1830  case EC_ELECTRIC: return is_mu ? LS_EMU : LS_PASSENGER_WAGON_ELECTRIC;
1831  case EC_MONORAIL: return LS_PASSENGER_WAGON_MONORAIL;
1832  case EC_MAGLEV: return LS_PASSENGER_WAGON_MAGLEV;
1833  }
1834  }
1835  } else {
1836  return LS_FREIGHT_WAGON;
1837  }
1838  } else {
1839  bool is_mu = HasBit(e->info.misc_flags, EF_RAIL_IS_MU);
1840 
1841  switch (e->u.rail.engclass) {
1842  default: NOT_REACHED();
1843  case EC_STEAM: return LS_STEAM;
1844  case EC_DIESEL: return is_mu ? LS_DMU : LS_DIESEL;
1845  case EC_ELECTRIC: return is_mu ? LS_EMU : LS_ELECTRIC;
1846  case EC_MONORAIL: return LS_MONORAIL;
1847  case EC_MAGLEV: return LS_MAGLEV;
1848  }
1849  }
1850 
1851  case VEH_ROAD:
1852  /* Always use the livery of the front */
1853  if (v != nullptr && parent_engine_type != INVALID_ENGINE) {
1854  engine_type = parent_engine_type;
1855  e = Engine::Get(engine_type);
1856  cargo_type = v->First()->cargo_type;
1857  }
1858  if (cargo_type == CT_INVALID) cargo_type = e->GetDefaultCargoType();
1859  if (cargo_type == CT_INVALID) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo
1860 
1861  /* Important: Use Tram Flag of front part. Luckily engine_type refers to the front part here. */
1862  if (HasBit(e->info.misc_flags, EF_ROAD_TRAM)) {
1863  /* Tram */
1864  return IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_TRAM : LS_FREIGHT_TRAM;
1865  } else {
1866  /* Bus or truck */
1867  return IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_BUS : LS_TRUCK;
1868  }
1869 
1870  case VEH_SHIP:
1871  if (cargo_type == CT_INVALID) cargo_type = e->GetDefaultCargoType();
1872  if (cargo_type == CT_INVALID) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo
1873  return IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_SHIP : LS_FREIGHT_SHIP;
1874 
1875  case VEH_AIRCRAFT:
1876  switch (e->u.air.subtype) {
1877  case AIR_HELI: return LS_HELICOPTER;
1878  case AIR_CTOL: return LS_SMALL_PLANE;
1879  case AIR_CTOL | AIR_FAST: return LS_LARGE_PLANE;
1880  default: NOT_REACHED();
1881  }
1882  }
1883 }
1884 
1894 const Livery *GetEngineLivery(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v, byte livery_setting)
1895 {
1896  const Company *c = Company::Get(company);
1897  LiveryScheme scheme = LS_DEFAULT;
1898 
1899  if (livery_setting == LIT_ALL || (livery_setting == LIT_COMPANY && company == _local_company)) {
1900  if (v != nullptr) {
1901  const Group *g = Group::GetIfValid(v->First()->group_id);
1902  if (g != nullptr) {
1903  /* Traverse parents until we find a livery or reach the top */
1904  while (g->livery.in_use == 0 && g->parent != INVALID_GROUP) {
1905  g = Group::Get(g->parent);
1906  }
1907  if (g->livery.in_use != 0) return &g->livery;
1908  }
1909  }
1910 
1911  /* The default livery is always available for use, but its in_use flag determines
1912  * whether any _other_ liveries are in use. */
1913  if (c->livery[LS_DEFAULT].in_use != 0) {
1914  /* Determine the livery scheme to use */
1915  scheme = GetEngineLiveryScheme(engine_type, parent_engine_type, v);
1916  }
1917  }
1918 
1919  return &c->livery[scheme];
1920 }
1921 
1922 
1923 static PaletteID GetEngineColourMap(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v)
1924 {
1925  PaletteID map = (v != nullptr) ? v->colourmap : PAL_NONE;
1926 
1927  /* Return cached value if any */
1928  if (map != PAL_NONE) return map;
1929 
1930  const Engine *e = Engine::Get(engine_type);
1931 
1932  /* Check if we should use the colour map callback */
1934  uint16 callback = GetVehicleCallback(CBID_VEHICLE_COLOUR_MAPPING, 0, 0, engine_type, v);
1935  /* Failure means "use the default two-colour" */
1936  if (callback != CALLBACK_FAILED) {
1937  assert_compile(PAL_NONE == 0); // Returning 0x4000 (resp. 0xC000) coincidences with default value (PAL_NONE)
1938  map = GB(callback, 0, 14);
1939  /* If bit 14 is set, then the company colours are applied to the
1940  * map else it's returned as-is. */
1941  if (!HasBit(callback, 14)) {
1942  /* Update cache */
1943  if (v != nullptr) const_cast<Vehicle *>(v)->colourmap = map;
1944  return map;
1945  }
1946  }
1947  }
1948 
1949  bool twocc = HasBit(e->info.misc_flags, EF_USES_2CC);
1950 
1951  if (map == PAL_NONE) map = twocc ? (PaletteID)SPR_2CCMAP_BASE : (PaletteID)PALETTE_RECOLOUR_START;
1952 
1953  /* Spectator has news shown too, but has invalid company ID - as well as dedicated server */
1954  if (!Company::IsValidID(company)) return map;
1955 
1956  const Livery *livery = GetEngineLivery(engine_type, company, parent_engine_type, v, _settings_client.gui.liveries);
1957 
1958  map += livery->colour1;
1959  if (twocc) map += livery->colour2 * 16;
1960 
1961  /* Update cache */
1962  if (v != nullptr) const_cast<Vehicle *>(v)->colourmap = map;
1963  return map;
1964 }
1965 
1973 {
1974  return GetEngineColourMap(engine_type, company, INVALID_ENGINE, nullptr);
1975 }
1976 
1983 {
1984  if (v->IsGroundVehicle()) {
1985  return GetEngineColourMap(v->engine_type, v->owner, v->GetGroundVehicleCache()->first_engine, v);
1986  }
1987 
1988  return GetEngineColourMap(v->engine_type, v->owner, INVALID_ENGINE, v);
1989 }
1990 
1995 {
1996  if (this->IsGroundVehicle()) {
1997  uint16 &gv_flags = this->GetGroundVehicleFlags();
1998  if (HasBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS)) {
1999  /* Do not delete orders, only skip them */
2001  this->cur_implicit_order_index = this->cur_real_order_index;
2002  InvalidateVehicleOrder(this, 0);
2003  return;
2004  }
2005  }
2006 
2007  const Order *order = this->GetOrder(this->cur_implicit_order_index);
2008  while (order != nullptr) {
2009  if (this->cur_implicit_order_index == this->cur_real_order_index) break;
2010 
2011  if (order->IsType(OT_IMPLICIT)) {
2012  DeleteOrder(this, this->cur_implicit_order_index);
2013  /* DeleteOrder does various magic with order_indices, so resync 'order' with 'cur_implicit_order_index' */
2014  order = this->GetOrder(this->cur_implicit_order_index);
2015  } else {
2016  /* Skip non-implicit orders, e.g. service-orders */
2017  order = order->next;
2018  this->cur_implicit_order_index++;
2019  }
2020 
2021  /* Wrap around */
2022  if (order == nullptr) {
2023  order = this->GetOrder(0);
2024  this->cur_implicit_order_index = 0;
2025  }
2026  }
2027 }
2028 
2034 {
2035  assert(IsTileType(this->tile, MP_STATION) || this->type == VEH_SHIP);
2036 
2037  if (this->current_order.IsType(OT_GOTO_STATION) &&
2038  this->current_order.GetDestination() == this->last_station_visited) {
2039  this->DeleteUnreachedImplicitOrders();
2040 
2041  /* Now both order indices point to the destination station, and we can start loading */
2042  this->current_order.MakeLoading(true);
2043  UpdateVehicleTimetable(this, true);
2044 
2045  /* Furthermore add the Non Stop flag to mark that this station
2046  * is the actual destination of the vehicle, which is (for example)
2047  * necessary to be known for HandleTrainLoading to determine
2048  * whether the train is lost or not; not marking a train lost
2049  * that arrives at random stations is bad. */
2050  this->current_order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION);
2051 
2052  } else {
2053  /* We weren't scheduled to stop here. Insert an implicit order
2054  * to show that we are stopping here.
2055  * While only groundvehicles have implicit orders, e.g. aircraft might still enter
2056  * the 'wrong' terminal when skipping orders etc. */
2057  Order *in_list = this->GetOrder(this->cur_implicit_order_index);
2058  if (this->IsGroundVehicle() &&
2059  (in_list == nullptr || !in_list->IsType(OT_IMPLICIT) ||
2060  in_list->GetDestination() != this->last_station_visited)) {
2061  bool suppress_implicit_orders = HasBit(this->GetGroundVehicleFlags(), GVF_SUPPRESS_IMPLICIT_ORDERS);
2062  /* Do not create consecutive duplicates of implicit orders */
2063  Order *prev_order = this->cur_implicit_order_index > 0 ? this->GetOrder(this->cur_implicit_order_index - 1) : (this->GetNumOrders() > 1 ? this->GetLastOrder() : nullptr);
2064  if (prev_order == nullptr ||
2065  (!prev_order->IsType(OT_IMPLICIT) && !prev_order->IsType(OT_GOTO_STATION)) ||
2066  prev_order->GetDestination() != this->last_station_visited) {
2067 
2068  /* Prefer deleting implicit orders instead of inserting new ones,
2069  * so test whether the right order follows later. In case of only
2070  * implicit orders treat the last order in the list like an
2071  * explicit one, except if the overall number of orders surpasses
2072  * IMPLICIT_ORDER_ONLY_CAP. */
2073  int target_index = this->cur_implicit_order_index;
2074  bool found = false;
2075  while (target_index != this->cur_real_order_index || this->GetNumManualOrders() == 0) {
2076  const Order *order = this->GetOrder(target_index);
2077  if (order == nullptr) break; // No orders.
2078  if (order->IsType(OT_IMPLICIT) && order->GetDestination() == this->last_station_visited) {
2079  found = true;
2080  break;
2081  }
2082  target_index++;
2083  if (target_index >= this->orders.list->GetNumOrders()) {
2084  if (this->GetNumManualOrders() == 0 &&
2085  this->GetNumOrders() < IMPLICIT_ORDER_ONLY_CAP) {
2086  break;
2087  }
2088  target_index = 0;
2089  }
2090  if (target_index == this->cur_implicit_order_index) break; // Avoid infinite loop.
2091  }
2092 
2093  if (found) {
2094  if (suppress_implicit_orders) {
2095  /* Skip to the found order */
2096  this->cur_implicit_order_index = target_index;
2097  InvalidateVehicleOrder(this, 0);
2098  } else {
2099  /* Delete all implicit orders up to the station we just reached */
2100  const Order *order = this->GetOrder(this->cur_implicit_order_index);
2101  while (!order->IsType(OT_IMPLICIT) || order->GetDestination() != this->last_station_visited) {
2102  if (order->IsType(OT_IMPLICIT)) {
2103  DeleteOrder(this, this->cur_implicit_order_index);
2104  /* DeleteOrder does various magic with order_indices, so resync 'order' with 'cur_implicit_order_index' */
2105  order = this->GetOrder(this->cur_implicit_order_index);
2106  } else {
2107  /* Skip non-implicit orders, e.g. service-orders */
2108  order = order->next;
2109  this->cur_implicit_order_index++;
2110  }
2111 
2112  /* Wrap around */
2113  if (order == nullptr) {
2114  order = this->GetOrder(0);
2115  this->cur_implicit_order_index = 0;
2116  }
2117  assert(order != nullptr);
2118  }
2119  }
2120  } else if (!suppress_implicit_orders &&
2121  ((this->orders.list == nullptr ? OrderList::CanAllocateItem() : this->orders.list->GetNumOrders() < MAX_VEH_ORDER_ID)) &&
2123  /* Insert new implicit order */
2124  Order *implicit_order = new Order();
2125  implicit_order->MakeImplicit(this->last_station_visited);
2126  InsertOrder(this, implicit_order, this->cur_implicit_order_index);
2127  if (this->cur_implicit_order_index > 0) --this->cur_implicit_order_index;
2128 
2129  /* InsertOrder disabled creation of implicit orders for all vehicles with the same implicit order.
2130  * Reenable it for this vehicle */
2131  uint16 &gv_flags = this->GetGroundVehicleFlags();
2133  }
2134  }
2135  }
2136  this->current_order.MakeLoading(false);
2137  }
2138 
2139  if (this->last_loading_station != INVALID_STATION &&
2140  this->last_loading_station != this->last_station_visited &&
2141  ((this->current_order.GetLoadType() & OLFB_NO_LOAD) == 0 ||
2142  (this->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0)) {
2143  IncreaseStats(Station::Get(this->last_loading_station), this, this->last_station_visited);
2144  }
2145 
2146  PrepareUnload(this);
2147 
2148  SetWindowDirty(GetWindowClassForVehicleType(this->type), this->owner);
2150  SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
2151  SetWindowDirty(WC_STATION_VIEW, this->last_station_visited);
2152 
2153  Station::Get(this->last_station_visited)->MarkTilesDirty(true);
2154  this->cur_speed = 0;
2155  this->MarkDirty();
2156 }
2157 
2163 void Vehicle::CancelReservation(StationID next, Station *st)
2164 {
2165  for (Vehicle *v = this; v != nullptr; v = v->next) {
2166  VehicleCargoList &cargo = v->cargo;
2167  if (cargo.ActionCount(VehicleCargoList::MTA_LOAD) > 0) {
2168  DEBUG(misc, 1, "cancelling cargo reservation");
2169  cargo.Return(UINT_MAX, &st->goods[v->cargo_type].cargo, next);
2170  cargo.SetTransferLoadPlace(st->xy);
2171  }
2172  cargo.KeepAll();
2173  }
2174 }
2175 
2181 {
2182  assert(this->current_order.IsType(OT_LOADING));
2183 
2184  delete this->cargo_payment;
2185  assert(this->cargo_payment == nullptr); // cleared by ~CargoPayment
2186 
2187  /* Only update the timetable if the vehicle was supposed to stop here. */
2188  if (this->current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE) UpdateVehicleTimetable(this, false);
2189 
2190  if ((this->current_order.GetLoadType() & OLFB_NO_LOAD) == 0 ||
2191  (this->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
2192  if (this->current_order.CanLeaveWithCargo(this->last_loading_station != INVALID_STATION)) {
2193  /* Refresh next hop stats to make sure we've done that at least once
2194  * during the stop and that refit_cap == cargo_cap for each vehicle in
2195  * the consist. */
2196  this->ResetRefitCaps();
2197  LinkRefresher::Run(this);
2198 
2199  /* if the vehicle could load here or could stop with cargo loaded set the last loading station */
2200  this->last_loading_station = this->last_station_visited;
2201  } else {
2202  /* if the vehicle couldn't load and had to unload or transfer everything
2203  * set the last loading station to invalid as it will leave empty. */
2204  this->last_loading_station = INVALID_STATION;
2205  }
2206  }
2207 
2208  this->current_order.MakeLeaveStation();
2209  Station *st = Station::Get(this->last_station_visited);
2210  this->CancelReservation(INVALID_STATION, st);
2211  st->loading_vehicles.remove(this);
2212 
2213  HideFillingPercent(&this->fill_percent_te_id);
2214  trip_occupancy = CalcPercentVehicleFilled(this, nullptr);
2215 
2216  if (this->type == VEH_TRAIN && !(this->vehstatus & VS_CRASHED)) {
2217  /* Trigger station animation (trains only) */
2218  if (IsTileType(this->tile, MP_STATION)) {
2220  TriggerStationAnimation(st, this->tile, SAT_TRAIN_DEPARTS);
2221  }
2222 
2223  SetBit(Train::From(this)->flags, VRF_LEAVING_STATION);
2224  }
2225 
2226  this->MarkDirty();
2227 }
2228 
2233 {
2234  for (Vehicle *v = this; v != nullptr; v = v->Next()) v->refit_cap = v->cargo_cap;
2235 }
2236 
2242 void Vehicle::HandleLoading(bool mode)
2243 {
2244  switch (this->current_order.GetType()) {
2245  case OT_LOADING: {
2246  uint wait_time = max(this->current_order.GetTimetabledWait() - this->lateness_counter, 0);
2247 
2248  /* Not the first call for this tick, or still loading */
2249  if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) || this->current_order_time < wait_time) return;
2250 
2251  this->PlayLeaveStationSound();
2252 
2253  this->LeaveStation();
2254 
2255  /* Only advance to next order if we just loaded at the current one */
2256  const Order *order = this->GetOrder(this->cur_implicit_order_index);
2257  if (order == nullptr ||
2258  (!order->IsType(OT_IMPLICIT) && !order->IsType(OT_GOTO_STATION)) ||
2259  order->GetDestination() != this->last_station_visited) {
2260  return;
2261  }
2262  break;
2263  }
2264 
2265  case OT_DUMMY: break;
2266 
2267  default: return;
2268  }
2269 
2270  this->IncrementImplicitOrderIndex();
2271 }
2272 
2278 {
2279  for (const Vehicle *v = this; v != nullptr; v = v->Next()) {
2280  if (v->cargo_cap == 0) continue;
2281  SmallPair<CargoID, uint> *pair = capacities.Find(v->cargo_type);
2282  if (pair == capacities.End()) {
2283  capacities.push_back({v->cargo_type, v->cargo_cap - v->cargo.StoredCount()});
2284  } else {
2285  pair->second += v->cargo_cap - v->cargo.StoredCount();
2286  }
2287  }
2288 }
2289 
2290 uint Vehicle::GetConsistTotalCapacity() const
2291 {
2292  uint result = 0;
2293  for (const Vehicle *v = this; v != nullptr; v = v->Next()) {
2294  result += v->cargo_cap;
2295  }
2296  return result;
2297 }
2298 
2306 {
2307  CommandCost ret = CheckOwnership(this->owner);
2308  if (ret.Failed()) return ret;
2309 
2310  if (this->vehstatus & VS_CRASHED) return CMD_ERROR;
2311  if (this->IsStoppedInDepot()) return CMD_ERROR;
2312 
2313  if (this->current_order.IsType(OT_GOTO_DEPOT)) {
2314  bool halt_in_depot = (this->current_order.GetDepotActionType() & ODATFB_HALT) != 0;
2315  if (!!(command & DEPOT_SERVICE) == halt_in_depot) {
2316  /* We called with a different DEPOT_SERVICE setting.
2317  * Now we change the setting to apply the new one and let the vehicle head for the same depot.
2318  * Note: the if is (true for requesting service == true for ordered to stop in depot) */
2319  if (flags & DC_EXEC) {
2320  this->current_order.SetDepotOrderType(ODTF_MANUAL);
2321  this->current_order.SetDepotActionType(halt_in_depot ? ODATF_SERVICE_ONLY : ODATFB_HALT);
2323  }
2324  return CommandCost();
2325  }
2326 
2327  if (command & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancellation of depot orders
2328  if (flags & DC_EXEC) {
2329  /* If the orders to 'goto depot' are in the orders list (forced servicing),
2330  * then skip to the next order; effectively cancelling this forced service */
2331  if (this->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) this->IncrementRealOrderIndex();
2332 
2333  if (this->IsGroundVehicle()) {
2334  uint16 &gv_flags = this->GetGroundVehicleFlags();
2336  }
2337 
2338  this->current_order.MakeDummy();
2340  }
2341  return CommandCost();
2342  }
2343 
2344  TileIndex location;
2345  DestinationID destination;
2346  bool reverse;
2347  static const StringID no_depot[] = {STR_ERROR_UNABLE_TO_FIND_ROUTE_TO, STR_ERROR_UNABLE_TO_FIND_LOCAL_DEPOT, STR_ERROR_UNABLE_TO_FIND_LOCAL_DEPOT, STR_ERROR_CAN_T_SEND_AIRCRAFT_TO_HANGAR};
2348  if (!this->FindClosestDepot(&location, &destination, &reverse)) return_cmd_error(no_depot[this->type]);
2349 
2350  if (flags & DC_EXEC) {
2351  if (this->current_order.IsType(OT_LOADING)) this->LeaveStation();
2352 
2353  if (this->IsGroundVehicle() && this->GetNumManualOrders() > 0) {
2354  uint16 &gv_flags = this->GetGroundVehicleFlags();
2356  }
2357 
2358  this->SetDestTile(location);
2359  this->current_order.MakeGoToDepot(destination, ODTF_MANUAL);
2360  if (!(command & DEPOT_SERVICE)) this->current_order.SetDepotActionType(ODATFB_HALT);
2362 
2363  /* If there is no depot in front and the train is not already reversing, reverse automatically (trains only) */
2364  if (this->type == VEH_TRAIN && (reverse ^ HasBit(Train::From(this)->flags, VRF_REVERSING))) {
2365  DoCommand(this->tile, this->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
2366  }
2367 
2368  if (this->type == VEH_AIRCRAFT) {
2369  Aircraft *a = Aircraft::From(this);
2370  if (a->state == FLYING && a->targetairport != destination) {
2371  /* The aircraft is now heading for a different hangar than the next in the orders */
2374  }
2375  }
2376  }
2377 
2378  return CommandCost();
2379 
2380 }
2381 
2386 void Vehicle::UpdateVisualEffect(bool allow_power_change)
2387 {
2388  bool powered_before = HasBit(this->vcache.cached_vis_effect, VE_DISABLE_WAGON_POWER);
2389  const Engine *e = this->GetEngine();
2390 
2391  /* Evaluate properties */
2392  byte visual_effect;
2393  switch (e->type) {
2394  case VEH_TRAIN: visual_effect = e->u.rail.visual_effect; break;
2395  case VEH_ROAD: visual_effect = e->u.road.visual_effect; break;
2396  case VEH_SHIP: visual_effect = e->u.ship.visual_effect; break;
2397  default: visual_effect = 1 << VE_DISABLE_EFFECT; break;
2398  }
2399 
2400  /* Check powered wagon / visual effect callback */
2402  uint16 callback = GetVehicleCallback(CBID_VEHICLE_VISUAL_EFFECT, 0, 0, this->engine_type, this);
2403 
2404  if (callback != CALLBACK_FAILED) {
2405  if (callback >= 0x100 && e->GetGRF()->grf_version >= 8) ErrorUnknownCallbackResult(e->GetGRFID(), CBID_VEHICLE_VISUAL_EFFECT, callback);
2406 
2407  callback = GB(callback, 0, 8);
2408  /* Avoid accidentally setting 'visual_effect' to the default value
2409  * Since bit 6 (disable effects) is set anyways, we can safely erase some bits. */
2410  if (callback == VE_DEFAULT) {
2411  assert(HasBit(callback, VE_DISABLE_EFFECT));
2412  SB(callback, VE_TYPE_START, VE_TYPE_COUNT, 0);
2413  }
2414  visual_effect = callback;
2415  }
2416  }
2417 
2418  /* Apply default values */
2419  if (visual_effect == VE_DEFAULT ||
2420  (!HasBit(visual_effect, VE_DISABLE_EFFECT) && GB(visual_effect, VE_TYPE_START, VE_TYPE_COUNT) == VE_TYPE_DEFAULT)) {
2421  /* Only train engines have default effects.
2422  * Note: This is independent of whether the engine is a front engine or articulated part or whatever. */
2423  if (e->type != VEH_TRAIN || e->u.rail.railveh_type == RAILVEH_WAGON || !IsInsideMM(e->u.rail.engclass, EC_STEAM, EC_MONORAIL)) {
2424  if (visual_effect == VE_DEFAULT) {
2425  visual_effect = 1 << VE_DISABLE_EFFECT;
2426  } else {
2427  SetBit(visual_effect, VE_DISABLE_EFFECT);
2428  }
2429  } else {
2430  if (visual_effect == VE_DEFAULT) {
2431  /* Also set the offset */
2432  visual_effect = (VE_OFFSET_CENTRE - (e->u.rail.engclass == EC_STEAM ? 4 : 0)) << VE_OFFSET_START;
2433  }
2434  SB(visual_effect, VE_TYPE_START, VE_TYPE_COUNT, e->u.rail.engclass - EC_STEAM + VE_TYPE_STEAM);
2435  }
2436  }
2437 
2438  this->vcache.cached_vis_effect = visual_effect;
2439 
2440  if (!allow_power_change && powered_before != HasBit(this->vcache.cached_vis_effect, VE_DISABLE_WAGON_POWER)) {
2441  ToggleBit(this->vcache.cached_vis_effect, VE_DISABLE_WAGON_POWER);
2442  ShowNewGrfVehicleError(this->engine_type, STR_NEWGRF_BROKEN, STR_NEWGRF_BROKEN_POWERED_WAGON, GBUG_VEH_POWERED_WAGON, false);
2443  }
2444 }
2445 
2446 static const int8 _vehicle_smoke_pos[8] = {
2447  1, 1, 1, 0, -1, -1, -1, 0
2448 };
2449 
2454 static void SpawnAdvancedVisualEffect(const Vehicle *v)
2455 {
2456  uint16 callback = GetVehicleCallback(CBID_VEHICLE_SPAWN_VISUAL_EFFECT, 0, Random(), v->engine_type, v);
2457  if (callback == CALLBACK_FAILED) return;
2458 
2459  uint count = GB(callback, 0, 2);
2460  bool auto_center = HasBit(callback, 13);
2461  bool auto_rotate = !HasBit(callback, 14);
2462 
2463  int8 l_center = 0;
2464  if (auto_center) {
2465  /* For road vehicles: Compute offset from vehicle position to vehicle center */
2466  if (v->type == VEH_ROAD) l_center = -(int)(VEHICLE_LENGTH - RoadVehicle::From(v)->gcache.cached_veh_length) / 2;
2467  } else {
2468  /* For trains: Compute offset from vehicle position to sprite position */
2469  if (v->type == VEH_TRAIN) l_center = (VEHICLE_LENGTH - Train::From(v)->gcache.cached_veh_length) / 2;
2470  }
2471 
2472  Direction l_dir = v->direction;
2473  if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_REVERSE_DIRECTION)) l_dir = ReverseDir(l_dir);
2474  Direction t_dir = ChangeDir(l_dir, DIRDIFF_90RIGHT);
2475 
2476  int8 x_center = _vehicle_smoke_pos[l_dir] * l_center;
2477  int8 y_center = _vehicle_smoke_pos[t_dir] * l_center;
2478 
2479  for (uint i = 0; i < count; i++) {
2480  uint32 reg = GetRegister(0x100 + i);
2481  uint type = GB(reg, 0, 8);
2482  int8 x = GB(reg, 8, 8);
2483  int8 y = GB(reg, 16, 8);
2484  int8 z = GB(reg, 24, 8);
2485 
2486  if (auto_rotate) {
2487  int8 l = x;
2488  int8 t = y;
2489  x = _vehicle_smoke_pos[l_dir] * l + _vehicle_smoke_pos[t_dir] * t;
2490  y = _vehicle_smoke_pos[t_dir] * l - _vehicle_smoke_pos[l_dir] * t;
2491  }
2492 
2493  if (type >= 0xF0) {
2494  switch (type) {
2495  case 0xF1: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_STEAM_SMOKE); break;
2496  case 0xF2: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_DIESEL_SMOKE); break;
2497  case 0xF3: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_ELECTRIC_SPARK); break;
2498  case 0xFA: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_BREAKDOWN_SMOKE_AIRCRAFT); break;
2499  default: break;
2500  }
2501  }
2502  }
2503 }
2504 
2510 {
2511  assert(this->IsPrimaryVehicle());
2512  bool sound = false;
2513 
2514  /* Do not show any smoke when:
2515  * - vehicle smoke is disabled by the player
2516  * - the vehicle is slowing down or stopped (by the player)
2517  * - the vehicle is moving very slowly
2518  */
2519  if (_settings_game.vehicle.smoke_amount == 0 ||
2520  this->vehstatus & (VS_TRAIN_SLOWING | VS_STOPPED) ||
2521  this->cur_speed < 2) {
2522  return;
2523  }
2524 
2525  /* Use the speed as limited by underground and orders. */
2526  uint max_speed = this->GetCurrentMaxSpeed();
2527 
2528  if (this->type == VEH_TRAIN) {
2529  const Train *t = Train::From(this);
2530  /* For trains, do not show any smoke when:
2531  * - the train is reversing
2532  * - is entering a station with an order to stop there and its speed is equal to maximum station entering speed
2533  */
2534  if (HasBit(t->flags, VRF_REVERSING) ||
2536  t->cur_speed >= max_speed)) {
2537  return;
2538  }
2539  }
2540 
2541  const Vehicle *v = this;
2542 
2543  do {
2544  bool advanced = HasBit(v->vcache.cached_vis_effect, VE_ADVANCED_EFFECT);
2546  VisualEffectSpawnModel effect_model = VESM_NONE;
2547  if (advanced) {
2548  effect_offset = VE_OFFSET_CENTRE;
2550  if (effect_model >= VESM_END) effect_model = VESM_NONE; // unknown spawning model
2551  } else {
2553  assert(effect_model != (VisualEffectSpawnModel)VE_TYPE_DEFAULT); // should have been resolved by UpdateVisualEffect
2554  assert_compile((uint)VESM_STEAM == (uint)VE_TYPE_STEAM);
2555  assert_compile((uint)VESM_DIESEL == (uint)VE_TYPE_DIESEL);
2556  assert_compile((uint)VESM_ELECTRIC == (uint)VE_TYPE_ELECTRIC);
2557  }
2558 
2559  /* Show no smoke when:
2560  * - Smoke has been disabled for this vehicle
2561  * - The vehicle is not visible
2562  * - The vehicle is under a bridge
2563  * - The vehicle is on a depot tile
2564  * - The vehicle is on a tunnel tile
2565  * - The vehicle is a train engine that is currently unpowered */
2566  if (effect_model == VESM_NONE ||
2567  v->vehstatus & VS_HIDDEN ||
2568  IsBridgeAbove(v->tile) ||
2569  IsDepotTile(v->tile) ||
2570  IsTunnelTile(v->tile) ||
2571  (v->type == VEH_TRAIN &&
2572  !HasPowerOnRail(Train::From(v)->railtype, GetTileRailType(v->tile)))) {
2573  continue;
2574  }
2575 
2576  EffectVehicleType evt = EV_END;
2577  switch (effect_model) {
2578  case VESM_STEAM:
2579  /* Steam smoke - amount is gradually falling until vehicle reaches its maximum speed, after that it's normal.
2580  * Details: while vehicle's current speed is gradually increasing, steam plumes' density decreases by one third each
2581  * third of its maximum speed spectrum. Steam emission finally normalises at very close to vehicle's maximum speed.
2582  * REGULATION:
2583  * - instead of 1, 4 / 2^smoke_amount (max. 2) is used to provide sufficient regulation to steam puffs' amount. */
2584  if (GB(v->tick_counter, 0, ((4 >> _settings_game.vehicle.smoke_amount) + ((this->cur_speed * 3) / max_speed))) == 0) {
2585  evt = EV_STEAM_SMOKE;
2586  }
2587  break;
2588 
2589  case VESM_DIESEL: {
2590  /* Diesel smoke - thicker when vehicle is starting, gradually subsiding till it reaches its maximum speed
2591  * when smoke emission stops.
2592  * Details: Vehicle's (max.) speed spectrum is divided into 32 parts. When max. speed is reached, chance for smoke
2593  * emission erodes by 32 (1/4). For trains, power and weight come in handy too to either increase smoke emission in
2594  * 6 steps (1000HP each) if the power is low or decrease smoke emission in 6 steps (512 tonnes each) if the train
2595  * isn't overweight. Power and weight contributions are expressed in a way that neither extreme power, nor
2596  * extreme weight can ruin the balance (e.g. FreightWagonMultiplier) in the formula. When the vehicle reaches
2597  * maximum speed no diesel_smoke is emitted.
2598  * REGULATION:
2599  * - up to which speed a diesel vehicle is emitting smoke (with reduced/small setting only until 1/2 of max_speed),
2600  * - in Chance16 - the last value is 512 / 2^smoke_amount (max. smoke when 128 = smoke_amount of 2). */
2601  int power_weight_effect = 0;
2602  if (v->type == VEH_TRAIN) {
2603  power_weight_effect = (32 >> (Train::From(this)->gcache.cached_power >> 10)) - (32 >> (Train::From(this)->gcache.cached_weight >> 9));
2604  }
2605  if (this->cur_speed < (max_speed >> (2 >> _settings_game.vehicle.smoke_amount)) &&
2606  Chance16((64 - ((this->cur_speed << 5) / max_speed) + power_weight_effect), (512 >> _settings_game.vehicle.smoke_amount))) {
2607  evt = EV_DIESEL_SMOKE;
2608  }
2609  break;
2610  }
2611 
2612  case VESM_ELECTRIC:
2613  /* Electric train's spark - more often occurs when train is departing (more load)
2614  * Details: Electric locomotives are usually at least twice as powerful as their diesel counterparts, so spark
2615  * emissions are kept simple. Only when starting, creating huge force are sparks more likely to happen, but when
2616  * reaching its max. speed, quarter by quarter of it, chance decreases until the usual 2,22% at train's top speed.
2617  * REGULATION:
2618  * - in Chance16 the last value is 360 / 2^smoke_amount (max. sparks when 90 = smoke_amount of 2). */
2619  if (GB(v->tick_counter, 0, 2) == 0 &&
2620  Chance16((6 - ((this->cur_speed << 2) / max_speed)), (360 >> _settings_game.vehicle.smoke_amount))) {
2621  evt = EV_ELECTRIC_SPARK;
2622  }
2623  break;
2624 
2625  default:
2626  NOT_REACHED();
2627  }
2628 
2629  if (evt != EV_END && advanced) {
2630  sound = true;
2632  } else if (evt != EV_END) {
2633  sound = true;
2634 
2635  /* The effect offset is relative to a point 4 units behind the vehicle's
2636  * front (which is the center of an 8/8 vehicle). Shorter vehicles need a
2637  * correction factor. */
2638  if (v->type == VEH_TRAIN) effect_offset += (VEHICLE_LENGTH - Train::From(v)->gcache.cached_veh_length) / 2;
2639 
2640  int x = _vehicle_smoke_pos[v->direction] * effect_offset;
2641  int y = _vehicle_smoke_pos[(v->direction + 2) % 8] * effect_offset;
2642 
2643  if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_REVERSE_DIRECTION)) {
2644  x = -x;
2645  y = -y;
2646  }
2647 
2648  CreateEffectVehicleRel(v, x, y, 10, evt);
2649  }
2650  } while ((v = v->Next()) != nullptr);
2651 
2652  if (sound) PlayVehicleSound(this, VSE_VISUAL_EFFECT);
2653 }
2654 
2660 {
2661  assert(this != next);
2662 
2663  if (this->next != nullptr) {
2664  /* We had an old next vehicle. Update the first and previous pointers */
2665  for (Vehicle *v = this->next; v != nullptr; v = v->Next()) {
2666  v->first = this->next;
2667  }
2668  this->next->previous = nullptr;
2669  }
2670 
2671  this->next = next;
2672 
2673  if (this->next != nullptr) {
2674  /* A new next vehicle. Update the first and previous pointers */
2675  if (this->next->previous != nullptr) this->next->previous->next = nullptr;
2676  this->next->previous = this;
2677  for (Vehicle *v = this->next; v != nullptr; v = v->Next()) {
2678  v->first = this->first;
2679  }
2680  }
2681 }
2682 
2688 void Vehicle::AddToShared(Vehicle *shared_chain)
2689 {
2690  assert(this->previous_shared == nullptr && this->next_shared == nullptr);
2691 
2692  if (shared_chain->orders.list == nullptr) {
2693  assert(shared_chain->previous_shared == nullptr);
2694  assert(shared_chain->next_shared == nullptr);
2695  this->orders.list = shared_chain->orders.list = new OrderList(nullptr, shared_chain);
2696  }
2697 
2698  this->next_shared = shared_chain->next_shared;
2699  this->previous_shared = shared_chain;
2700 
2701  shared_chain->next_shared = this;
2702 
2703  if (this->next_shared != nullptr) this->next_shared->previous_shared = this;
2704 
2705  shared_chain->orders.list->AddVehicle(this);
2706 }
2707 
2712 {
2713  /* Remember if we were first and the old window number before RemoveVehicle()
2714  * as this changes first if needed. */
2715  bool were_first = (this->FirstShared() == this);
2716  VehicleListIdentifier vli(VL_SHARED_ORDERS, this->type, this->owner, this->FirstShared()->index);
2717 
2718  this->orders.list->RemoveVehicle(this);
2719 
2720  if (!were_first) {
2721  /* We are not the first shared one, so only relink our previous one. */
2722  this->previous_shared->next_shared = this->NextShared();
2723  }
2724 
2725  if (this->next_shared != nullptr) this->next_shared->previous_shared = this->previous_shared;
2726 
2727 
2728  if (this->orders.list->GetNumVehicles() == 1) {
2729  /* When there is only one vehicle, remove the shared order list window. */
2731  InvalidateVehicleOrder(this->FirstShared(), VIWD_MODIFY_ORDERS);
2732  } else if (were_first) {
2733  /* If we were the first one, update to the new first one.
2734  * Note: FirstShared() is already the new first */
2735  InvalidateWindowData(GetWindowClassForVehicleType(this->type), vli.Pack(), this->FirstShared()->index | (1U << 31));
2736  }
2737 
2738  this->next_shared = nullptr;
2739  this->previous_shared = nullptr;
2740 }
2741 
2742 void VehiclesYearlyLoop()
2743 {
2744  for (Vehicle *v : Vehicle::Iterate()) {
2745  if (v->IsPrimaryVehicle()) {
2746  /* show warning if vehicle is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */
2747  Money profit = v->GetDisplayProfitThisYear();
2748  if (v->age >= 730 && profit < 0) {
2750  SetDParam(0, v->index);
2751  SetDParam(1, profit);
2752  AddVehicleAdviceNewsItem(STR_NEWS_VEHICLE_IS_UNPROFITABLE, v->index);
2753  }
2754  AI::NewEvent(v->owner, new ScriptEventVehicleUnprofitable(v->index));
2755  }
2756 
2758  v->profit_this_year = 0;
2760  }
2761  }
2767 }
2768 
2769 
2779 bool CanVehicleUseStation(EngineID engine_type, const Station *st)
2780 {
2781  const Engine *e = Engine::GetIfValid(engine_type);
2782  assert(e != nullptr);
2783 
2784  switch (e->type) {
2785  case VEH_TRAIN:
2786  return (st->facilities & FACIL_TRAIN) != 0;
2787 
2788  case VEH_ROAD:
2789  /* For road vehicles we need the vehicle to know whether it can actually
2790  * use the station, but if it doesn't have facilities for RVs it is
2791  * certainly not possible that the station can be used. */
2792  return (st->facilities & (FACIL_BUS_STOP | FACIL_TRUCK_STOP)) != 0;
2793 
2794  case VEH_SHIP:
2795  return (st->facilities & FACIL_DOCK) != 0;
2796 
2797  case VEH_AIRCRAFT:
2798  return (st->facilities & FACIL_AIRPORT) != 0 &&
2800 
2801  default:
2802  return false;
2803  }
2804 }
2805 
2812 bool CanVehicleUseStation(const Vehicle *v, const Station *st)
2813 {
2814  if (v->type == VEH_ROAD) return st->GetPrimaryRoadStop(RoadVehicle::From(v)) != nullptr;
2815 
2816  return CanVehicleUseStation(v->engine_type, st);
2817 }
2818 
2825 {
2826  assert(this->IsGroundVehicle());
2827  if (this->type == VEH_TRAIN) {
2828  return &Train::From(this)->gcache;
2829  } else {
2830  return &RoadVehicle::From(this)->gcache;
2831  }
2832 }
2833 
2840 {
2841  assert(this->IsGroundVehicle());
2842  if (this->type == VEH_TRAIN) {
2843  return &Train::From(this)->gcache;
2844  } else {
2845  return &RoadVehicle::From(this)->gcache;
2846  }
2847 }
2848 
2855 {
2856  assert(this->IsGroundVehicle());
2857  if (this->type == VEH_TRAIN) {
2858  return Train::From(this)->gv_flags;
2859  } else {
2860  return RoadVehicle::From(this)->gv_flags;
2861  }
2862 }
2863 
2869 const uint16 &Vehicle::GetGroundVehicleFlags() const
2870 {
2871  assert(this->IsGroundVehicle());
2872  if (this->type == VEH_TRAIN) {
2873  return Train::From(this)->gv_flags;
2874  } else {
2875  return RoadVehicle::From(this)->gv_flags;
2876  }
2877 }
2878 
2887 void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8 num_vehicles)
2888 {
2889  if (v->type == VEH_TRAIN) {
2890  Train *u = Train::From(v);
2891  /* Only include whole vehicles, so start with the first articulated part */
2892  u = u->GetFirstEnginePart();
2893 
2894  /* Include num_vehicles vehicles, not counting articulated parts */
2895  for (; u != nullptr && num_vehicles > 0; num_vehicles--) {
2896  do {
2897  /* Include current vehicle in the selection. */
2898  include(set, u->index);
2899 
2900  /* If the vehicle is multiheaded, add the other part too. */
2901  if (u->IsMultiheaded()) include(set, u->other_multiheaded_part->index);
2902 
2903  u = u->Next();
2904  } while (u != nullptr && u->IsArticulatedPart());
2905  }
2906  }
2907 }
void ViewportAddVehicles(DrawPixelInfo *dpi)
Add the vehicle sprites that should be drawn at a part of the screen.
Definition: vehicle.cpp:1107
Functions related to OTTD&#39;s strings.
void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigger trigger, CargoID cargo_type)
Trigger station randomisation.
static TileType GetTileType(TileIndex tile)
Get the tiletype of a given tile.
Definition: tile_map.h:96
Owner
Enum for all companies/owners.
Definition: company_type.h:18
Road vehicle states.
Normal operation.
Definition: train.h:38
bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Checks whether a vehicle is on a specific location.
Definition: vehicle.cpp:511
VehicleSettings vehicle
options for vehicles
static bool HasPowerOnRail(RailType enginetype, RailType tiletype)
Checks if an engine of the given RailType got power on a tile with a given RailType.
Definition: rail.h:332
Functions/types related to NewGRF debugging.
uint16 reliability
Current reliability of the engine.
Definition: engine_base.h:25
CommandCost EnsureNoTrainOnTrackBits(TileIndex tile, TrackBits track_bits)
Tests if a vehicle interacts with the specified track bits.
Definition: vehicle.cpp:599
Date max_age
Maximum age.
Definition: vehicle_base.h:257
uint32 PaletteID
The number of the palette.
Definition: gfx_type.h:18
static bool IsLocalCompany()
Is the current company the local company?
Definition: company_func.h:43
StationFacility facilities
The facilities that this station has.
Vehicle * Previous() const
Get the previous vehicle of this vehicle.
Definition: vehicle_base.h:586
Vehicle is stopped by the player.
Definition: vehicle_base.h:31
Time spent processing cargo movement.
VehicleCargoList cargo
The cargo this vehicle is carrying.
Definition: vehicle_base.h:307
byte state
Definition: roadveh.h:109
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:79
static void RunVehicleDayProc()
Increases the day counter for all vehicles and calls 1-day and 32-day handlers.
Definition: vehicle.cpp:910
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:302
uint32 motion_counter
counter to occasionally play a vehicle sound.
Definition: vehicle_base.h:294
Money value
Value of the vehicle.
Definition: vehicle_base.h:239
bool _networking
are we in networking mode?
Definition: network.cpp:52
int virtual_left
Virtual left coordinate.
Definition: viewport_type.h:28
void DecreaseVehicleValue(Vehicle *v)
Decrease the value of a vehicle.
Definition: vehicle.cpp:1199
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
void LoadUnloadStation(Station *st)
Load/unload the vehicles in this station according to the order they entered.
Definition: economy.cpp:1905
Data about how and where to blit pixels.
Definition: gfx_type.h:154
virtual void MarkDirty()
Marks the vehicles to be redrawn and updates cached variables.
Definition: vehicle_base.h:362
The information about a vehicle list.
Definition: vehiclelist.h:29
Direction direction
facing
Definition: vehicle_base.h:269
void ShowVisualEffect() const
Draw visual effects (smoke and/or sparks) for a vehicle chain.
Definition: vehicle.cpp:2509
bool UsesWagonOverride(const Vehicle *v)
Check if a wagon is currently using a wagon override.
Definition of link refreshing utility.
StationID targetairport
Airport to go to next.
Definition: aircraft.h:78
static const int VEHICLE_PROFIT_MIN_AGE
Only vehicles older than this have a meaningful profit.
Definition: vehicle_func.h:27
LiveryScheme
List of different livery schemes.
Definition: livery.h:20
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3215
byte landscape
the landscape we&#39;re currently in
static bool Chance16I(const uint a, const uint b, const uint32 r)
Checks if a given randomize-number is below a given probability.
Money GetDisplayProfitThisYear() const
Gets the profit vehicle had this year.
Definition: vehicle_base.h:564
Base class for roadstops.
Vehicle * hash_tile_next
NOSAVE: Next vehicle in the tile location hash.
Definition: vehicle_base.h:248
Functions related to the autoreplace GUIs.
void ResetRefitCaps()
Reset all refit_cap in the consist to cargo_cap.
Definition: vehicle.cpp:2232
Train is just leaving a station.
Definition: train.h:33
Don&#39;t cancel current goto depot command if any.
Definition: vehicle_type.h:68
Vehicle has finished loading.
Definition: vehicle_base.h:42
Functions and type for generating vehicle lists.
Aircraft is broken down.
Definition: vehicle_base.h:36
static RoadStopType GetRoadStopType(TileIndex t)
Get the road stop type of this tile.
Definition: station_map.h:56
CommandCost EnsureNoVehicleOnGround(TileIndex tile)
Ensure there is no vehicle at the ground at the given position.
Definition: vehicle.cpp:537
Functions related to time tabling.
VehiclePool _vehicle_pool("Vehicle")
The pool with all our precious vehicles.
void InvalidateVehicleOrder(const Vehicle *v, int data)
Updates the widgets of a vehicle which contains the order-data.
Definition: order_cmd.cpp:250
void HandleAircraftEnterHangar(Aircraft *v)
Handle Aircraft specific tasks when an Aircraft enters a hangar.
Train vehicle type.
Definition: vehicle_type.h:24
union Vehicle::@49 orders
The orders currently assigned to the vehicle.
int height
Screen height of the viewport.
Definition: viewport_type.h:26
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:291
static Point RemapCoords(int x, int y, int z)
Map 3D world or tile coordinate to equivalent 2D coordinate as used in the viewports and smallmap...
Definition: landscape.h:82
Functions related to dates.
Angle of 45 degrees left.
virtual uint Crash(bool flooded=false)
Crash the (whole) vehicle chain.
Definition: vehicle.cpp:259
Vehicle ** hash_viewport_prev
NOSAVE: Previous vehicle in the visual location hash.
Definition: vehicle_base.h:246
Conventional Take Off and Landing, i.e. planes.
Definition: engine_type.h:92
static T ToggleBit(T &x, const uint8 y)
Toggles a bit in a variable.
const AirportFTAClass * GetFTA() const
Get the finite-state machine for this airport or the finite-state machine for the dummy airport in ca...
Definition: station_base.h:332
Sparcs of electric engines.
byte breakdown_delay
Counter for managing breakdown length.
Definition: vehicle_base.h:262
Use default vehicle palette.
Definition: vehicle_base.h:33
Angle of 90 degrees right.
West.
Vehicle is a shadow vehicle.
Definition: vehicle_base.h:35
Smoke of diesel engines.
Base for the train class.
Other order modifications.
Definition: vehicle_gui.h:33
uint8 smoke_amount
amount of smoke/sparks locomotives produce
virtual ~Vehicle()
We want to &#39;destruct&#39; the right class.
Definition: vehicle.cpp:866
static T SetBit(T &x, const uint8 y)
Set a bit in a variable.
Called to spawn visual effects for vehicles.
void Leave(RoadVehicle *rv)
Leave the road stop.
Definition: roadstop.cpp:216
byte pos
Next desired position of the aircraft.
Definition: aircraft.h:76
void SetTransferLoadPlace(TileIndex xy)
Sets loaded_at_xy to the current station for all cargo to be transferred.
Can planes land on this airport type?
Definition: airport.h:147
uint16 cur_speed
current speed
Definition: vehicle_base.h:291
uint16 cached_cargo_age_period
Number of ticks before carried cargo is aged.
Definition: vehicle_base.h:122
static void AddVehicleAdviceNewsItem(StringID string, VehicleID vehicle)
Adds a vehicle-advice news item.
Definition: news_func.h:40
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:23
Do not show black smoke during a breakdown.
Definition: engine_type.h:160
Data structure describing a sprite.
Definition: spritecache.h:16
No visual effect.
Definition: vehicle_base.h:97
Ship vehicle type.
Definition: vehicle_type.h:26
Depot view; Window numbers:
Definition: window_type.h:344
uint16 cargo_age_counter
Ticks till cargo is aged next.
Definition: vehicle_base.h:308
GRFFilePropsBase< NUM_CARGO+2 > grf_prop
Properties related the the grf file.
Definition: engine_base.h:58
Functions to be called to log possibly unsafe game events.
Types for recording game performance data.
Both directions faces to the same direction.
uint16 _returned_refit_capacity
Stores the capacity after a refit operation.
Definition: vehicle.cpp:85
std::vector< Pair >::const_iterator Find(const T &key) const
Finds given key in this map.
VehicleType
Available vehicle types.
Definition: vehicle_type.h:21
OrderList * list
Pointer to the order list for this vehicle.
Definition: vehicle_base.h:319
Train * GetNextUnit() const
Get the next real (non-articulated part and non rear part of dualheaded engine) vehicle in the consis...
Definition: train.h:143
StationID last_loading_station
Last station the vehicle has stopped at and could possibly leave from with any cargo loaded...
Definition: vehicle_base.h:301
byte visual_effect
Bitstuffed NewGRF visual effect data.
Definition: engine_type.h:123
TileIndex dest_tile
Heading for this tile.
Definition: vehicle_base.h:235
Vehicle ** hash_tile_prev
NOSAVE: Previous vehicle in the tile location hash.
Definition: vehicle_base.h:249
uint16 wait_counter
Ticks waiting in front of a signal, ticks being stuck or a counter for forced proceeding through sign...
Definition: train.h:100
Implementation of simple mapping class.
Functions related to vehicles.
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition: aircraft.h:74
static bool IsWagon(EngineID index)
Determine whether an engine type is a wagon (and not a loco).
Definition: engine.cpp:567
bool lost_vehicle_warn
if a vehicle can&#39;t find its destination, show a warning
Definition: settings_type.h:84
void IncrementImplicitOrderIndex()
Increments cur_implicit_order_index, keeps care of the wrap-around and invalidates the GUI...
Definition: vehicle_base.h:798
Trigger platform when train leaves.
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:205
void VehicleEnterDepot(Vehicle *v)
Vehicle entirely entered the depot, update its status, orders, vehicle windows, service it...
Definition: vehicle.cpp:1436
const Livery * GetEngineLivery(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v, byte livery_setting)
Determines the livery for a vehicle.
Definition: vehicle.cpp:1894
void Draw(int x, int y, PaletteID default_pal, bool force_pal) const
Draw the sprite sequence.
Definition: vehicle.cpp:126
Vehicle data structure.
Definition: vehicle_base.h:210
UnitID max_aircraft
max planes in game per company
byte vehicle_breakdowns
likelihood of vehicles breaking down
Definition: settings_type.h:61
Flags flags
Flags for this airport type.
Definition: airport.h:180
void Change(const U &new_value)
Change the value of the variable.
Definition: backup_type.hpp:84
static int ScaleByZoom(int value, ZoomLevel zoom)
Scale by zoom level, usually shift left (when zoom > ZOOM_LVL_NORMAL) When shifting right...
Definition: zoom_func.h:22
Only service the vehicle.
Definition: order_type.h:103
void PreDestructor()
Destroy all stuff that (still) needs the virtual functions to work properly.
Definition: vehicle.cpp:800
void LeaveStation()
Perform all actions when leaving a station.
Definition: vehicle.cpp:2180
DifficultySettings difficulty
settings related to the difficulty
Start or stop this vehicle, and show information about the current state.
Tindex index
Index of this pool item.
Definition: pool_type.hpp:189
Vehicle is flying in the air.
Definition: airport.h:75
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=nullptr, uint textref_stack_size=0, const uint32 *textref_stack=nullptr)
Display an error message in a window.
Definition: error_gui.cpp:380
A special vehicle is one of the following:
static const int DAY_TICKS
1 day is 74 ticks; _date_fract used to be uint16 and incremented by 885.
Definition: date_type.h:28
PaletteID GetVehiclePalette(const Vehicle *v)
Get the colour map for a vehicle.
Definition: vehicle.cpp:1982
void SetNext(Vehicle *next)
Set the next vehicle of this vehicle.
Definition: vehicle.cpp:2659
void UpdateViewport(bool force_update, bool update_delta)
Update vehicle sprite- and position caches.
Vehicle is unloading cargo.
Definition: vehicle_base.h:43
bool IsMultiheaded() const
Check if the vehicle is a multiheaded engine.
Base for aircraft.
StationID last_station_visited
The last station we stopped at.
Definition: vehicle_base.h:300
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:48
uint16 reliability_spd_dec
Reliability decrease speed.
Definition: vehicle_base.h:260
Electric model.
Definition: vehicle_base.h:100
void UpdateViewport(bool dirty)
Update the vehicle on the viewport, updating the right hash and setting the new coordinates.
Definition: vehicle.cpp:1569
void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indices)
Delete all orders from a vehicle.
Definition: order_cmd.cpp:1888
void MarkTilesDirty(bool cargo_change) const
Marks the tiles of the station as dirty.
Definition: station.cpp:218
static Pool::IterateWrapper< Station > Iterate(size_t from=0)
Returns an iterable ensemble of all valid stations of type T.
Money GetCost() const
The costs as made up to this moment.
Definition: command_type.h:82
void HandlePathfindingResult(bool path_found)
Handle the pathfinding result, especially the lost status.
Definition: vehicle.cpp:773
bool IsArticulatedVehicleCarryingDifferentCargoes(const Vehicle *v, CargoID *cargo_type)
Tests if all parts of an articulated vehicle are refitted to the same cargo.
void AircraftNextAirportPos_and_Order(Aircraft *v)
set the right pos when heading to other airports after takeoff
Visual effects and wagon power.
#define CLRBITS(x, y)
Clears several bits in a variable.
T * GetFirstEnginePart()
Get the first part of an articulated engine.
static const byte LIT_COMPANY
Show the liveries of your own company.
Definition: livery.h:16
LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_type, const Vehicle *v)
Determines the LiveryScheme for a vehicle.
Definition: vehicle.cpp:1803
First bit that contains the offset (0 = front, 8 = centre, 15 = rear)
Definition: vehicle_base.h:77
Flag for an invalid DiagDirection.
Common return value for all commands.
Definition: command_type.h:23
uint32 cached_power
Total power of the consist (valid only for the first engine).
GrfSpecFeature GetGrfSpecFeature(TileIndex tile)
Get the GrfSpecFeature associated with the tile.
void StartSpriteCombine()
Starts a block of sprites, which are "combined" into a single bounding box.
Definition: viewport.cpp:757
RAII class for measuring simple elements of performance.
StationCargoList cargo
The cargo packets of cargo waiting in this station.
Definition: station_base.h:255
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:24
void MarkAllViewportsDirty() const
Marks viewports dirty where the vehicle&#39;s image is.
Definition: vehicle.cpp:1610
bool HasRating() const
Does this cargo have a rating at this station?
Definition: station_base.h:273
byte vehstatus
Status.
Definition: vehicle_base.h:315
UnitID GetFreeUnitNumber(VehicleType type)
Get an unused unit number for a vehicle (if allowed).
Definition: vehicle.cpp:1725
Cached, frequently calculated values.
uint StoredCount() const
Returns sum of cargo on board the vehicle (ie not only reserved).
Definition: cargopacket.h:351
uint Return(uint max_move, StationCargoList *dest, StationID next_station)
Returns reserved cargo to the station and removes it from the cache.
Time spent processing aircraft.
static void Reset(PerformanceElement elem)
Store the previous accumulator value and reset for a new cycle of accumulating measurements.
static Train * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
CompanySettings settings
settings specific for each company
Definition: company_base.h:127
Generates sequence of free UnitID numbers.
bool NeedsAutomaticServicing() const
Checks if the current order should be interrupted for a service-in-depot order.
Definition: vehicle.cpp:251
const Engine * GetEngine() const
Retrieves the engine of the vehicle.
Definition: vehicle.cpp:741
Vehicle * next_shared
pointer to the next vehicle that shares the order
Definition: vehicle_base.h:219
bool IsNormalAircraft() const
Check if the aircraft type is a normal flying device; eg not a rotor or a shadow. ...
Definition: aircraft.h:121
GoodsEntry goods[NUM_CARGO]
Goods at this station.
Definition: station_base.h:479
static const uint TILE_SIZE
Tile size in world coordinates.
Definition: tile_type.h:13
byte VehicleRandomBits()
Get a value for a vehicle&#39;s random_bits.
Definition: vehicle.cpp:361
Use default from engine class.
Definition: vehicle_base.h:83
Southwest.
FreeUnitIDGenerator(VehicleType type, CompanyID owner)
Initializes the structure.
Definition: vehicle.cpp:1686
static uint32 RandomRange(uint32 limit)
Pick a random number between 0 and limit - 1, inclusive.
Definition: random_func.hpp:81
VehicleSpriteSeq sprite_seq
Vehicle appearance.
Definition: vehicle_base.h:278
Maglev engine.
Definition: engine_type.h:38
static T SB(T &x, const uint8 s, const uint8 n, const U d)
Set n bits in x starting at bit s to d.
Vehicle * hash_viewport_next
NOSAVE: Next vehicle in the visual location hash.
Definition: vehicle_base.h:245
North.
OrderDepotActionFlags GetDepotActionType() const
What are we going to do when in the depot.
Definition: order_base.h:137
int8 x_bb_offs
x offset of vehicle bounding box
Definition: vehicle_base.h:282
DepotCommand
Flags to add to p1 for goto depot commands.
Definition: vehicle_type.h:65
uint32 GetGRFID() const
Retrieve the GRF ID of the NewGRF the engine is tied to.
Definition: engine.cpp:160
Money profit_last_year
Profit last year << 8, low 8 bits are fract.
Definition: vehicle_base.h:238
Mono rail engine.
Definition: engine_type.h:37
Order * next
Pointer to next order. If nullptr, end of list.
Definition: order_base.h:49
EngineID first_engine
Cached EngineID of the front vehicle. INVALID_ENGINE for the front vehicle itself.
Diesel model.
Definition: vehicle_base.h:99
Class to backup a specific variable and restore it later.
Definition: backup_type.hpp:21
Diesel rail engine.
Definition: engine_type.h:35
replace/renew a vehicle while it is in a depot
Definition: command_type.h:313
Value of offset corresponding to a position above the centre of the vehicle.
Definition: vehicle_base.h:79
bool no_servicing_if_no_breakdowns
don&#39;t send vehicles to depot when breakdowns are disabled
Functions related to (drawing on) viewports.
Pseudo random number generator.
Vehicle ** hash_tile_current
NOSAVE: Cache of the current hash chain.
Definition: vehicle_base.h:250
static const int32 INVALID_COORD
Sentinel for an invalid coordinate.
int8 y_bb_offs
y offset of vehicle bounding box
Definition: vehicle_base.h:283
Angle of 45 degrees right.
byte breakdown_ctr
Counter for managing breakdown events.
Definition: vehicle_base.h:261
Invalid cargo type.
Definition: cargo_type.h:68
Vehicle running normally.
Definition: newgrf_sound.h:22
The vehicle will stop at any station it passes and the destination.
Definition: order_type.h:73
byte subtype
subtype (Filled with values from AircraftSubType/DisasterSubType/EffectVehicleType/GroundVehicleSubty...
Definition: vehicle_base.h:325
void EndSpriteCombine()
Terminates a block of sprites started by StartSpriteCombine.
Definition: viewport.cpp:767
static bool IsInsideMM(const T x, const size_t min, const size_t max)
Checks if a value is in an interval.
Definition: math_func.hpp:264
static bool IsBridgeAbove(TileIndex t)
checks if a bridge is set above the ground of this tile
Definition: bridge_map.h:45
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:3334
Buses, trucks and trams belong to this class.
Definition: roadveh.h:107
Critical errors, the MessageBox is shown in all cases.
Definition: error.h:24
bool ShouldStopAtStation(const Vehicle *v, StationID station) const
Check whether the given vehicle should stop at the given station based on this order and the non-stop...
Definition: order_cmd.cpp:2229
uint16 cargo_cap
total capacity
Definition: vehicle_base.h:305
void VehicleLengthChanged(const Vehicle *u)
Logs a bug in GRF and shows a warning message if this is for the first time this happened.
Definition: vehicle.cpp:329
VehicleEnterTileProc * vehicle_enter_tile_proc
Called when a vehicle enters a tile.
Definition: tile_cmd.h:157
Shared order list linking together the linked list of orders and the list of vehicles sharing this or...
Definition: order_base.h:250
void SetDParamStr(uint n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition: strings.cpp:279
OrderDepotTypeFlags GetDepotOrderType() const
What caused us going to the depot?
Definition: order_base.h:135
Vehicle orders; Window numbers:
Definition: window_type.h:205
Map related accessors for depots.
static void SpawnAdvancedVisualEffect(const Vehicle *v)
Call CBID_VEHICLE_SPAWN_VISUAL_EFFECT and spawn requested effects.
Definition: vehicle.cpp:2454
Some methods of Pool are placed here in order to reduce compilation time and binary size...
Vehicle is crashed.
Definition: vehicle_base.h:37
static uint32 GetRegister(uint i)
Gets the value of a so-called newgrf "register".
void UpdateCache()
Update the caches of this ship.
Definition: ship_cmd.cpp:202
First bit used for the type of effect.
Definition: vehicle_base.h:81
uint32 grf_bugs
NOSAVE: bugs in this GRF in this run,.
TransparencyOption GetTransparencyOption() const
Determines the transparency option affecting the effect.
virtual bool IsPrimaryVehicle() const
Whether this is the primary vehicle in the chain.
Definition: vehicle_base.h:431
static bool IsTileType(TileIndex tile, TileType type)
Checks if a tile is a given tiletype.
Definition: tile_map.h:150
int16 y_offs
Number of pixels to shift the sprite downwards.
Definition: spritecache.h:20
static void DoDrawVehicle(const Vehicle *v)
Add vehicle sprite for drawing to the screen.
Definition: vehicle.cpp:1077
Functions related to errors.
UnitID unitnumber
unit number, for display purposes only
Definition: vehicle_base.h:289
int y
x and y position of the vehicle after moving
Definition: vehicle_func.h:76
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
Shorthand for calling the long DoCommand with a container.
Definition: command.cpp:441
void MakeImplicit(StationID destination)
Makes this order an implicit order.
Definition: order_cmd.cpp:153
byte subtype
Type of aircraft.
Definition: engine_type.h:101
void AgeVehicle(Vehicle *v)
Update age of a vehicle.
Definition: vehicle.cpp:1327
DateFract _date_fract
Fractional part of the day.
Definition: date.cpp:27
void DeleteVehicleNews(VehicleID vid, StringID news)
Delete a news item type about a vehicle.
Definition: news_gui.cpp:897
static size_t GetPoolSize()
Returns first unused index.
Definition: pool_type.hpp:312
Information about GRF, used in the game and (part of it) in savegames.
static bool IsRailStationTile(TileIndex t)
Is this tile a station tile and a rail station?
Definition: station_map.h:102
void ConsistChanged(ConsistChangeFlags allowed_changes)
Recalculates the cached stuff of a train.
Definition: train_cmd.cpp:106
bool IsRefit() const
Is this order a refit order.
Definition: order_base.h:108
UnitID max_roadveh
max trucks in game per company
Simple pair of data.
Internal structure used in openttd - Finite sTate mAchine –> FTA.
Definition: airport.h:190
The vehicle will not stop at any stations it passes including the destination.
Definition: order_type.h:76
bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
Checks whether a vehicle in on a specific location.
Definition: vehicle.cpp:452
bool NeedsServicing() const
Check if the vehicle needs to go to a depot in near future (if a opportunity presents itself) for ser...
Definition: vehicle.cpp:183
void MakeDummy()
Makes this order a Dummy order.
Definition: order_cmd.cpp:132
int8 y_offs
y offset for vehicle sprite
Definition: vehicle_base.h:285
GroundVehicleCache * GetGroundVehicleCache()
Access the ground vehicle cache of the vehicle.
Definition: vehicle.cpp:2824
EngineClass engclass
Class of engine for this vehicle.
Definition: engine_type.h:52
East.
void MarkAllViewportsDirty(int left, int top, int right, int bottom)
Mark all viewports that display an area as dirty (in need of repaint).
Definition: viewport.cpp:1905
void HideFillingPercent(TextEffectID *te_id)
Hide vehicle loading indicators.
Definition: misc_gui.cpp:651
Do not load anything.
Definition: order_type.h:66
Manually initiated order.
Definition: order_type.h:94
Don&#39;t load anymore during the next load cycle.
Definition: vehicle_base.h:48
uint32 VehicleID
The type all our vehicle IDs have.
Definition: vehicle_type.h:16
UnitID maxid
maximum ID at the moment of constructor call
StringID GetErrorMessage() const
Returns the error message of a command.
Definition: command_type.h:140
Time spend processing road vehicles.
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition: order_base.h:61
CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle *ignore)
Finds vehicle in tunnel / bridge.
Definition: vehicle.cpp:566
Southeast.
DoCommandFlag
List of flags for a command.
Definition: command_type.h:342
VisualEffectSpawnModel
Models for spawning visual effects.
Definition: vehicle_base.h:96
T * Next() const
Get next vehicle in the chain.
byte callback_mask
Bitmask of vehicle callbacks that have to be called.
Definition: engine_type.h:143
simple wagon, not motorized
Definition: engine_type.h:29
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:78
Rail vehicle is a multiple-unit (DMU/EMU)
Definition: engine_type.h:156
bool Succeeded() const
Did this command succeed?
Definition: command_type.h:150
void IncreaseStats(Station *st, CargoID cargo, StationID next_station_id, uint capacity, uint usage, EdgeUpdateMode mode)
Increase capacity for a link stat given by station cargo and next hop.
void PrepareUnload(Vehicle *front_v)
Prepare the vehicle to be unloaded.
Definition: economy.cpp:1236
Can helicopters land on this airport type?
Definition: airport.h:148
Definition of base types and functions in a cross-platform compatible way.
PaletteID GetEnginePalette(EngineID engine_type, CompanyID company)
Get the colour map for an engine.
Definition: vehicle.cpp:1972
static const uint VEHICLE_LENGTH
The length of a vehicle in tile units.
Definition: vehicle_type.h:76
bool IsArticulatedPart() const
Check if the vehicle is an articulated part of an engine.
Definition: vehicle_base.h:890
A number of safeguards to prevent using unsafe methods.
Trigger platform when train leaves.
byte x_extent
x-extent of vehicle bounding box
Definition: vehicle_base.h:279
static void Run(Vehicle *v, bool allow_merge=true, bool is_full_loading=false)
Refresh all links the given vehicle will visit.
Definition: refresh.cpp:26
Direction
Defines the 8 directions on the map.
void VehicleEnteredDepotThisTick(Vehicle *v)
Adds a vehicle to the list of vehicles that visited a depot this tick.
Definition: vehicle.cpp:892
Vehicle uses two company colours.
Definition: engine_type.h:155
bool HasAnyRailtypesAvail(const CompanyID company)
Test if any buildable railtype is available for a company.
Definition: rail.cpp:196
void DeleteDepotHighlightOfVehicle(const Vehicle *v)
Removes the highlight of a vehicle in a depot window.
Definition: depot_gui.cpp:1116
void DeleteOrder(Vehicle *v, VehicleOrderID sel_ord)
Delete an order but skip the parameter validation.
Definition: order_cmd.cpp:1043
Vehicle refit; Window numbers:
Definition: window_type.h:199
DirDiff
Enumeration for the difference between two directions.
static uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
Definition: math_func.hpp:314
Electric sparks.
Definition: vehicle_base.h:86
Station * GetTargetAirportIfValid(const Aircraft *v)
Returns aircraft&#39;s target station if v->target_airport is a valid station with airport.
struct AirportFTA * layout
state machine for airport
Definition: airport.h:177
byte z_extent
z-extent of vehicle bounding box
Definition: vehicle_base.h:281
byte visual_effect
Bitstuffed NewGRF visual effect data.
Definition: engine_type.h:73
VehicleType type
Vehicle type, ie VEH_ROAD, VEH_TRAIN, etc.
Definition: engine_base.h:40
Valid changes for arranging the consist in a depot.
Definition: train.h:52
Every 16 ticks while the vehicle is running (speed > 0).
Definition: newgrf_sound.h:25
CargoID cargo_type
type of cargo this vehicle is carrying
Definition: vehicle_base.h:303
uint32 engine_renew_money
minimum amount of money before autorenew is used
uint ActionCount(MoveToAction action) const
Returns the amount of cargo designated for a given purpose.
Definition: cargopacket.h:341
CompanyMask company_avail
Bit for each company whether the engine is available for that company.
Definition: engine_base.h:37
void AddToShared(Vehicle *shared_chain)
Adds this vehicle to a shared vehicle chain.
Definition: vehicle.cpp:2688
Change colour mapping of vehicle.
Information about a particular livery.
Definition: livery.h:78
Vehicle view; Window numbers:
Definition: window_type.h:332
TrackBits
Bitfield corresponding to Track.
Definition: track_type.h:38
static const byte LIT_ALL
Show the liveries of all companies.
Definition: livery.h:17
GroupStatistics group_all[VEH_COMPANY_END]
NOSAVE: Statistics for the ALL_GROUP group.
Definition: company_base.h:128
Functions related to order backups.
Smoke of broken vehicles except aircraft.
bool IsFrontEngine() const
Check if the vehicle is a front engine.
Definition: vehicle_base.h:881
GRFBugs
Encountered GRF bugs.
Definition: newgrf_config.h:42
byte misc_flags
Miscellaneous flags.
Definition: engine_type.h:142
Map accessor functions for bridges.
void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition: vehicle.cpp:496
TileIndex tile
Current tile index.
Definition: vehicle_base.h:228
Road vehicle list; Window numbers:
Definition: window_type.h:307
South.
Disaster vehicle type.
Definition: vehicle_type.h:32
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
static EngineID EngineReplacementForCompany(const Company *c, EngineID engine, GroupID group, bool *replace_when_old=nullptr)
Retrieve the engine replacement for the given company and original engine type.
static void CountVehicle(const Vehicle *v, int delta)
Update num_vehicle when adding or removing a vehicle.
Definition: group_cmd.cpp:133
static Vehicle * VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc, bool find_first)
Helper function for FindVehicleOnPos/HasVehicleOnPos.
Definition: vehicle.cpp:467
Money money
Money owned by the company.
Definition: company_base.h:65
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
Definition: viewport.cpp:1938
Vehicle timetable; Window numbers:
Definition: window_type.h:217
Every 16 ticks while the vehicle is stopped (speed == 0).
Definition: newgrf_sound.h:26
bool CanVehicleUseStation(EngineID engine_type, const Station *st)
Can this station be used by the given engine type?
Definition: vehicle.cpp:2779
A game normally paused.
Definition: openttd.h:57
Steam model.
Definition: vehicle_base.h:98
static const GroupID INVALID_GROUP
Sentinel for invalid groups.
Definition: group_type.h:18
Station view; Window numbers:
Definition: window_type.h:338
OrderLoadFlags GetLoadType() const
How must the consist be loaded?
Definition: order_base.h:127
Base class for all effect vehicles.
Basic functions/variables used all over the place.
static DirDiff DirDifference(Direction d0, Direction d1)
Calculate the difference between two directions.
Service the vehicle and then halt it.
Definition: order_type.h:104
bool IsRearDualheaded() const
Tell if we are dealing with the rear end of a multiheaded engine.
uint16 num_vehicle
Number of vehicles.
Definition: group.h:25
static Direction ChangeDir(Direction d, DirDiff delta)
Change a direction by a given difference.
int8 x_offs
x offset for vehicle sprite
Definition: vehicle_base.h:284
Owner owner
Which company owns the vehicle?
Definition: vehicle_base.h:271
Sprite sequence for a vehicle part.
Definition: vehicle_base.h:128
uint64 flags
stores which blocks on the airport are taken. was 16 bit earlier on, then 32
Definition: station_base.h:308
Called to determine if a specific colour map should be used for a vehicle instead of the default live...
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:40
static bool IsCargoInClass(CargoID c, CargoClass cc)
Does cargo c have cargo class cc?
Definition: cargotype.h:148
byte previous_pos
Previous desired position of the aircraft.
Definition: aircraft.h:77
uint16 refit_cap
Capacity left over from before last refit.
Definition: vehicle_base.h:306
Functions related to sound.
byte breakdowns_since_last_service
Counter for the amount of breakdowns.
Definition: vehicle_base.h:263
uint16 reliability
Reliability.
Definition: vehicle_base.h:259
Functions to cache sprites in memory.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
Vehicle * First() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:592
Vehicle&#39;s pathfinder is lost.
Definition: vehicle_base.h:49
bool Failed() const
Did this command fail?
Definition: command_type.h:159
byte tick_counter
Increased by one for each tick.
Definition: vehicle_base.h:312
EffectVehicle * CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicleType type)
Create an effect vehicle above a particular vehicle.
byte colour2
Second colour, for vehicles with 2CC support.
Definition: livery.h:81
UnitID curid
last ID returned; 0 if none
All ships have this type.
Definition: ship.h:26
void InvalidateAutoreplaceWindow(EngineID e, GroupID id_g)
Rebuild the left autoreplace list if an engine is removed or added.
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w, int h, int dz, int z, bool transparent, int bb_offset_x, int bb_offset_y, int bb_offset_z, const SubSprite *sub)
Draw a (transparent) sprite at given coordinates with a given bounding box.
Definition: viewport.cpp:659
bool PlayVehicleSound(const Vehicle *v, VehicleSoundEvent event)
Checks whether a NewGRF wants to play a different vehicle sound effect.
bool HasAnyRoadTypesAvail(CompanyID company, RoadTramType rtt)
Test if any buildable RoadType is available for a company.
Definition: road.cpp:132
#define return_cmd_error(errcode)
Returns from a function with a specific StringID as error.
Definition: command_func.h:33
bool CanBuildVehicleInfrastructure(VehicleType type, byte subtype)
Check whether we can build infrastructure for the given vehicle type.
Definition: vehicle.cpp:1754
byte state
State of the airport.
Definition: aircraft.h:79
int16 engine_renew_months
months before/after the maximum vehicle age a vehicle should be renewed
Base class for all pools.
Definition: pool_type.hpp:82
bool engine_renew
is autorenew enabled
uint16 height
Height of the sprite.
Definition: spritecache.h:17
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition: ai_core.cpp:234
The most basic (normal) sprite.
Definition: gfx_type.h:297
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:35
&#39;Train&#39; is either a loco or a wagon.
Definition: train.h:85
static bool Chance16(const uint a, const uint b)
Flips a coin with given probability.
TileIndex old_tile
Current tile of the vehicle.
Definition: vehicle_func.h:77
bool IsEngineCountable() const
Check if a vehicle is counted in num_engines in each company struct.
Definition: vehicle.cpp:708
byte breakdown_chance
Current chance of breakdowns.
Definition: vehicle_base.h:264
The vehicle is in a drive-through road stop.
Definition: roadveh.h:52
Diesel fumes.
Definition: vehicle_base.h:85
Livery livery
Custom colour scheme for vehicles in this group.
Definition: group.h:71
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don&#39;t get linker errors.
Definition: pool_func.hpp:224
int left
Screen coordinate left edge of the viewport.
Definition: viewport_type.h:23
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Definition: window.cpp:1162
Bitflag for a depot.
Definition: track_type.h:56
VehicleEnterTileStatus VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y)
Call the tile callback function for a vehicle entering a tile.
Definition: vehicle.cpp:1674
static void UpdateProfits()
Recompute the profits for all groups.
Definition: group_cmd.cpp:180
void RemoveFromShared()
Removes the vehicle from the shared order list.
Definition: vehicle.cpp:2711
Effect vehicle type (smoke, explosions, sparks, bubbles)
Definition: vehicle_type.h:31
void AddVehicle(Vehicle *v)
Adds the given vehicle to this shared order list.
Definition: order_base.h:352
execute the given command
Definition: command_type.h:344
Station with an airport.
Definition: station_type.h:55
UnitID max_ships
max ships in game per company
Flag to disable visual effect.
Definition: vehicle_base.h:88
static const EngineID INVALID_ENGINE
Constant denoting an invalid engine.
Definition: engine_type.h:174
bool vehicle_income_warn
if a vehicle isn&#39;t generating income, show a warning
Definition: settings_type.h:86
Steam plumes.
Definition: vehicle_base.h:84
static const GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition: group_type.h:17
The vehicle will leave the depot right after arrival (service only)
Definition: vehicle_type.h:66
uint16 width
Width of the sprite.
Definition: spritecache.h:18
Functions related to companies.
Called for every vehicle every 32 days (not all on same date though).
RailType GetTileRailType(TileIndex tile)
Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile.
Definition: rail.cpp:155
GetNewVehiclePosResult GetNewVehiclePos(const Vehicle *v)
Get position information of a vehicle when moving one pixel in the direction it is facing...
Definition: vehicle.cpp:1620
void UpdatePosition()
Update the position of the vehicle.
Definition: vehicle.cpp:1559
Station with a dock.
Definition: station_type.h:56
static StationID GetStationIndex(TileIndex t)
Get StationID from a tile.
Definition: station_map.h:28
static TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition: map_func.h:194
GRFConfig * GetGRFConfig(uint32 grfid, uint32 mask)
Retrieve a NewGRF from the current config by its grfid.
static const PaletteID PALETTE_RECOLOUR_START
First recolour sprite for company colours.
Definition: sprites.h:1556
Functions related to articulated vehicles.
void ErrorUnknownCallbackResult(uint32 grfid, uint16 cbid, uint16 cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
TrackBits state
The "track" the ship is following.
Definition: ship.h:27
Header file for NewGRF stations.
static T ClrBit(T &x, const uint8 y)
Clears a bit in a variable.
bool IsGroundVehicle() const
Check if the vehicle is a ground vehicle.
Definition: vehicle_base.h:469
GUISettings gui
settings related to the GUI
const GRFFile * GetGRF() const
Retrieve the NewGRF the engine is tied to.
Definition: engine_base.h:138
DestinationID GetDestination() const
Gets the destination of this order.
Definition: order_base.h:94
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:340
bool NeedsAutorenewing(const Company *c, bool use_renew_setting=true) const
Function to tell if a vehicle needs to be autorenewed.
Definition: vehicle.cpp:140
void VehicleServiceInDepot(Vehicle *v)
Service a vehicle and all subsequent vehicles in the consist.
Definition: vehicle.cpp:162
GroupID parent
Parent group.
Definition: group.h:76
void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, byte widget_index)
Mark a particular widget in a particular window as dirty (in need of repainting)
Definition: window.cpp:3229
CargoList that is used for vehicles.
Definition: cargopacket.h:268
Time spent processing ships.
Smoke of steam engines.
bool HandleBreakdown()
Handle all of the aspects of a vehicle breakdown This includes adding smoke and sounds, and ending the breakdown when appropriate.
Definition: vehicle.cpp:1261
static void ClearVehicle(const Vehicle *v)
Clear/update the (clone) vehicle from an order backup.
Data structure for viewport, display of a part of the world.
Definition: viewport_type.h:22
static const int MAX_VEHICLE_PIXEL_X
Maximum width of a vehicle in pixels in #ZOOM_LVL_BASE.
Definition: tile_type.h:19
Used for vehicle var 0xFE bit 8 (toggled each time the train is reversed, accurate for first vehicle ...
Definition: train.h:31
uint16 EngineID
Unique identification number of an engine.
Definition: engine_type.h:21
void UpdateVehicleTimetable(Vehicle *v, bool travelling)
Update the timetable for the vehicle.
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Definition: cargotype.h:117
Number of bits used for the effect type.
Definition: vehicle_base.h:82
static Vehicle * EnsureNoVehicleProcZ(Vehicle *v, void *data)
Callback that returns &#39;real&#39; vehicles lower or at height *(int*)data .
Definition: vehicle.cpp:522
Ships list; Window numbers:
Definition: window_type.h:313
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:78
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition: sprites.h:1587
static Vehicle * GetVehicleTunnelBridgeProc(Vehicle *v, void *data)
Procedure called for every vehicle found in tunnel/bridge in the hash map.
Definition: vehicle.cpp:551
uint32 Pack() const
Pack a VehicleListIdentifier in a single uint32.
Definition: vehiclelist.cpp:21
void DeleteGroupHighlightOfVehicle(const Vehicle *v)
Removes the highlight of a vehicle in a group window.
Definition: group_gui.cpp:1125
Functions related to depots.
void BeginLoading()
Prepare everything to begin the loading when arriving at a station.
Definition: vehicle.cpp:2033
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition: vehicle_base.h:579
Date date_of_last_service
Last date the vehicle had a service at a depot.
Definition: vehicle_base.h:258
bool include(std::vector< T > &vec, const T &item)
Helper function to append an item to a vector if it is not already contained Consider using std::set...
void InsertOrder(Vehicle *v, Order *new_o, VehicleOrderID sel_ord)
Insert a new order but skip the validation.
Definition: order_cmd.cpp:915
void ShowNewGrfVehicleError(EngineID engine, StringID part1, StringID part2, GRFBugs bug_type, bool critical)
Displays a "NewGrf Bug" error message for a engine, and pauses the game if not networking.
Definition: vehicle.cpp:296
Position information of a vehicle after it moved.
Definition: vehicle_func.h:75
OrderSettings order
settings related to orders
void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8 num_vehicles)
Calculates the set of vehicles that will be affected by a given selection.
Definition: vehicle.cpp:2887
void FindVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition: vehicle.cpp:436
static const int MAX_VEHICLE_PIXEL_Y
Maximum height of a vehicle in pixels in #ZOOM_LVL_BASE.
Definition: tile_type.h:20
Send the vehicle to the nearest depot.
Definition: order_type.h:105
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:215
static Vehicle * VehicleFromPosXY(int x, int y, void *data, VehicleFromPosProc *proc, bool find_first)
Helper function for FindVehicleOnPos/HasVehicleOnPos.
Definition: vehicle.cpp:409
uint64 block
64 bit blocks (st->airport.flags), should be enough for the most complex airports ...
Definition: airport.h:192
Powered wagon changed poweredness state when not inside a depot.
Definition: newgrf_config.h:45
UnitID NextID()
Returns next free UnitID.
Definition: vehicle.cpp:1711
SigSegState UpdateSignalsOnSegment(TileIndex tile, DiagDirection side, Owner owner)
Update signals, starting at one side of a tile Will check tile next to this at opposite side too...
Definition: signal.cpp:638
static T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition: math_func.hpp:81
turn a train around
Definition: command_type.h:222
TileIndex xy
Base tile of the station.
void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type, CargoTypes *union_mask, CargoTypes *intersection_mask)
Merges the refit_masks of all articulated parts.
static void UpdateAutoreplace(CompanyID company)
Update autoreplace_defined and autoreplace_finished of all statistics of a company.
Definition: group_cmd.cpp:204
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
bool GamelogGRFBugReverse(uint32 grfid, uint16 internal_id)
Logs GRF bug - rail vehicle has different length after reversing.
Definition: gamelog.cpp:564
Trains list; Window numbers:
Definition: window_type.h:301
Functions related to zooming.
Full load all cargoes of the consist.
Definition: order_type.h:64
void AgeCargo()
Ages the all cargo in this list.
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:52
Vehicle * next
pointer to the next vehicle in the chain
Definition: vehicle_base.h:215
void SubtractMoneyFromCompany(CommandCost cost)
Subtract money from the _current_company, if the company is valid.
void DeleteUnreachedImplicitOrders()
Delete all implicit orders which were not reached.
Definition: vehicle.cpp:1994
void ReleaseDisastersTargetingVehicle(VehicleID vehicle)
Notify disasters that we are about to delete a vehicle.
A tile of a station.
Definition: tile_type.h:46
const TileTypeProcs *const _tile_type_procs[16]
Tile callback functions for each type of tile.
Definition: landscape.cpp:60
Invalid transparency option.
Definition: transparency.h:33
Vehicle * previous_shared
NOSAVE: pointer to the previous vehicle in the shared order chain.
Definition: vehicle_base.h:220
Reverse the visible direction of the vehicle.
Definition: train.h:28
bool show_track_reservation
highlight reserved tracks.
Northwest.
uint16 _returned_mail_refit_capacity
Stores the mail capacity after a refit operation (Aircraft only).
Definition: vehicle.cpp:86
#define MAX_DAY
The number of days till the last day.
Definition: date_type.h:95
int16 x_offs
Number of pixels to shift the sprite to the right.
Definition: spritecache.h:19
Group data.
Definition: group.h:65
Totally no unloading will be done.
Definition: order_type.h:56
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function() ...
Definition: pool_type.hpp:261
Vehicle * CheckClickOnVehicle(const ViewPort *vp, int x, int y)
Find the vehicle close to the clicked coordinates.
Definition: vehicle.cpp:1165
virtual void OnNewDay()
Calls the new day handler of the vehicle.
Definition: vehicle_base.h:531
bool HasEngineType() const
Check whether Vehicle::engine_type has any meaning.
Definition: vehicle.cpp:725
Vehicle breaking down.
Definition: newgrf_sound.h:21
Default value to indicate that visual effect should be based on engine class.
Definition: vehicle_base.h:92
Aircraft list; Window numbers:
Definition: window_type.h:319
uint16 & GetGroundVehicleFlags()
Access the ground vehicle flags of the vehicle.
Definition: vehicle.cpp:2854
int32 z_pos
z coordinate.
Definition: vehicle_base.h:268
Vehicle is not visible.
Definition: vehicle_base.h:30
Vehicle details; Window numbers:
Definition: window_type.h:193
Functions/definitions that have something to do with groups.
Functions related to commands.
static bool IsValidID(size_t index)
Tests whether given index is a valid index for station of this type.
byte 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
Coordinates of a point in 2D.
Vehicle * previous
NOSAVE: pointer to the previous vehicle in the chain.
Definition: vehicle_base.h:216
uint8 CalcPercentVehicleFilled(const Vehicle *front, StringID *colour)
Calculates how full a vehicle is.
Definition: vehicle.cpp:1377
Northeast.
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:45
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:280
uint16 local_id
id defined by the grf file for this entity
static void CountEngine(const Vehicle *v, int delta)
Update num_engines when adding/removing an engine.
Definition: group_cmd.cpp:156
uint32 GetGRFID() const
Retrieve the GRF ID of the NewGRF the vehicle is tied to.
Definition: vehicle.cpp:761
uint16 UnitID
Type for the company global vehicle unit number.
Base classes related to the economy.
SmallMap< Vehicle *, bool > AutoreplaceMap
List of vehicles that should check for autoreplace this tick.
Definition: vehicle.cpp:687
Base for ships.
static WindowClass GetWindowClassForVehicleType(VehicleType vt)
Get WindowClass for vehicle list of given vehicle type.
Definition: vehicle_gui.h:91
void GetConsistFreeCapacities(SmallMap< CargoID, uint > &capacities) const
Get a map of cargoes and free capacities in the consist.
Definition: vehicle.cpp:2277
void KeepAll()
Marks all cargo in the vehicle as to be kept.
Definition: cargopacket.h:407
UnitID max_trains
max trains in game per company
Station with bus stops.
Definition: station_type.h:54
Declaration of link graph classes used for cargo distribution.
bool * cache
array of occupied unit id numbers
EffectVehicleType
Effect vehicle types.
Steam rail engine.
Definition: engine_type.h:34
Order * GetOrder(int index) const
Returns order &#39;index&#39; of a vehicle or nullptr when it doesn&#39;t exists.
Definition: vehicle_base.h:858
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:17
CommandCost SendToDepot(DoCommandFlag flags, DepotCommand command)
Send this vehicle to the depot using the given command(s).
Definition: vehicle.cpp:2305
uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v)
Evaluate a newgrf callback for vehicles.
const char * GetName() const
Get the name of this grf.
Aircraft vehicle type.
Definition: vehicle_type.h:27
uint8 cached_veh_length
Length of this vehicle in units of 1/VEHICLE_LENGTH of normal length. It is cached because this can b...
static bool IsTunnelTile(TileIndex t)
Is this a tunnel (entrance)?
Definition: tunnel_map.h:33
Airport airport
Tile area the airport covers.
Definition: station_base.h:464
static bool EngineHasReplacementForCompany(const Company *c, EngineID engine, GroupID group)
Check if a company has a replacement set up for the given engine.
byte y_extent
y-extent of vehicle bounding box
Definition: vehicle_base.h:280
Flag to disable wagon power.
Definition: vehicle_base.h:90
EngineID engine_type
The type of engine used for this vehicle.
Definition: vehicle_base.h:286
byte liveries
options for displaying company liveries, 0=none, 1=self, 2=all
Definition: settings_type.h:99
const struct GRFFile * grffile
grf file that introduced this entity
ZoomLevel zoom
The zoom level of the viewport.
Definition: viewport_type.h:33
byte cached_vis_effect
Visual effect to show (see VisualEffect)
Definition: vehicle_base.h:124
Passengers.
Definition: cargotype.h:39
bool disable_unsuitable_building
disable infrastructure building when no suitable vehicles are available
int32 x_pos
x coordinate.
Definition: vehicle_base.h:266
virtual bool Tick()
Calls the tick handler of the vehicle.
Definition: vehicle_base.h:526
uint16 vehicle_flags
Used for gradual loading and other miscellaneous things (.
Definition: base_consist.h:30
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
Functions related to NewGRF provided sounds.
void Restore()
Restore the variable.
Base functions for all AIs.
Map accessors for tunnels.
const GRFFile * GetGRF() const
Retrieve the NewGRF the vehicle is tied to.
Definition: vehicle.cpp:751
byte colour1
First colour, for all vehicles.
Definition: livery.h:80
Station with truck stops.
Definition: station_type.h:53
int virtual_top
Virtual top coordinate.
Definition: viewport_type.h:29
GameCreationSettings game_creation
settings used during the creation of a game (map)
Smoke of broken aircraft.
static void VehicleReachedProfitAge(const Vehicle *v)
Add a vehicle to the profit sum of its group.
Definition: group_cmd.cpp:166
Specification of a rectangle with absolute coordinates of all edges.
byte CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:20
int32 y_pos
y coordinate.
Definition: vehicle_base.h:267
static bool IsInvisibilitySet(TransparencyOption to)
Check if the invisibility option bit is set and if we aren&#39;t in the game menu (there&#39;s never transpar...
Definition: transparency.h:59
Road vehicle is a tram/light rail vehicle.
Definition: engine_type.h:154
New vehicles.
Definition: economy_type.h:150
Length of rail vehicle changes when not inside a depot.
Definition: newgrf_config.h:43
Flag for advanced effects.
Definition: vehicle_base.h:89
static bool IsDepotTile(TileIndex tile)
Is the given tile a tile with a depot on it?
Definition: depot_map.h:41
int top
Screen coordinate top edge of the viewport.
Definition: viewport_type.h:24
Station with train station.
Definition: station_type.h:52
void ShowCostOrIncomeAnimation(int x, int y, int z, Money cost)
Display animated income or costs on the map.
Definition: misc_gui.cpp:576
Vehicle(VehicleType type=VEH_INVALID)
Vehicle constructor.
Definition: vehicle.cpp:344
VehicleEnterTileStatus
The returned bits of VehicleEnterTile.
Definition: tile_cmd.h:20
One direction is the opposite of the other one.
SpriteID sprite
The &#39;real&#39; sprite.
Definition: gfx_type.h:23
static const VehicleOrderID MAX_VEH_ORDER_ID
Last valid VehicleOrderID.
Definition: order_type.h:23
Money profit_this_year
Profit this year << 8, low 8 bits are fract.
Definition: vehicle_base.h:237
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3243
This depot order is because of a regular order.
Definition: order_type.h:96
Functions related to news.
uint16 animation_state
State primarily used to change the graphics/behaviour.
Base classes/functions for stations.
VehicleCache vcache
Cache of often used vehicle values.
Definition: vehicle_base.h:328
static Station * Get(size_t index)
Gets station with given index.
Date _date
Current date in days (day counter)
Definition: date.cpp:26
Number of bits used for the offset.
Definition: vehicle_base.h:78
static Direction ReverseDir(Direction d)
Return the reverse of a direction.
Functions related to autoreplacing.
Company view; Window numbers:
Definition: window_type.h:362
Rect coord
NOSAVE: Graphical bounding box of the vehicle, i.e. what to redraw on moves.
Definition: vehicle_base.h:243
TileIndex new_tile
Tile of the vehicle after moving.
Definition: vehicle_func.h:78
Vehicle * first
NOSAVE: pointer to the first vehicle in the chain.
Definition: vehicle_base.h:217
Date age
Age in days.
Definition: vehicle_base.h:256
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:44
static bool IsCompanyBuildableVehicleType(VehicleType type)
Is the given vehicle type buildable by a company?
Definition: vehicle_func.h:89
void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index)
Delete inspect window for a given feature and index.
This depot order is because of the servicing limit.
Definition: order_type.h:95
VehicleOrderID cur_real_order_index
The index to the current real (non-implicit) order.
Definition: base_consist.h:27
void HandleLoading(bool mode=false)
Handle the loading of the vehicle; when not it skips through dummy orders and does nothing in all oth...
Definition: vehicle.cpp:2242
Class for backupping variables and making sure they are restored later.
static const uint IMPLICIT_ORDER_ONLY_CAP
Maximum number of orders in implicit-only lists before we start searching harder for duplicates...
Definition: order_type.h:32
Station data structure.
Definition: station_base.h:450
Functions related to effect vehicles.
static bool IsTransparencySet(TransparencyOption to)
Check if the transparency option bit is set and if we aren&#39;t in the game menu (there&#39;s never transpar...
Definition: transparency.h:48
Time spent processing trains.
uint32 cached_weight
Total weight of the consist (valid only for the first engine).
Disable insertion and removal of automatic orders until the vehicle completes the real order...
Road vehicle type.
Definition: vehicle_type.h:25
A game paused because a (critical) error.
Definition: openttd.h:60
Train is slowing down.
Definition: vehicle_base.h:34
byte day_counter
Increased by one for each day.
Definition: vehicle_base.h:311
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition: gfx.cpp:835
static bool TracksOverlap(TrackBits bits)
Checks if the given tracks overlap, ie form a crossing.
Definition: track_func.h:653
Order current_order
The current order (+ status, like: loading)
Definition: vehicle_base.h:316
void UpdatePositionAndViewport()
Update the position of the vehicle, and update the viewport.
Definition: vehicle.cpp:1601
static RoadStop * GetByTile(TileIndex tile, RoadStopType type)
Find a roadstop at given tile.
Definition: roadstop.cpp:266
shadow of the aircraft
Definition: aircraft.h:33
void UpdateVisualEffect(bool allow_power_change=true)
Update the cached visual effect.
Definition: vehicle.cpp:2386
GroupID group_id
Index of group Pool array.
Definition: vehicle_base.h:324
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:3316
static const int DAYS_IN_LEAP_YEAR
sometimes, you need one day more...
Definition: date_type.h:30
bool IsEngine() const
Check if a vehicle is an engine (can be first in a consist).
TransparencyOption
Transparency option bits: which position in _transparency_opt stands for which transparency.
Definition: transparency.h:22
GroundVehicleCache gcache
Cache of often calculated values.
Visual effects and wagon power (trains, road vehicles and ships)
CargoID GetRefitCargo() const
Get the cargo to to refit to.
Definition: order_base.h:122
Vehicle is not clickable by the user (shadow vehicles).
Definition: vehicle_base.h:32
SpriteID colourmap
NOSAVE: cached colour mapping.
Definition: vehicle_base.h:252
byte visual_effect
Bitstuffed NewGRF visual effect data.
Definition: engine_type.h:57
Electric rail engine.
Definition: engine_type.h:36
static int GetTileMaxPixelZ(TileIndex tile)
Get top height of the tile.
Definition: tile_map.h:304
Dynamic data of a loaded NewGRF.
Definition: newgrf.h:105
Vehicle visual effect (steam, diesel smoke or electric spark) is shown.
Definition: newgrf_sound.h:24
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:199
void CancelReservation(StationID next, Station *st)
Return all reserved cargo packets to the station and reset all packets staged for transfer...
Definition: vehicle.cpp:2163
static void SetDepotReservation(TileIndex t, bool b)
Set the reservation state of the depot.
Definition: rail_map.h:270
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition: gfx_type.h:24
int width
Screen width of the viewport.
Definition: viewport_type.h:25
static Station * GetIfValid(size_t index)
Returns station if the index is a valid index for this station type.
static Pool::IterateWrapper< Engine > IterateType(VehicleType vt, size_t from=0)
Returns an iterable ensemble of all valid engines of the given type.
Definition: engine_base.h:151
pause the game
Definition: command_type.h:254