OpenTTD Source  20241120-master-g6d3adc6169
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 "vehicle_func.h"
29 #include "autoreplace_func.h"
30 #include "autoreplace_gui.h"
31 #include "station_base.h"
32 #include "ai/ai.hpp"
33 #include "depot_func.h"
34 #include "network/network.h"
35 #include "core/pool_func.hpp"
36 #include "economy_base.h"
37 #include "articulated_vehicles.h"
38 #include "roadstop_base.h"
39 #include "core/random_func.hpp"
40 #include "core/backup_type.hpp"
41 #include "core/container_func.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 #include "autoreplace_cmd.h"
55 #include "misc_cmd.h"
56 #include "train_cmd.h"
57 #include "vehicle_cmd.h"
58 #include "newgrf_roadstop.h"
59 #include "timer/timer.h"
62 #include "timer/timer_game_tick.h"
63 
64 #include "table/strings.h"
65 
66 #include "safeguards.h"
67 
68 /* Number of bits in the hash to use from each vehicle coord */
69 static const uint GEN_HASHX_BITS = 6;
70 static const uint GEN_HASHY_BITS = 6;
71 
72 /* Size of each hash bucket */
73 static const uint GEN_HASHX_BUCKET_BITS = 7;
74 static const uint GEN_HASHY_BUCKET_BITS = 6;
75 
76 /* Compute hash for vehicle coord */
77 #define GEN_HASHX(x) GB((x), GEN_HASHX_BUCKET_BITS + ZOOM_BASE_SHIFT, GEN_HASHX_BITS)
78 #define GEN_HASHY(y) (GB((y), GEN_HASHY_BUCKET_BITS + ZOOM_BASE_SHIFT, GEN_HASHY_BITS) << GEN_HASHX_BITS)
79 #define GEN_HASH(x, y) (GEN_HASHY(y) + GEN_HASHX(x))
80 
81 /* Maximum size until hash repeats */
82 static const int GEN_HASHX_SIZE = 1 << (GEN_HASHX_BUCKET_BITS + GEN_HASHX_BITS + ZOOM_BASE_SHIFT);
83 static const int GEN_HASHY_SIZE = 1 << (GEN_HASHY_BUCKET_BITS + GEN_HASHY_BITS + ZOOM_BASE_SHIFT);
84 
85 /* Increments to reach next bucket in hash table */
86 static const int GEN_HASHX_INC = 1;
87 static const int GEN_HASHY_INC = 1 << GEN_HASHX_BITS;
88 
89 /* Mask to wrap-around buckets */
90 static const uint GEN_HASHX_MASK = (1 << GEN_HASHX_BITS) - 1;
91 static const uint GEN_HASHY_MASK = ((1 << GEN_HASHY_BITS) - 1) << GEN_HASHX_BITS;
92 
93 
97 
98 
99 
103 void VehicleSpriteSeq::GetBounds(Rect *bounds) const
104 {
105  bounds->left = bounds->top = bounds->right = bounds->bottom = 0;
106  for (uint i = 0; i < this->count; ++i) {
107  const Sprite *spr = GetSprite(this->seq[i].sprite, SpriteType::Normal);
108  if (i == 0) {
109  bounds->left = spr->x_offs;
110  bounds->top = spr->y_offs;
111  bounds->right = spr->width + spr->x_offs - 1;
112  bounds->bottom = spr->height + spr->y_offs - 1;
113  } else {
114  if (spr->x_offs < bounds->left) bounds->left = spr->x_offs;
115  if (spr->y_offs < bounds->top) bounds->top = spr->y_offs;
116  int right = spr->width + spr->x_offs - 1;
117  int bottom = spr->height + spr->y_offs - 1;
118  if (right > bounds->right) bounds->right = right;
119  if (bottom > bounds->bottom) bounds->bottom = bottom;
120  }
121  }
122 }
123 
131 void VehicleSpriteSeq::Draw(int x, int y, PaletteID default_pal, bool force_pal) const
132 {
133  for (uint i = 0; i < this->count; ++i) {
134  PaletteID pal = force_pal || !this->seq[i].pal ? default_pal : this->seq[i].pal;
135  DrawSprite(this->seq[i].sprite, pal, x, y);
136  }
137 }
138 
145 bool Vehicle::NeedsAutorenewing(const Company *c, bool use_renew_setting) const
146 {
147  /* We can always generate the Company pointer when we have the vehicle.
148  * However this takes time and since the Company pointer is often present
149  * when this function is called then it's faster to pass the pointer as an
150  * argument rather than finding it again. */
151  assert(c == Company::Get(this->owner));
152 
153  if (use_renew_setting && !c->settings.engine_renew) return false;
154  if (this->age - this->max_age < (c->settings.engine_renew_months * 30)) return false;
155 
156  /* Only engines need renewing */
157  if (this->type == VEH_TRAIN && !Train::From(this)->IsEngine()) return false;
158 
159  return true;
160 }
161 
168 {
169  assert(v != nullptr);
170  SetWindowDirty(WC_VEHICLE_DETAILS, v->index); // ensure that last service date and reliability are updated
171 
172  do {
176  v->reliability = v->GetEngine()->reliability;
177  /* Prevent vehicles from breaking down directly after exiting the depot. */
178  v->breakdown_chance /= 4;
179  if (_settings_game.difficulty.vehicle_breakdowns == 1) v->breakdown_chance = 0; // on reduced breakdown
180  v = v->Next();
181  } while (v != nullptr && v->HasEngineType());
182 }
183 
191 {
192  /* Stopped or crashed vehicles will not move, as such making unmovable
193  * vehicles to go for service is lame. */
194  if (this->vehstatus & (VS_STOPPED | VS_CRASHED)) return false;
195 
196  /* Are we ready for the next service cycle? */
197  const Company *c = Company::Get(this->owner);
198 
199  /* Service intervals can be measured in different units, which we handle individually. */
200  if (this->ServiceIntervalIsPercent()) {
201  /* Service interval is in percents. */
202  if (this->reliability >= this->GetEngine()->reliability * (100 - this->GetServiceInterval()) / 100) return false;
204  /* Service interval is in minutes. */
205  if (this->date_of_last_service + (this->GetServiceInterval() * EconomyTime::DAYS_IN_ECONOMY_MONTH) >= TimerGameEconomy::date) return false;
206  } else {
207  /* Service interval is in days. */
208  if (this->date_of_last_service + this->GetServiceInterval() >= TimerGameEconomy::date) return false;
209  }
210 
211  /* If we're servicing anyway, because we have not disabled servicing when
212  * there are no breakdowns or we are playing with breakdowns, bail out. */
215  return true;
216  }
217 
218  /* Test whether there is some pending autoreplace.
219  * Note: We do this after the service-interval test.
220  * There are a lot more reasons for autoreplace to fail than we can test here reasonably. */
221  bool pending_replace = false;
222  Money needed_money = c->settings.engine_renew_money;
223  if (needed_money > GetAvailableMoney(c->index)) return false;
224 
225  for (const Vehicle *v = this; v != nullptr; v = (v->type == VEH_TRAIN) ? Train::From(v)->GetNextUnit() : nullptr) {
226  bool replace_when_old = false;
227  EngineID new_engine = EngineReplacementForCompany(c, v->engine_type, v->group_id, &replace_when_old);
228 
229  /* Check engine availability */
230  if (new_engine == INVALID_ENGINE || !HasBit(Engine::Get(new_engine)->company_avail, v->owner)) continue;
231  /* Is the vehicle old if we are not always replacing? */
232  if (replace_when_old && !v->NeedsAutorenewing(c, false)) continue;
233 
234  /* Check refittability */
235  CargoTypes available_cargo_types, union_mask;
236  GetArticulatedRefitMasks(new_engine, true, &union_mask, &available_cargo_types);
237  /* Is there anything to refit? */
238  if (union_mask != 0) {
240  CargoTypes cargo_mask = GetCargoTypesOfArticulatedVehicle(v, &cargo_type);
241  if (!HasAtMostOneBit(cargo_mask)) {
242  CargoTypes new_engine_default_cargoes = GetCargoTypesOfArticulatedParts(new_engine);
243  if ((cargo_mask & new_engine_default_cargoes) != cargo_mask) {
244  /* We cannot refit to mixed cargoes in an automated way */
245  continue;
246  }
247  /* engine_type is already a mixed cargo type which matches the incoming vehicle by default, no refit required */
248  } else {
249  /* Did the old vehicle carry anything? */
250  if (IsValidCargoID(cargo_type)) {
251  /* We can't refit the vehicle to carry the cargo we want */
252  if (!HasBit(available_cargo_types, cargo_type)) continue;
253  }
254  }
255  }
256 
257  /* Check money.
258  * We want 2*(the price of the new vehicle) without looking at the value of the vehicle we are going to sell. */
259  pending_replace = true;
260  needed_money += 2 * Engine::Get(new_engine)->GetCost();
261  if (needed_money > GetAvailableMoney(c->index)) return false;
262  }
263 
264  return pending_replace;
265 }
266 
273 {
274  if (this->HasDepotOrder()) return false;
275  if (this->current_order.IsType(OT_LOADING)) return false;
276  if (this->current_order.IsType(OT_GOTO_DEPOT) && (this->current_order.GetDepotOrderType() & ODTFB_SERVICE) == 0) return false;
277  return NeedsServicing();
278 }
279 
280 uint Vehicle::Crash(bool)
281 {
282  assert((this->vehstatus & VS_CRASHED) == 0);
283  assert(this->Previous() == nullptr); // IsPrimaryVehicle fails for free-wagon-chains
284 
285  uint pass = 0;
286  /* Stop the vehicle. */
287  if (this->IsPrimaryVehicle()) this->vehstatus |= VS_STOPPED;
288  /* crash all wagons, and count passengers */
289  for (Vehicle *v = this; v != nullptr; v = v->Next()) {
290  /* We do not transfer reserver cargo back, so TotalCount() instead of StoredCount() */
291  if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) pass += v->cargo.TotalCount();
292  v->vehstatus |= VS_CRASHED;
293  v->MarkAllViewportsDirty();
294  }
295 
296  /* Dirty some windows */
301 
302  delete this->cargo_payment;
303  assert(this->cargo_payment == nullptr); // cleared by ~CargoPayment
304 
305  return RandomRange(pass + 1); // Randomise deceased passengers.
306 }
307 
308 
317 void ShowNewGrfVehicleError(EngineID engine, StringID part1, StringID part2, GRFBugs bug_type, bool critical)
318 {
319  const Engine *e = Engine::Get(engine);
320  GRFConfig *grfconfig = GetGRFConfig(e->GetGRFID());
321 
322  /* Missing GRF. Nothing useful can be done in this situation. */
323  if (grfconfig == nullptr) return;
324 
325  if (!HasBit(grfconfig->grf_bugs, bug_type)) {
326  SetBit(grfconfig->grf_bugs, bug_type);
327  SetDParamStr(0, grfconfig->GetName());
328  SetDParam(1, engine);
329  ShowErrorMessage(part1, part2, WL_CRITICAL);
331  }
332 
333  /* debug output */
334  SetDParamStr(0, grfconfig->GetName());
335  Debug(grf, 0, "{}", StrMakeValid(GetString(part1)));
336 
337  SetDParam(1, engine);
338  Debug(grf, 0, "{}", StrMakeValid(GetString(part2)));
339 }
340 
347 {
348  /* show a warning once for each engine in whole game and once for each GRF after each game load */
349  const Engine *engine = u->GetEngine();
350  uint32_t grfid = engine->grf_prop.grffile->grfid;
351  GRFConfig *grfconfig = GetGRFConfig(grfid);
352  if (_gamelog.GRFBugReverse(grfid, engine->grf_prop.local_id) || !HasBit(grfconfig->grf_bugs, GBUG_VEH_LENGTH)) {
353  ShowNewGrfVehicleError(u->engine_type, STR_NEWGRF_BROKEN, STR_NEWGRF_BROKEN_VEHICLE_LENGTH, GBUG_VEH_LENGTH, true);
354  }
355 }
356 
362 {
363  this->type = type;
364  this->coord.left = INVALID_COORD;
365  this->sprite_cache.old_coord.left = INVALID_COORD;
366  this->group_id = DEFAULT_GROUP;
367  this->fill_percent_te_id = INVALID_TE_ID;
368  this->first = this;
369  this->colourmap = PAL_NONE;
370  this->cargo_age_counter = 1;
371  this->last_station_visited = INVALID_STATION;
372  this->last_loading_station = INVALID_STATION;
373 }
374 
375 /* Size of the hash, 6 = 64 x 64, 7 = 128 x 128. Larger sizes will (in theory) reduce hash
376  * lookup times at the expense of memory usage. */
377 const int HASH_BITS = 7;
378 const int HASH_SIZE = 1 << HASH_BITS;
379 const int HASH_MASK = HASH_SIZE - 1;
380 const int TOTAL_HASH_SIZE = 1 << (HASH_BITS * 2);
381 const int TOTAL_HASH_MASK = TOTAL_HASH_SIZE - 1;
382 
383 /* Resolution of the hash, 0 = 1*1 tile, 1 = 2*2 tiles, 2 = 4*4 tiles, etc.
384  * Profiling results show that 0 is fastest. */
385 const int HASH_RES = 0;
386 
387 static Vehicle *_vehicle_tile_hash[TOTAL_HASH_SIZE];
388 
389 static Vehicle *VehicleFromTileHash(int xl, int yl, int xu, int yu, void *data, VehicleFromPosProc *proc, bool find_first)
390 {
391  for (int y = yl; ; y = (y + (1 << HASH_BITS)) & (HASH_MASK << HASH_BITS)) {
392  for (int x = xl; ; x = (x + 1) & HASH_MASK) {
393  Vehicle *v = _vehicle_tile_hash[(x + y) & TOTAL_HASH_MASK];
394  for (; v != nullptr; v = v->hash_tile_next) {
395  Vehicle *a = proc(v, data);
396  if (find_first && a != nullptr) return a;
397  }
398  if (x == xu) break;
399  }
400  if (y == yu) break;
401  }
402 
403  return nullptr;
404 }
405 
406 
418 static Vehicle *VehicleFromPosXY(int x, int y, void *data, VehicleFromPosProc *proc, bool find_first)
419 {
420  const int COLL_DIST = 6;
421 
422  /* Hash area to scan is from xl,yl to xu,yu */
423  int xl = GB((x - COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS);
424  int xu = GB((x + COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS);
425  int yl = GB((y - COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS) << HASH_BITS;
426  int yu = GB((y + COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS) << HASH_BITS;
427 
428  return VehicleFromTileHash(xl, yl, xu, yu, data, proc, find_first);
429 }
430 
445 void FindVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
446 {
447  VehicleFromPosXY(x, y, data, proc, false);
448 }
449 
461 bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
462 {
463  return VehicleFromPosXY(x, y, data, proc, true) != nullptr;
464 }
465 
476 static Vehicle *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc, bool find_first)
477 {
478  int x = GB(TileX(tile), HASH_RES, HASH_BITS);
479  int y = GB(TileY(tile), HASH_RES, HASH_BITS) << HASH_BITS;
480 
481  Vehicle *v = _vehicle_tile_hash[(x + y) & TOTAL_HASH_MASK];
482  for (; v != nullptr; v = v->hash_tile_next) {
483  if (v->tile != tile) continue;
484 
485  Vehicle *a = proc(v, data);
486  if (find_first && a != nullptr) return a;
487  }
488 
489  return nullptr;
490 }
491 
505 void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
506 {
507  VehicleFromPos(tile, data, proc, false);
508 }
509 
520 bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
521 {
522  return VehicleFromPos(tile, data, proc, true) != nullptr;
523 }
524 
531 static Vehicle *EnsureNoVehicleProcZ(Vehicle *v, void *data)
532 {
533  int z = *(int*)data;
534 
535  if (v->type == VEH_DISASTER || (v->type == VEH_AIRCRAFT && v->subtype == AIR_SHADOW)) return nullptr;
536  if (v->z_pos > z) return nullptr;
537 
538  return v;
539 }
540 
547 {
548  int z = GetTileMaxPixelZ(tile);
549 
550  /* Value v is not safe in MP games, however, it is used to generate a local
551  * error message only (which may be different for different machines).
552  * Such a message does not affect MP synchronisation.
553  */
554  Vehicle *v = VehicleFromPos(tile, &z, &EnsureNoVehicleProcZ, true);
555  if (v != nullptr) return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
556  return CommandCost();
557 }
558 
561 {
562  if (v->type != VEH_TRAIN && v->type != VEH_ROAD && v->type != VEH_SHIP) return nullptr;
563  if (v == (const Vehicle *)data) return nullptr;
564 
565  return v;
566 }
567 
576 {
577  /* Value v is not safe in MP games, however, it is used to generate a local
578  * error message only (which may be different for different machines).
579  * Such a message does not affect MP synchronisation.
580  */
581  Vehicle *v = VehicleFromPos(tile, const_cast<Vehicle *>(ignore), &GetVehicleTunnelBridgeProc, true);
582  if (v == nullptr) v = VehicleFromPos(endtile, const_cast<Vehicle *>(ignore), &GetVehicleTunnelBridgeProc, true);
583 
584  if (v != nullptr) return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
585  return CommandCost();
586 }
587 
588 static Vehicle *EnsureNoTrainOnTrackProc(Vehicle *v, void *data)
589 {
590  TrackBits rail_bits = *(TrackBits *)data;
591 
592  if (v->type != VEH_TRAIN) return nullptr;
593 
594  Train *t = Train::From(v);
595  if ((t->track != rail_bits) && !TracksOverlap(t->track | rail_bits)) return nullptr;
596 
597  return v;
598 }
599 
609 {
610  /* Value v is not safe in MP games, however, it is used to generate a local
611  * error message only (which may be different for different machines).
612  * Such a message does not affect MP synchronisation.
613  */
614  Vehicle *v = VehicleFromPos(tile, &track_bits, &EnsureNoTrainOnTrackProc, true);
615  if (v != nullptr) return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
616  return CommandCost();
617 }
618 
619 static void UpdateVehicleTileHash(Vehicle *v, bool remove)
620 {
621  Vehicle **old_hash = v->hash_tile_current;
622  Vehicle **new_hash;
623 
624  if (remove) {
625  new_hash = nullptr;
626  } else {
627  int x = GB(TileX(v->tile), HASH_RES, HASH_BITS);
628  int y = GB(TileY(v->tile), HASH_RES, HASH_BITS) << HASH_BITS;
629  new_hash = &_vehicle_tile_hash[(x + y) & TOTAL_HASH_MASK];
630  }
631 
632  if (old_hash == new_hash) return;
633 
634  /* Remove from the old position in the hash table */
635  if (old_hash != nullptr) {
636  if (v->hash_tile_next != nullptr) v->hash_tile_next->hash_tile_prev = v->hash_tile_prev;
638  }
639 
640  /* Insert vehicle at beginning of the new position in the hash table */
641  if (new_hash != nullptr) {
642  v->hash_tile_next = *new_hash;
643  if (v->hash_tile_next != nullptr) v->hash_tile_next->hash_tile_prev = &v->hash_tile_next;
644  v->hash_tile_prev = new_hash;
645  *new_hash = v;
646  }
647 
648  /* Remember current hash position */
649  v->hash_tile_current = new_hash;
650 }
651 
652 static Vehicle *_vehicle_viewport_hash[1 << (GEN_HASHX_BITS + GEN_HASHY_BITS)];
653 
654 static void UpdateVehicleViewportHash(Vehicle *v, int x, int y, int old_x, int old_y)
655 {
656  Vehicle **old_hash, **new_hash;
657 
658  new_hash = (x == INVALID_COORD) ? nullptr : &_vehicle_viewport_hash[GEN_HASH(x, y)];
659  old_hash = (old_x == INVALID_COORD) ? nullptr : &_vehicle_viewport_hash[GEN_HASH(old_x, old_y)];
660 
661  if (old_hash == new_hash) return;
662 
663  /* remove from hash table? */
664  if (old_hash != nullptr) {
667  }
668 
669  /* insert into hash table? */
670  if (new_hash != nullptr) {
671  v->hash_viewport_next = *new_hash;
673  v->hash_viewport_prev = new_hash;
674  *new_hash = v;
675  }
676 }
677 
678 void ResetVehicleHash()
679 {
680  for (Vehicle *v : Vehicle::Iterate()) { v->hash_tile_current = nullptr; }
681  memset(_vehicle_viewport_hash, 0, sizeof(_vehicle_viewport_hash));
682  memset(_vehicle_tile_hash, 0, sizeof(_vehicle_tile_hash));
683 }
684 
685 void ResetVehicleColourMap()
686 {
687  for (Vehicle *v : Vehicle::Iterate()) { v->colourmap = PAL_NONE; }
688 }
689 
694 using AutoreplaceMap = std::map<VehicleID, bool>;
695 static AutoreplaceMap _vehicles_to_autoreplace;
696 
697 void InitializeVehicles()
698 {
699  _vehicles_to_autoreplace.clear();
700  ResetVehicleHash();
701 }
702 
703 uint CountVehiclesInChain(const Vehicle *v)
704 {
705  uint count = 0;
706  do count++; while ((v = v->Next()) != nullptr);
707  return count;
708 }
709 
715 {
716  switch (this->type) {
717  case VEH_AIRCRAFT: return Aircraft::From(this)->IsNormalAircraft(); // don't count plane shadows and helicopter rotors
718  case VEH_TRAIN:
719  return !this->IsArticulatedPart() && // tenders and other articulated parts
720  !Train::From(this)->IsRearDualheaded(); // rear parts of multiheaded engines
721  case VEH_ROAD: return RoadVehicle::From(this)->IsFrontEngine();
722  case VEH_SHIP: return true;
723  default: return false; // Only count company buildable vehicles
724  }
725 }
726 
732 {
733  switch (this->type) {
734  case VEH_AIRCRAFT: return Aircraft::From(this)->IsNormalAircraft();
735  case VEH_TRAIN:
736  case VEH_ROAD:
737  case VEH_SHIP: return true;
738  default: return false;
739  }
740 }
741 
748 {
749  return Engine::Get(this->engine_type);
750 }
751 
757 const GRFFile *Vehicle::GetGRF() const
758 {
759  return this->GetEngine()->GetGRF();
760 }
761 
767 uint32_t Vehicle::GetGRFID() const
768 {
769  return this->GetEngine()->GetGRFID();
770 }
771 
777 void Vehicle::ShiftDates(TimerGameEconomy::Date interval)
778 {
779  this->date_of_last_service = std::max(this->date_of_last_service + interval, TimerGameEconomy::Date(0));
780  /* date_of_last_service_newgrf is not updated here as it must stay stable
781  * for vehicles outside of a depot. */
782 }
783 
791 void Vehicle::HandlePathfindingResult(bool path_found)
792 {
793  if (path_found) {
794  /* Route found, is the vehicle marked with "lost" flag? */
795  if (!HasBit(this->vehicle_flags, VF_PATHFINDER_LOST)) return;
796 
797  /* Clear the flag as the PF's problem was solved. */
801  /* Delete the news item. */
802  DeleteVehicleNews(this->index, STR_NEWS_VEHICLE_IS_LOST);
803  return;
804  }
805 
806  /* Were we already lost? */
807  if (HasBit(this->vehicle_flags, VF_PATHFINDER_LOST)) return;
808 
809  /* It is first time the problem occurred, set the "lost" flag. */
813 
814  /* Unbunching data is no longer valid. */
815  this->ResetDepotUnbunching();
816 
817  /* Notify user about the event. */
818  AI::NewEvent(this->owner, new ScriptEventVehicleLost(this->index));
819  if (_settings_client.gui.lost_vehicle_warn && this->owner == _local_company) {
820  SetDParam(0, this->index);
821  AddVehicleAdviceNewsItem(STR_NEWS_VEHICLE_IS_LOST, this->index);
822  }
823 }
824 
827 {
828  if (CleaningPool()) return;
829 
832  st->loading_vehicles.remove(this);
833 
835  this->CancelReservation(INVALID_STATION, st);
836  delete this->cargo_payment;
837  assert(this->cargo_payment == nullptr); // cleared by ~CargoPayment
838  }
839 
840  if (this->IsEngineCountable()) {
842  if (this->IsPrimaryVehicle()) GroupStatistics::CountVehicle(this, -1);
844 
847  }
848 
849  Company::Get(this->owner)->freeunits[this->type].ReleaseID(this->unitnumber);
850 
851  if (this->type == VEH_AIRCRAFT && this->IsPrimaryVehicle()) {
852  Aircraft *a = Aircraft::From(this);
854  if (st != nullptr) {
855  const AirportFTA *layout = st->airport.GetFTA()->layout;
856  CLRBITS(st->airport.flags, layout[a->previous_pos].block | layout[a->pos].block);
857  }
858  }
859 
860 
861  if (this->type == VEH_ROAD && this->IsPrimaryVehicle()) {
862  RoadVehicle *v = RoadVehicle::From(this);
863  if (!(v->vehstatus & VS_CRASHED) && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END)) {
864  /* Leave the drive through roadstop, when you have not already left it. */
866  }
867 
869  }
870 
871  if (this->Previous() == nullptr) {
873  }
874 
875  if (this->IsPrimaryVehicle()) {
883  }
885 
886  this->cargo.Truncate();
887  DeleteVehicleOrders(this);
889 
890  StopGlobalFollowVehicle(this);
891 }
892 
894 {
895  if (CleaningPool()) {
896  this->cargo.OnCleanPool();
897  return;
898  }
899 
900  /* sometimes, eg. for disaster vehicles, when company bankrupts, when removing crashed/flooded vehicles,
901  * it may happen that vehicle chain is deleted when visible */
902  if (!(this->vehstatus & VS_HIDDEN)) this->MarkAllViewportsDirty();
903 
904  Vehicle *v = this->Next();
905  this->SetNext(nullptr);
906 
907  delete v;
908 
909  UpdateVehicleTileHash(this, true);
910  UpdateVehicleViewportHash(this, INVALID_COORD, 0, this->sprite_cache.old_coord.left, this->sprite_cache.old_coord.top);
911  if (this->type != VEH_EFFECT) {
914  }
915 }
916 
922 {
923  /* Vehicle should stop in the depot if it was in 'stopping' state */
924  _vehicles_to_autoreplace[v->index] = !(v->vehstatus & VS_STOPPED);
925 
926  /* We ALWAYS set the stopped state. Even when the vehicle does not plan on
927  * stopping in the depot, so we stop it to ensure that it will not reserve
928  * the path out of the depot before we might autoreplace it to a different
929  * engine. The new engine would not own the reserved path we store that we
930  * stopped the vehicle, so autoreplace can start it again */
931  v->vehstatus |= VS_STOPPED;
932 }
933 
938 {
939  if (_game_mode != GM_NORMAL) return;
940 
941  /* Run the calendar day proc for every DAY_TICKS vehicle starting at TimerGameCalendar::date_fract. */
943  Vehicle *v = Vehicle::Get(i);
944  if (v == nullptr) continue;
945  v->OnNewCalendarDay();
946  }
947 }
948 
955 {
956  if (_game_mode != GM_NORMAL) return;
957 
958  /* Run the economy day proc for every DAY_TICKS vehicle starting at TimerGameEconomy::date_fract. */
960  Vehicle *v = Vehicle::Get(i);
961  if (v == nullptr) continue;
962 
963  /* Call the 32-day callback if needed */
964  if ((v->day_counter & 0x1F) == 0 && v->HasEngineType()) {
965  uint16_t callback = GetVehicleCallback(CBID_VEHICLE_32DAY_CALLBACK, 0, 0, v->engine_type, v);
966  if (callback != CALLBACK_FAILED) {
967  if (HasBit(callback, 0)) {
968  TriggerVehicle(v, VEHICLE_TRIGGER_CALLBACK_32); // Trigger vehicle trigger 10
969  }
970 
971  /* After a vehicle trigger, the graphics and properties of the vehicle could change.
972  * Note: MarkDirty also invalidates the palette, which is the meaning of bit 1. So, nothing special there. */
973  if (callback != 0) v->First()->MarkDirty();
974 
975  if (callback & ~3) ErrorUnknownCallbackResult(v->GetGRFID(), CBID_VEHICLE_32DAY_CALLBACK, callback);
976  }
977  }
978 
979  /* This is called once per day for each vehicle, but not in the first tick of the day */
980  v->OnNewEconomyDay();
981  }
982 }
983 
984 void CallVehicleTicks()
985 {
986  _vehicles_to_autoreplace.clear();
987 
989 
990  {
992  for (Station *st : Station::Iterate()) LoadUnloadStation(st);
993  }
998 
999  for (Vehicle *v : Vehicle::Iterate()) {
1000  [[maybe_unused]] size_t vehicle_index = v->index;
1001 
1002  /* Vehicle could be deleted in this tick */
1003  if (!v->Tick()) {
1004  assert(Vehicle::Get(vehicle_index) == nullptr);
1005  continue;
1006  }
1007 
1008  assert(Vehicle::Get(vehicle_index) == v);
1009 
1010  switch (v->type) {
1011  default: break;
1012 
1013  case VEH_TRAIN:
1014  case VEH_ROAD:
1015  case VEH_AIRCRAFT:
1016  case VEH_SHIP: {
1017  Vehicle *front = v->First();
1018 
1019  if (v->vcache.cached_cargo_age_period != 0) {
1021  if (--v->cargo_age_counter == 0) {
1022  v->cargo.AgeCargo();
1024  }
1025  }
1026 
1027  /* Do not play any sound when crashed */
1028  if (front->vehstatus & VS_CRASHED) continue;
1029 
1030  /* Do not play any sound when in depot or tunnel */
1031  if (v->vehstatus & VS_HIDDEN) continue;
1032 
1033  /* Do not play any sound when stopped */
1034  if ((front->vehstatus & VS_STOPPED) && (front->type != VEH_TRAIN || front->cur_speed == 0)) continue;
1035 
1036  /* Update motion counter for animation purposes. */
1037  v->motion_counter += front->cur_speed;
1038 
1039  /* Check vehicle type specifics */
1040  switch (v->type) {
1041  case VEH_TRAIN:
1042  if (!Train::From(v)->IsEngine()) continue;
1043  break;
1044 
1045  case VEH_ROAD:
1046  if (!RoadVehicle::From(v)->IsFrontEngine()) continue;
1047  break;
1048 
1049  case VEH_AIRCRAFT:
1050  if (!Aircraft::From(v)->IsNormalAircraft()) continue;
1051  break;
1052 
1053  default:
1054  break;
1055  }
1056 
1057  /* Play a running sound if the motion counter passes 256 (Do we not skip sounds?) */
1058  if (GB(v->motion_counter, 0, 8) < front->cur_speed) PlayVehicleSound(v, VSE_RUNNING);
1059 
1060  /* Play an alternating running sound every 16 ticks */
1061  if (GB(v->tick_counter, 0, 4) == 0) {
1062  /* Play running sound when speed > 0 and not braking */
1063  bool running = (front->cur_speed > 0) && !(front->vehstatus & (VS_STOPPED | VS_TRAIN_SLOWING));
1065  }
1066 
1067  break;
1068  }
1069  }
1070  }
1071 
1072  Backup<CompanyID> cur_company(_current_company);
1073  for (auto &it : _vehicles_to_autoreplace) {
1074  Vehicle *v = Vehicle::Get(it.first);
1075  /* Autoreplace needs the current company set as the vehicle owner */
1076  cur_company.Change(v->owner);
1077 
1078  /* Start vehicle if we stopped them in VehicleEnteredDepotThisTick()
1079  * We need to stop them between VehicleEnteredDepotThisTick() and here or we risk that
1080  * they are already leaving the depot again before being replaced. */
1081  if (it.second) v->vehstatus &= ~VS_STOPPED;
1082 
1083  /* Store the position of the effect as the vehicle pointer will become invalid later */
1084  int x = v->x_pos;
1085  int y = v->y_pos;
1086  int z = v->z_pos;
1087 
1092 
1093  if (!IsLocalCompany()) continue;
1094 
1095  if (res.Succeeded()) {
1096  ShowCostOrIncomeAnimation(x, y, z, res.GetCost());
1097  continue;
1098  }
1099 
1100  StringID error_message = res.GetErrorMessage();
1101  if (error_message == STR_ERROR_AUTOREPLACE_NOTHING_TO_DO || error_message == INVALID_STRING_ID) continue;
1102 
1103  if (error_message == STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY) error_message = STR_ERROR_AUTOREPLACE_MONEY_LIMIT;
1104 
1105  StringID message;
1106  if (error_message == STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT) {
1107  message = error_message;
1108  } else {
1109  message = STR_NEWS_VEHICLE_AUTORENEW_FAILED;
1110  }
1111 
1112  SetDParam(0, v->index);
1113  SetDParam(1, error_message);
1114  AddVehicleAdviceNewsItem(message, v->index);
1115  }
1116 
1117  cur_company.Restore();
1118 }
1119 
1124 static void DoDrawVehicle(const Vehicle *v)
1125 {
1126  PaletteID pal = PAL_NONE;
1127 
1129 
1130  /* Check whether the vehicle shall be transparent due to the game state */
1131  bool shadowed = (v->vehstatus & VS_SHADOW) != 0;
1132 
1133  if (v->type == VEH_EFFECT) {
1134  /* Check whether the vehicle shall be transparent/invisible due to GUI settings.
1135  * However, transparent smoke and bubbles look weird, so always hide them. */
1137  if (to != TO_INVALID && (IsTransparencySet(to) || IsInvisibilitySet(to))) return;
1138  }
1139 
1141  for (uint i = 0; i < v->sprite_cache.sprite_seq.count; ++i) {
1142  PaletteID pal2 = v->sprite_cache.sprite_seq.seq[i].pal;
1143  if (!pal2 || (v->vehstatus & VS_CRASHED)) pal2 = pal;
1144  AddSortableSpriteToDraw(v->sprite_cache.sprite_seq.seq[i].sprite, pal2, v->x_pos + v->x_offs, v->y_pos + v->y_offs,
1145  v->x_extent, v->y_extent, v->z_extent, v->z_pos, shadowed, v->x_bb_offs, v->y_bb_offs);
1146  }
1147  EndSpriteCombine();
1148 }
1149 
1155 {
1156  /* The bounding rectangle */
1157  const int l = dpi->left;
1158  const int r = dpi->left + dpi->width;
1159  const int t = dpi->top;
1160  const int b = dpi->top + dpi->height;
1161 
1162  /* Border size of MAX_VEHICLE_PIXEL_xy */
1163  const int xb = MAX_VEHICLE_PIXEL_X * ZOOM_BASE;
1164  const int yb = MAX_VEHICLE_PIXEL_Y * ZOOM_BASE;
1165 
1166  /* The hash area to scan */
1167  int xl, xu, yl, yu;
1168 
1169  if (dpi->width + xb < GEN_HASHX_SIZE) {
1170  xl = GEN_HASHX(l - xb);
1171  xu = GEN_HASHX(r);
1172  } else {
1173  /* scan whole hash row */
1174  xl = 0;
1175  xu = GEN_HASHX_MASK;
1176  }
1177 
1178  if (dpi->height + yb < GEN_HASHY_SIZE) {
1179  yl = GEN_HASHY(t - yb);
1180  yu = GEN_HASHY(b);
1181  } else {
1182  /* scan whole column */
1183  yl = 0;
1184  yu = GEN_HASHY_MASK;
1185  }
1186 
1187  for (int y = yl;; y = (y + GEN_HASHY_INC) & GEN_HASHY_MASK) {
1188  for (int x = xl;; x = (x + GEN_HASHX_INC) & GEN_HASHX_MASK) {
1189  const Vehicle *v = _vehicle_viewport_hash[x + y]; // already masked & 0xFFF
1190 
1191  while (v != nullptr) {
1192 
1193  if (!(v->vehstatus & VS_HIDDEN) &&
1194  l <= v->coord.right + xb &&
1195  t <= v->coord.bottom + yb &&
1196  r >= v->coord.left - xb &&
1197  b >= v->coord.top - yb)
1198  {
1199  /*
1200  * This vehicle can potentially be drawn as part of this viewport and
1201  * needs to be revalidated, as the sprite may not be correct.
1202  */
1204  VehicleSpriteSeq seq;
1205  v->GetImage(v->direction, EIT_ON_MAP, &seq);
1206 
1207  if (seq.IsValid() && v->sprite_cache.sprite_seq != seq) {
1208  v->sprite_cache.sprite_seq = seq;
1209  /*
1210  * A sprite change may also result in a bounding box change,
1211  * so we need to update the bounding box again before we
1212  * check to see if the vehicle should be drawn. Note that
1213  * we can't interfere with the viewport hash at this point,
1214  * so we keep the original hash on the assumption there will
1215  * not be a significant change in the top and left coordinates
1216  * of the vehicle.
1217  */
1218  v->UpdateBoundingBoxCoordinates(false);
1219 
1220  }
1221 
1223  }
1224 
1225  if (l <= v->coord.right &&
1226  t <= v->coord.bottom &&
1227  r >= v->coord.left &&
1228  b >= v->coord.top) DoDrawVehicle(v);
1229  }
1230 
1231  v = v->hash_viewport_next;
1232  }
1233 
1234  if (x == xu) break;
1235  }
1236 
1237  if (y == yu) break;
1238  }
1239 }
1240 
1248 Vehicle *CheckClickOnVehicle(const Viewport *vp, int x, int y)
1249 {
1250  Vehicle *found = nullptr;
1251  uint dist, best_dist = UINT_MAX;
1252 
1253  if ((uint)(x -= vp->left) >= (uint)vp->width || (uint)(y -= vp->top) >= (uint)vp->height) return nullptr;
1254 
1255  x = ScaleByZoom(x, vp->zoom) + vp->virtual_left;
1256  y = ScaleByZoom(y, vp->zoom) + vp->virtual_top;
1257 
1258  /* Border size of MAX_VEHICLE_PIXEL_xy */
1259  const int xb = MAX_VEHICLE_PIXEL_X * ZOOM_BASE;
1260  const int yb = MAX_VEHICLE_PIXEL_Y * ZOOM_BASE;
1261 
1262  /* The hash area to scan */
1263  int xl = GEN_HASHX(x - xb);
1264  int xu = GEN_HASHX(x);
1265  int yl = GEN_HASHY(y - yb);
1266  int yu = GEN_HASHY(y);
1267 
1268  for (int hy = yl;; hy = (hy + GEN_HASHY_INC) & GEN_HASHY_MASK) {
1269  for (int hx = xl;; hx = (hx + GEN_HASHX_INC) & GEN_HASHX_MASK) {
1270  Vehicle *v = _vehicle_viewport_hash[hx + hy]; // already masked & 0xFFF
1271 
1272  while (v != nullptr) {
1273  if ((v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0 &&
1274  x >= v->coord.left && x <= v->coord.right &&
1275  y >= v->coord.top && y <= v->coord.bottom) {
1276 
1277  dist = std::max(
1278  abs(((v->coord.left + v->coord.right) >> 1) - x),
1279  abs(((v->coord.top + v->coord.bottom) >> 1) - y)
1280  );
1281 
1282  if (dist < best_dist) {
1283  found = v;
1284  best_dist = dist;
1285  }
1286  }
1287  v = v->hash_viewport_next;
1288  }
1289  if (hx == xu) break;
1290  }
1291  if (hy == yu) break;
1292  }
1293 
1294  return found;
1295 }
1296 
1302 {
1303  v->value -= v->value >> 8;
1305 }
1306 
1307 static const uint8_t _breakdown_chance[64] = {
1308  3, 3, 3, 3, 3, 3, 3, 3,
1309  4, 4, 5, 5, 6, 6, 7, 7,
1310  8, 8, 9, 9, 10, 10, 11, 11,
1311  12, 13, 13, 13, 13, 14, 15, 16,
1312  17, 19, 21, 25, 28, 31, 34, 37,
1313  40, 44, 48, 52, 56, 60, 64, 68,
1314  72, 80, 90, 100, 110, 120, 130, 140,
1315  150, 170, 190, 210, 230, 250, 250, 250,
1316 };
1317 
1318 void CheckVehicleBreakdown(Vehicle *v)
1319 {
1320  int rel, rel_old;
1321 
1322  /* decrease reliability */
1325  v->reliability = rel = std::max((rel_old = v->reliability) - v->reliability_spd_dec, 0);
1326  if ((rel_old >> 8) != (rel >> 8)) SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
1327  }
1328 
1329  if (v->breakdown_ctr != 0 || (v->vehstatus & VS_STOPPED) ||
1331  v->cur_speed < 5 || _game_mode == GM_MENU) {
1332  return;
1333  }
1334 
1335  uint32_t r = Random();
1336 
1337  /* increase chance of failure */
1338  int chance = v->breakdown_chance + 1;
1339  if (Chance16I(1, 25, r)) chance += 25;
1340  v->breakdown_chance = ClampTo<uint8_t>(chance);
1341 
1342  /* calculate reliability value to use in comparison */
1343  rel = v->reliability;
1344  if (v->type == VEH_SHIP) rel += 0x6666;
1345 
1346  /* reduced breakdowns? */
1347  if (_settings_game.difficulty.vehicle_breakdowns == 1) rel += 0x6666;
1348 
1349  /* check if to break down */
1350  if (_breakdown_chance[ClampTo<uint16_t>(rel) >> 10] <= v->breakdown_chance) {
1351  v->breakdown_ctr = GB(r, 16, 6) + 0x3F;
1352  v->breakdown_delay = GB(r, 24, 7) + 0x80;
1353  v->breakdown_chance = 0;
1354  }
1355 }
1356 
1364 {
1365  /* Possible states for Vehicle::breakdown_ctr
1366  * 0 - vehicle is running normally
1367  * 1 - vehicle is currently broken down
1368  * 2 - vehicle is going to break down now
1369  * >2 - vehicle is counting down to the actual breakdown event */
1370  switch (this->breakdown_ctr) {
1371  case 0:
1372  return false;
1373 
1374  case 2:
1375  this->breakdown_ctr = 1;
1376 
1377  if (this->breakdowns_since_last_service != 255) {
1379  }
1380 
1381  if (this->type == VEH_AIRCRAFT) {
1382  /* Aircraft just need this flag, the rest is handled elsewhere */
1383  this->vehstatus |= VS_AIRCRAFT_BROKEN;
1384  } else {
1385  this->cur_speed = 0;
1386 
1387  if (!PlayVehicleSound(this, VSE_BREAKDOWN)) {
1388  bool train_or_ship = this->type == VEH_TRAIN || this->type == VEH_SHIP;
1389  SndPlayVehicleFx((_settings_game.game_creation.landscape != LT_TOYLAND) ?
1392  }
1393 
1394  if (!(this->vehstatus & VS_HIDDEN) && !HasBit(EngInfo(this->engine_type)->misc_flags, EF_NO_BREAKDOWN_SMOKE)) {
1396  if (u != nullptr) u->animation_state = this->breakdown_delay * 2;
1397  }
1398  }
1399 
1400  this->MarkDirty(); // Update graphics after speed is zeroed
1403 
1404  [[fallthrough]];
1405  case 1:
1406  /* Aircraft breakdowns end only when arriving at the airport */
1407  if (this->type == VEH_AIRCRAFT) return false;
1408 
1409  /* For trains this function is called twice per tick, so decrease v->breakdown_delay at half the rate */
1410  if ((this->tick_counter & (this->type == VEH_TRAIN ? 3 : 1)) == 0) {
1411  if (--this->breakdown_delay == 0) {
1412  this->breakdown_ctr = 0;
1413  this->MarkDirty();
1415  }
1416  }
1417  return true;
1418 
1419  default:
1420  if (!this->current_order.IsType(OT_LOADING)) this->breakdown_ctr--;
1421  return false;
1422  }
1423 }
1424 
1430 {
1432  v->economy_age++;
1434  }
1435 }
1436 
1442 {
1443  if (v->age < CalendarTime::MAX_DATE) v->age++;
1444 
1445  if (!v->IsPrimaryVehicle() && (v->type != VEH_TRAIN || !Train::From(v)->IsEngine())) return;
1446 
1447  auto age = v->age - v->max_age;
1448  for (int32_t i = 0; i <= 4; i++) {
1449  if (age == TimerGameCalendar::DateAtStartOfYear(i)) {
1450  v->reliability_spd_dec <<= 1;
1451  break;
1452  }
1453  }
1454 
1456 
1457  /* Don't warn if warnings are disabled */
1458  if (!_settings_client.gui.old_vehicle_warn) return;
1459 
1460  /* Don't warn about vehicles which are non-primary (e.g., part of an articulated vehicle), don't belong to us, are crashed, or are stopped */
1461  if (v->Previous() != nullptr || v->owner != _local_company || (v->vehstatus & VS_CRASHED) != 0 || (v->vehstatus & VS_STOPPED) != 0) return;
1462 
1463  const Company *c = Company::Get(v->owner);
1464  /* Don't warn if a renew is active */
1465  if (c->settings.engine_renew && v->GetEngine()->company_avail != 0) return;
1466  /* Don't warn if a replacement is active */
1467  if (EngineHasReplacementForCompany(c, v->engine_type, v->group_id)) return;
1468 
1469  StringID str;
1470  if (age == TimerGameCalendar::DateAtStartOfYear(-1)) {
1471  str = STR_NEWS_VEHICLE_IS_GETTING_OLD;
1472  } else if (age == TimerGameCalendar::DateAtStartOfYear(0)) {
1473  str = STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD;
1474  } else if (age > TimerGameCalendar::DateAtStartOfYear(0) && (age.base() % CalendarTime::DAYS_IN_LEAP_YEAR) == 0) {
1475  str = STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD_AND;
1476  } else {
1477  return;
1478  }
1479 
1480  SetDParam(0, v->index);
1482 }
1483 
1493 uint8_t CalcPercentVehicleFilled(const Vehicle *front, StringID *colour)
1494 {
1495  int count = 0;
1496  int max = 0;
1497  int cars = 0;
1498  int unloading = 0;
1499  bool loading = false;
1500 
1501  bool is_loading = front->current_order.IsType(OT_LOADING);
1502 
1503  /* The station may be nullptr when the (colour) string does not need to be set. */
1504  const Station *st = Station::GetIfValid(front->last_station_visited);
1505  assert(colour == nullptr || (st != nullptr && is_loading));
1506 
1507  bool order_no_load = is_loading && (front->current_order.GetLoadType() & OLFB_NO_LOAD);
1508  bool order_full_load = is_loading && (front->current_order.GetLoadType() & OLFB_FULL_LOAD);
1509 
1510  /* Count up max and used */
1511  for (const Vehicle *v = front; v != nullptr; v = v->Next()) {
1512  count += v->cargo.StoredCount();
1513  max += v->cargo_cap;
1514  if (v->cargo_cap != 0 && colour != nullptr) {
1515  unloading += HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) ? 1 : 0;
1516  loading |= !order_no_load &&
1517  (order_full_load || st->goods[v->cargo_type].HasRating()) &&
1519  cars++;
1520  }
1521  }
1522 
1523  if (colour != nullptr) {
1524  if (unloading == 0 && loading) {
1525  *colour = STR_PERCENT_UP;
1526  } else if (unloading == 0 && !loading) {
1527  *colour = STR_PERCENT_NONE;
1528  } else if (cars == unloading || !loading) {
1529  *colour = STR_PERCENT_DOWN;
1530  } else {
1531  *colour = STR_PERCENT_UP_DOWN;
1532  }
1533  }
1534 
1535  /* Train without capacity */
1536  if (max == 0) return 100;
1537 
1538  /* Return the percentage */
1539  if (count * 2 < max) {
1540  /* Less than 50%; round up, so that 0% means really empty. */
1541  return CeilDiv(count * 100, max);
1542  } else {
1543  /* More than 50%; round down, so that 100% means really full. */
1544  return (count * 100) / max;
1545  }
1546 }
1547 
1553 {
1554  /* Always work with the front of the vehicle */
1555  assert(v == v->First());
1556 
1557  switch (v->type) {
1558  case VEH_TRAIN: {
1559  Train *t = Train::From(v);
1561  /* Clear path reservation */
1562  SetDepotReservation(t->tile, false);
1564 
1566  t->wait_counter = 0;
1567  t->force_proceed = TFP_NONE;
1568  ClrBit(t->flags, VRF_TOGGLE_REVERSE);
1570  break;
1571  }
1572 
1573  case VEH_ROAD:
1575  break;
1576 
1577  case VEH_SHIP: {
1579  Ship *ship = Ship::From(v);
1580  ship->state = TRACK_BIT_DEPOT;
1581  ship->UpdateCache();
1582  ship->UpdateViewport(true, true);
1584  break;
1585  }
1586 
1587  case VEH_AIRCRAFT:
1590  break;
1591  default: NOT_REACHED();
1592  }
1594 
1595  if (v->type != VEH_TRAIN) {
1596  /* Trains update the vehicle list when the first unit enters the depot and calls VehicleEnterDepot() when the last unit enters.
1597  * 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 */
1599  }
1601 
1602  v->vehstatus |= VS_HIDDEN;
1603  v->cur_speed = 0;
1604 
1606 
1607  /* After a vehicle trigger, the graphics and properties of the vehicle could change. */
1608  TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
1609  v->MarkDirty();
1610 
1612 
1613  if (v->current_order.IsType(OT_GOTO_DEPOT)) {
1615 
1616  const Order *real_order = v->GetOrder(v->cur_real_order_index);
1617 
1618  /* Test whether we are heading for this depot. If not, do nothing.
1619  * Note: The target depot for nearest-/manual-depot-orders is only updated on junctions, but we want to accept every depot. */
1621  real_order != nullptr && !(real_order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) &&
1622  (v->type == VEH_AIRCRAFT ? v->current_order.GetDestination() != GetStationIndex(v->tile) : v->dest_tile != v->tile)) {
1623  /* We are heading for another depot, keep driving. */
1624  return;
1625  }
1626 
1627  if (v->current_order.IsRefit()) {
1628  Backup<CompanyID> cur_company(_current_company, v->owner);
1629  CommandCost cost = std::get<0>(Command<CMD_REFIT_VEHICLE>::Do(DC_EXEC, v->index, v->current_order.GetRefitCargo(), 0xFF, false, false, 0));
1630  cur_company.Restore();
1631 
1632  if (cost.Failed()) {
1633  _vehicles_to_autoreplace[v->index] = false;
1634  if (v->owner == _local_company) {
1635  /* Notify the user that we stopped the vehicle */
1636  SetDParam(0, v->index);
1637  AddVehicleAdviceNewsItem(STR_NEWS_ORDER_REFIT_FAILED, v->index);
1638  }
1639  } else if (cost.GetCost() != 0) {
1640  v->profit_this_year -= cost.GetCost() << 8;
1641  if (v->owner == _local_company) {
1642  ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
1643  }
1644  }
1645  }
1646 
1648  /* Part of orders */
1650  UpdateVehicleTimetable(v, true);
1652  }
1654  /* Vehicles are always stopped on entering depots. Do not restart this one. */
1655  _vehicles_to_autoreplace[v->index] = false;
1656  /* Invalidate last_loading_station. As the link from the station
1657  * before the stop to the station after the stop can't be predicted
1658  * we shouldn't construct it when the vehicle visits the next stop. */
1659  v->last_loading_station = INVALID_STATION;
1660 
1661  /* Clear unbunching data. */
1662  v->ResetDepotUnbunching();
1663 
1664  /* Announce that the vehicle is waiting to players and AIs. */
1665  if (v->owner == _local_company) {
1666  SetDParam(0, v->index);
1667  AddVehicleAdviceNewsItem(STR_NEWS_TRAIN_IS_WAITING + v->type, v->index);
1668  }
1669  AI::NewEvent(v->owner, new ScriptEventVehicleWaitingInDepot(v->index));
1670  }
1671 
1672  /* If we've entered our unbunching depot, record the round trip duration. */
1675  if (v->round_trip_time == 0) {
1676  /* This might be our first round trip. */
1677  v->round_trip_time = measured_round_trip;
1678  } else {
1679  /* If we have a previous trip, smooth the effects of outlier trip calculations caused by jams or other interference. */
1680  v->round_trip_time = Clamp(measured_round_trip, (v->round_trip_time / 2), ClampTo<TimerGameTick::Ticks>(v->round_trip_time * 2));
1681  }
1682  }
1683 
1684  v->current_order.MakeDummy();
1685  }
1686 }
1687 
1688 
1694 {
1695  UpdateVehicleTileHash(this, false);
1696 }
1697 
1702 void Vehicle::UpdateBoundingBoxCoordinates(bool update_cache) const
1703 {
1704  Rect new_coord;
1705  this->sprite_cache.sprite_seq.GetBounds(&new_coord);
1706 
1707  Point pt = RemapCoords(this->x_pos + this->x_offs, this->y_pos + this->y_offs, this->z_pos);
1708  new_coord.left += pt.x;
1709  new_coord.top += pt.y;
1710  new_coord.right += pt.x + 2 * ZOOM_BASE;
1711  new_coord.bottom += pt.y + 2 * ZOOM_BASE;
1712 
1713  if (update_cache) {
1714  /*
1715  * If the old coordinates are invalid, set the cache to the new coordinates for correct
1716  * behaviour the next time the coordinate cache is checked.
1717  */
1718  this->sprite_cache.old_coord = this->coord.left == INVALID_COORD ? new_coord : this->coord;
1719  }
1720  else {
1721  /* Extend the bounds of the existing cached bounding box so the next dirty window is correct */
1722  this->sprite_cache.old_coord.left = std::min(this->sprite_cache.old_coord.left, this->coord.left);
1723  this->sprite_cache.old_coord.top = std::min(this->sprite_cache.old_coord.top, this->coord.top);
1724  this->sprite_cache.old_coord.right = std::max(this->sprite_cache.old_coord.right, this->coord.right);
1725  this->sprite_cache.old_coord.bottom = std::max(this->sprite_cache.old_coord.bottom, this->coord.bottom);
1726  }
1727 
1728  this->coord = new_coord;
1729 }
1730 
1735 void Vehicle::UpdateViewport(bool dirty)
1736 {
1737  /* If the existing cache is invalid we should ignore it, as it will be set to the current coords by UpdateBoundingBoxCoordinates */
1738  bool ignore_cached_coords = this->sprite_cache.old_coord.left == INVALID_COORD;
1739 
1740  this->UpdateBoundingBoxCoordinates(true);
1741 
1742  if (ignore_cached_coords) {
1743  UpdateVehicleViewportHash(this, this->coord.left, this->coord.top, INVALID_COORD, INVALID_COORD);
1744  } else {
1745  UpdateVehicleViewportHash(this, this->coord.left, this->coord.top, this->sprite_cache.old_coord.left, this->sprite_cache.old_coord.top);
1746  }
1747 
1748  if (dirty) {
1749  if (ignore_cached_coords) {
1751  } else {
1753  std::min(this->sprite_cache.old_coord.left, this->coord.left),
1754  std::min(this->sprite_cache.old_coord.top, this->coord.top),
1755  std::max(this->sprite_cache.old_coord.right, this->coord.right),
1756  std::max(this->sprite_cache.old_coord.bottom, this->coord.bottom));
1757  }
1758  }
1759 }
1760 
1765 {
1766  this->UpdatePosition();
1767  this->UpdateViewport(true);
1768 }
1769 
1775 {
1776  return ::MarkAllViewportsDirty(this->coord.left, this->coord.top, this->coord.right, this->coord.bottom);
1777 }
1778 
1785 {
1786  static const int8_t _delta_coord[16] = {
1787  -1,-1,-1, 0, 1, 1, 1, 0, /* x */
1788  -1, 0, 1, 1, 1, 0,-1,-1, /* y */
1789  };
1790 
1791  int x = v->x_pos + _delta_coord[v->direction];
1792  int y = v->y_pos + _delta_coord[v->direction + 8];
1793 
1795  gp.x = x;
1796  gp.y = y;
1797  gp.old_tile = v->tile;
1798  gp.new_tile = TileVirtXY(x, y);
1799  return gp;
1800 }
1801 
1802 static const Direction _new_direction_table[] = {
1803  DIR_N, DIR_NW, DIR_W,
1804  DIR_NE, DIR_SE, DIR_SW,
1805  DIR_E, DIR_SE, DIR_S
1806 };
1807 
1808 Direction GetDirectionTowards(const Vehicle *v, int x, int y)
1809 {
1810  int i = 0;
1811 
1812  if (y >= v->y_pos) {
1813  if (y != v->y_pos) i += 3;
1814  i += 3;
1815  }
1816 
1817  if (x >= v->x_pos) {
1818  if (x != v->x_pos) i++;
1819  i++;
1820  }
1821 
1822  Direction dir = v->direction;
1823 
1824  DirDiff dirdiff = DirDifference(_new_direction_table[i], dir);
1825  if (dirdiff == DIRDIFF_SAME) return dir;
1826  return ChangeDir(dir, dirdiff > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT);
1827 }
1828 
1839 {
1840  return _tile_type_procs[GetTileType(tile)]->vehicle_enter_tile_proc(v, tile, x, y);
1841 }
1842 
1849 {
1850  for (auto it = std::begin(this->used_bitmap); it != std::end(this->used_bitmap); ++it) {
1851  BitmapStorage available = ~(*it);
1852  if (available == 0) continue;
1853  return static_cast<UnitID>(std::distance(std::begin(this->used_bitmap), it) * BITMAP_SIZE + FindFirstBit(available) + 1);
1854  }
1855  return static_cast<UnitID>(this->used_bitmap.size() * BITMAP_SIZE + 1);
1856 }
1857 
1864 {
1865  if (index == 0 || index == UINT16_MAX) return index;
1866 
1867  index--;
1868 
1869  size_t slot = index / BITMAP_SIZE;
1870  if (slot >= this->used_bitmap.size()) this->used_bitmap.resize(slot + 1);
1871  SetBit(this->used_bitmap[index / BITMAP_SIZE], index % BITMAP_SIZE);
1872 
1873  return index + 1;
1874 }
1875 
1881 {
1882  if (index == 0 || index == UINT16_MAX) return;
1883 
1884  index--;
1885 
1886  assert(index / BITMAP_SIZE < this->used_bitmap.size());
1887  ClrBit(this->used_bitmap[index / BITMAP_SIZE], index % BITMAP_SIZE);
1888 }
1889 
1896 {
1897  /* Check whether it is allowed to build another vehicle. */
1898  uint max_veh;
1899  switch (type) {
1900  case VEH_TRAIN: max_veh = _settings_game.vehicle.max_trains; break;
1901  case VEH_ROAD: max_veh = _settings_game.vehicle.max_roadveh; break;
1902  case VEH_SHIP: max_veh = _settings_game.vehicle.max_ships; break;
1903  case VEH_AIRCRAFT: max_veh = _settings_game.vehicle.max_aircraft; break;
1904  default: NOT_REACHED();
1905  }
1906 
1908  if (c->group_all[type].num_vehicle >= max_veh) return UINT16_MAX; // Currently already at the limit, no room to make a new one.
1909 
1910  return c->freeunits[type].NextID();
1911 }
1912 
1913 
1922 bool CanBuildVehicleInfrastructure(VehicleType type, uint8_t subtype)
1923 {
1924  assert(IsCompanyBuildableVehicleType(type));
1925 
1926  if (!Company::IsValidID(_local_company)) return false;
1927 
1928  UnitID max;
1929  switch (type) {
1930  case VEH_TRAIN:
1931  if (!HasAnyRailTypesAvail(_local_company)) return false;
1933  break;
1934  case VEH_ROAD:
1935  if (!HasAnyRoadTypesAvail(_local_company, (RoadTramType)subtype)) return false;
1937  break;
1938  case VEH_SHIP: max = _settings_game.vehicle.max_ships; break;
1939  case VEH_AIRCRAFT: max = _settings_game.vehicle.max_aircraft; break;
1940  default: NOT_REACHED();
1941  }
1942 
1943  /* We can build vehicle infrastructure when we may build the vehicle type */
1944  if (max > 0) {
1945  /* Can we actually build the vehicle type? */
1946  for (const Engine *e : Engine::IterateType(type)) {
1947  if (type == VEH_ROAD && GetRoadTramType(e->u.road.roadtype) != (RoadTramType)subtype) continue;
1948  if (HasBit(e->company_avail, _local_company)) return true;
1949  }
1950  return false;
1951  }
1952 
1953  /* We should be able to build infrastructure when we have the actual vehicle type */
1954  for (const Vehicle *v : Vehicle::Iterate()) {
1955  if (v->type == VEH_ROAD && GetRoadTramType(RoadVehicle::From(v)->roadtype) != (RoadTramType)subtype) continue;
1956  if (v->owner == _local_company && v->type == type) return true;
1957  }
1958 
1959  return false;
1960 }
1961 
1962 
1970 LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_type, const Vehicle *v)
1971 {
1972  CargoID cargo_type = v == nullptr ? INVALID_CARGO : v->cargo_type;
1973  const Engine *e = Engine::Get(engine_type);
1974  switch (e->type) {
1975  default: NOT_REACHED();
1976  case VEH_TRAIN:
1977  if (v != nullptr && parent_engine_type != INVALID_ENGINE && (UsesWagonOverride(v) || (v->IsArticulatedPart() && e->u.rail.railveh_type != RAILVEH_WAGON))) {
1978  /* Wagonoverrides use the colour scheme of the front engine.
1979  * Articulated parts use the colour scheme of the first part. (Not supported for articulated wagons) */
1980  engine_type = parent_engine_type;
1981  e = Engine::Get(engine_type);
1982  /* Note: Luckily cargo_type is not needed for engines */
1983  }
1984 
1985  if (!IsValidCargoID(cargo_type)) cargo_type = e->GetDefaultCargoType();
1986  if (!IsValidCargoID(cargo_type)) cargo_type = GetCargoIDByLabel(CT_GOODS); // The vehicle does not carry anything, let's pick some freight cargo
1987  assert(IsValidCargoID(cargo_type));
1988  if (e->u.rail.railveh_type == RAILVEH_WAGON) {
1989  if (!CargoSpec::Get(cargo_type)->is_freight) {
1990  if (parent_engine_type == INVALID_ENGINE) {
1991  return LS_PASSENGER_WAGON_STEAM;
1992  } else {
1993  bool is_mu = HasBit(EngInfo(parent_engine_type)->misc_flags, EF_RAIL_IS_MU);
1994  switch (RailVehInfo(parent_engine_type)->engclass) {
1995  default: NOT_REACHED();
1996  case EC_STEAM: return LS_PASSENGER_WAGON_STEAM;
1997  case EC_DIESEL: return is_mu ? LS_DMU : LS_PASSENGER_WAGON_DIESEL;
1998  case EC_ELECTRIC: return is_mu ? LS_EMU : LS_PASSENGER_WAGON_ELECTRIC;
1999  case EC_MONORAIL: return LS_PASSENGER_WAGON_MONORAIL;
2000  case EC_MAGLEV: return LS_PASSENGER_WAGON_MAGLEV;
2001  }
2002  }
2003  } else {
2004  return LS_FREIGHT_WAGON;
2005  }
2006  } else {
2007  bool is_mu = HasBit(e->info.misc_flags, EF_RAIL_IS_MU);
2008 
2009  switch (e->u.rail.engclass) {
2010  default: NOT_REACHED();
2011  case EC_STEAM: return LS_STEAM;
2012  case EC_DIESEL: return is_mu ? LS_DMU : LS_DIESEL;
2013  case EC_ELECTRIC: return is_mu ? LS_EMU : LS_ELECTRIC;
2014  case EC_MONORAIL: return LS_MONORAIL;
2015  case EC_MAGLEV: return LS_MAGLEV;
2016  }
2017  }
2018 
2019  case VEH_ROAD:
2020  /* Always use the livery of the front */
2021  if (v != nullptr && parent_engine_type != INVALID_ENGINE) {
2022  engine_type = parent_engine_type;
2023  e = Engine::Get(engine_type);
2024  cargo_type = v->First()->cargo_type;
2025  }
2026  if (!IsValidCargoID(cargo_type)) cargo_type = e->GetDefaultCargoType();
2027  if (!IsValidCargoID(cargo_type)) cargo_type = GetCargoIDByLabel(CT_GOODS); // The vehicle does not carry anything, let's pick some freight cargo
2028  assert(IsValidCargoID(cargo_type));
2029 
2030  /* Important: Use Tram Flag of front part. Luckily engine_type refers to the front part here. */
2031  if (HasBit(e->info.misc_flags, EF_ROAD_TRAM)) {
2032  /* Tram */
2033  return IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_TRAM : LS_FREIGHT_TRAM;
2034  } else {
2035  /* Bus or truck */
2036  return IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_BUS : LS_TRUCK;
2037  }
2038 
2039  case VEH_SHIP:
2040  if (!IsValidCargoID(cargo_type)) cargo_type = e->GetDefaultCargoType();
2041  if (!IsValidCargoID(cargo_type)) cargo_type = GetCargoIDByLabel(CT_GOODS); // The vehicle does not carry anything, let's pick some freight cargo
2042  assert(IsValidCargoID(cargo_type));
2043  return IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_SHIP : LS_FREIGHT_SHIP;
2044 
2045  case VEH_AIRCRAFT:
2046  switch (e->u.air.subtype) {
2047  case AIR_HELI: return LS_HELICOPTER;
2048  case AIR_CTOL: return LS_SMALL_PLANE;
2049  case AIR_CTOL | AIR_FAST: return LS_LARGE_PLANE;
2050  default: NOT_REACHED();
2051  }
2052  }
2053 }
2054 
2064 const Livery *GetEngineLivery(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v, uint8_t livery_setting)
2065 {
2066  const Company *c = Company::Get(company);
2067  LiveryScheme scheme = LS_DEFAULT;
2068 
2069  if (livery_setting == LIT_ALL || (livery_setting == LIT_COMPANY && company == _local_company)) {
2070  if (v != nullptr) {
2071  const Group *g = Group::GetIfValid(v->First()->group_id);
2072  if (g != nullptr) {
2073  /* Traverse parents until we find a livery or reach the top */
2074  while (g->livery.in_use == 0 && g->parent != INVALID_GROUP) {
2075  g = Group::Get(g->parent);
2076  }
2077  if (g->livery.in_use != 0) return &g->livery;
2078  }
2079  }
2080 
2081  /* The default livery is always available for use, but its in_use flag determines
2082  * whether any _other_ liveries are in use. */
2083  if (c->livery[LS_DEFAULT].in_use != 0) {
2084  /* Determine the livery scheme to use */
2085  scheme = GetEngineLiveryScheme(engine_type, parent_engine_type, v);
2086  }
2087  }
2088 
2089  return &c->livery[scheme];
2090 }
2091 
2092 
2093 static PaletteID GetEngineColourMap(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v)
2094 {
2095  PaletteID map = (v != nullptr) ? v->colourmap : PAL_NONE;
2096 
2097  /* Return cached value if any */
2098  if (map != PAL_NONE) return map;
2099 
2100  const Engine *e = Engine::Get(engine_type);
2101 
2102  /* Check if we should use the colour map callback */
2104  uint16_t callback = GetVehicleCallback(CBID_VEHICLE_COLOUR_MAPPING, 0, 0, engine_type, v);
2105  /* Failure means "use the default two-colour" */
2106  if (callback != CALLBACK_FAILED) {
2107  static_assert(PAL_NONE == 0); // Returning 0x4000 (resp. 0xC000) coincidences with default value (PAL_NONE)
2108  map = GB(callback, 0, 14);
2109  /* If bit 14 is set, then the company colours are applied to the
2110  * map else it's returned as-is. */
2111  if (!HasBit(callback, 14)) {
2112  /* Update cache */
2113  if (v != nullptr) const_cast<Vehicle *>(v)->colourmap = map;
2114  return map;
2115  }
2116  }
2117  }
2118 
2119  bool twocc = HasBit(e->info.misc_flags, EF_USES_2CC);
2120 
2121  if (map == PAL_NONE) map = twocc ? (PaletteID)SPR_2CCMAP_BASE : (PaletteID)PALETTE_RECOLOUR_START;
2122 
2123  /* Spectator has news shown too, but has invalid company ID - as well as dedicated server */
2124  if (!Company::IsValidID(company)) return map;
2125 
2126  const Livery *livery = GetEngineLivery(engine_type, company, parent_engine_type, v, _settings_client.gui.liveries);
2127 
2128  map += livery->colour1;
2129  if (twocc) map += livery->colour2 * 16;
2130 
2131  /* Update cache */
2132  if (v != nullptr) const_cast<Vehicle *>(v)->colourmap = map;
2133  return map;
2134 }
2135 
2143 {
2144  return GetEngineColourMap(engine_type, company, INVALID_ENGINE, nullptr);
2145 }
2146 
2153 {
2154  if (v->IsGroundVehicle()) {
2155  return GetEngineColourMap(v->engine_type, v->owner, v->GetGroundVehicleCache()->first_engine, v);
2156  }
2157 
2158  return GetEngineColourMap(v->engine_type, v->owner, INVALID_ENGINE, v);
2159 }
2160 
2165 {
2166  if (this->IsGroundVehicle()) {
2167  uint16_t &gv_flags = this->GetGroundVehicleFlags();
2168  if (HasBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS)) {
2169  /* Do not delete orders, only skip them */
2172  InvalidateVehicleOrder(this, 0);
2173  return;
2174  }
2175  }
2176 
2177  const Order *order = this->GetOrder(this->cur_implicit_order_index);
2178  while (order != nullptr) {
2179  if (this->cur_implicit_order_index == this->cur_real_order_index) break;
2180 
2181  if (order->IsType(OT_IMPLICIT)) {
2183  /* DeleteOrder does various magic with order_indices, so resync 'order' with 'cur_implicit_order_index' */
2184  order = this->GetOrder(this->cur_implicit_order_index);
2185  } else {
2186  /* Skip non-implicit orders, e.g. service-orders */
2187  order = order->next;
2188  this->cur_implicit_order_index++;
2189  }
2190 
2191  /* Wrap around */
2192  if (order == nullptr) {
2193  order = this->GetOrder(0);
2194  this->cur_implicit_order_index = 0;
2195  }
2196  }
2197 }
2198 
2204 {
2205  assert(IsTileType(this->tile, MP_STATION) || this->type == VEH_SHIP);
2206 
2208  if (this->current_order.IsType(OT_GOTO_STATION) &&
2209  this->current_order.GetDestination() == this->last_station_visited) {
2211 
2212  /* Now both order indices point to the destination station, and we can start loading */
2213  this->current_order.MakeLoading(true);
2214  UpdateVehicleTimetable(this, true);
2215 
2216  /* Furthermore add the Non Stop flag to mark that this station
2217  * is the actual destination of the vehicle, which is (for example)
2218  * necessary to be known for HandleTrainLoading to determine
2219  * whether the train is lost or not; not marking a train lost
2220  * that arrives at random stations is bad. */
2222 
2223  } else {
2224  /* We weren't scheduled to stop here. Insert an implicit order
2225  * to show that we are stopping here.
2226  * While only groundvehicles have implicit orders, e.g. aircraft might still enter
2227  * the 'wrong' terminal when skipping orders etc. */
2228  Order *in_list = this->GetOrder(this->cur_implicit_order_index);
2229  if (this->IsGroundVehicle() &&
2230  (in_list == nullptr || !in_list->IsType(OT_IMPLICIT) ||
2231  in_list->GetDestination() != this->last_station_visited)) {
2232  bool suppress_implicit_orders = HasBit(this->GetGroundVehicleFlags(), GVF_SUPPRESS_IMPLICIT_ORDERS);
2233  /* Do not create consecutive duplicates of implicit orders */
2234  Order *prev_order = this->cur_implicit_order_index > 0 ? this->GetOrder(this->cur_implicit_order_index - 1) : (this->GetNumOrders() > 1 ? this->GetLastOrder() : nullptr);
2235  if (prev_order == nullptr ||
2236  (!prev_order->IsType(OT_IMPLICIT) && !prev_order->IsType(OT_GOTO_STATION)) ||
2237  prev_order->GetDestination() != this->last_station_visited) {
2238 
2239  /* Prefer deleting implicit orders instead of inserting new ones,
2240  * so test whether the right order follows later. In case of only
2241  * implicit orders treat the last order in the list like an
2242  * explicit one, except if the overall number of orders surpasses
2243  * IMPLICIT_ORDER_ONLY_CAP. */
2244  int target_index = this->cur_implicit_order_index;
2245  bool found = false;
2246  while (target_index != this->cur_real_order_index || this->GetNumManualOrders() == 0) {
2247  const Order *order = this->GetOrder(target_index);
2248  if (order == nullptr) break; // No orders.
2249  if (order->IsType(OT_IMPLICIT) && order->GetDestination() == this->last_station_visited) {
2250  found = true;
2251  break;
2252  }
2253  target_index++;
2254  if (target_index >= this->orders->GetNumOrders()) {
2255  if (this->GetNumManualOrders() == 0 &&
2257  break;
2258  }
2259  target_index = 0;
2260  }
2261  if (target_index == this->cur_implicit_order_index) break; // Avoid infinite loop.
2262  }
2263 
2264  if (found) {
2265  if (suppress_implicit_orders) {
2266  /* Skip to the found order */
2267  this->cur_implicit_order_index = target_index;
2268  InvalidateVehicleOrder(this, 0);
2269  } else {
2270  /* Delete all implicit orders up to the station we just reached */
2271  const Order *order = this->GetOrder(this->cur_implicit_order_index);
2272  while (!order->IsType(OT_IMPLICIT) || order->GetDestination() != this->last_station_visited) {
2273  if (order->IsType(OT_IMPLICIT)) {
2275  /* DeleteOrder does various magic with order_indices, so resync 'order' with 'cur_implicit_order_index' */
2276  order = this->GetOrder(this->cur_implicit_order_index);
2277  } else {
2278  /* Skip non-implicit orders, e.g. service-orders */
2279  order = order->next;
2280  this->cur_implicit_order_index++;
2281  }
2282 
2283  /* Wrap around */
2284  if (order == nullptr) {
2285  order = this->GetOrder(0);
2286  this->cur_implicit_order_index = 0;
2287  }
2288  assert(order != nullptr);
2289  }
2290  }
2291  } else if (!suppress_implicit_orders &&
2292  ((this->orders == nullptr ? OrderList::CanAllocateItem() : this->orders->GetNumOrders() < MAX_VEH_ORDER_ID)) &&
2294  /* Insert new implicit order */
2295  Order *implicit_order = new Order();
2296  implicit_order->MakeImplicit(this->last_station_visited);
2297  InsertOrder(this, implicit_order, this->cur_implicit_order_index);
2298  if (this->cur_implicit_order_index > 0) --this->cur_implicit_order_index;
2299 
2300  /* InsertOrder disabled creation of implicit orders for all vehicles with the same implicit order.
2301  * Reenable it for this vehicle */
2302  uint16_t &gv_flags = this->GetGroundVehicleFlags();
2304  }
2305  }
2306  }
2307  this->current_order.MakeLoading(false);
2308  }
2309 
2310  if (this->last_loading_station != INVALID_STATION &&
2311  this->last_loading_station != this->last_station_visited &&
2312  ((this->current_order.GetLoadType() & OLFB_NO_LOAD) == 0 ||
2313  (this->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0)) {
2314  IncreaseStats(Station::Get(this->last_loading_station), this, this->last_station_visited, travel_time);
2315  }
2316 
2317  PrepareUnload(this);
2318 
2323 
2325  this->cur_speed = 0;
2326  this->MarkDirty();
2327 }
2328 
2334 void Vehicle::CancelReservation(StationID next, Station *st)
2335 {
2336  for (Vehicle *v = this; v != nullptr; v = v->next) {
2339  Debug(misc, 1, "cancelling cargo reservation");
2340  cargo.Return(UINT_MAX, &st->goods[v->cargo_type].cargo, next, v->tile);
2341  }
2342  cargo.KeepAll();
2343  }
2344 }
2345 
2351 {
2352  assert(this->current_order.IsType(OT_LOADING));
2353 
2354  delete this->cargo_payment;
2355  assert(this->cargo_payment == nullptr); // cleared by ~CargoPayment
2356 
2357  /* Only update the timetable if the vehicle was supposed to stop here. */
2359 
2360  if ((this->current_order.GetLoadType() & OLFB_NO_LOAD) == 0 ||
2361  (this->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
2362  if (this->current_order.CanLeaveWithCargo(this->last_loading_station != INVALID_STATION)) {
2363  /* Refresh next hop stats to make sure we've done that at least once
2364  * during the stop and that refit_cap == cargo_cap for each vehicle in
2365  * the consist. */
2366  this->ResetRefitCaps();
2367  LinkRefresher::Run(this);
2368 
2369  /* if the vehicle could load here or could stop with cargo loaded set the last loading station */
2372  } else {
2373  /* if the vehicle couldn't load and had to unload or transfer everything
2374  * set the last loading station to invalid as it will leave empty. */
2375  this->last_loading_station = INVALID_STATION;
2376  }
2377  }
2378 
2381  this->CancelReservation(INVALID_STATION, st);
2382  st->loading_vehicles.remove(this);
2383 
2385  trip_occupancy = CalcPercentVehicleFilled(this, nullptr);
2386 
2387  if (this->type == VEH_TRAIN && !(this->vehstatus & VS_CRASHED)) {
2388  /* Trigger station animation (trains only) */
2389  if (IsTileType(this->tile, MP_STATION)) {
2391  TriggerStationAnimation(st, this->tile, SAT_TRAIN_DEPARTS);
2392  }
2393 
2394  SetBit(Train::From(this)->flags, VRF_LEAVING_STATION);
2395  }
2396  if (this->type == VEH_ROAD && !(this->vehstatus & VS_CRASHED)) {
2397  /* Trigger road stop animation */
2398  if (IsStationRoadStopTile(this->tile)) {
2400  TriggerRoadStopAnimation(st, this->tile, SAT_TRAIN_DEPARTS);
2401  }
2402  }
2403 
2404 
2405  this->MarkDirty();
2406 }
2407 
2412 {
2413  for (Vehicle *v = this; v != nullptr; v = v->Next()) v->refit_cap = v->cargo_cap;
2414 }
2415 
2420 {
2421  Company::Get(this->owner)->freeunits[this->type].ReleaseID(this->unitnumber);
2422  this->unitnumber = 0;
2423 }
2424 
2430 void Vehicle::HandleLoading(bool mode)
2431 {
2432  switch (this->current_order.GetType()) {
2433  case OT_LOADING: {
2434  TimerGameTick::Ticks wait_time = std::max(this->current_order.GetTimetabledWait() - this->lateness_counter, 0);
2435 
2436  /* Not the first call for this tick, or still loading */
2437  if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) || this->current_order_time < wait_time) return;
2438 
2439  this->PlayLeaveStationSound();
2440 
2441  this->LeaveStation();
2442 
2443  /* Only advance to next order if we just loaded at the current one */
2444  const Order *order = this->GetOrder(this->cur_implicit_order_index);
2445  if (order == nullptr ||
2446  (!order->IsType(OT_IMPLICIT) && !order->IsType(OT_GOTO_STATION)) ||
2447  order->GetDestination() != this->last_station_visited) {
2448  return;
2449  }
2450  break;
2451  }
2452 
2453  case OT_DUMMY: break;
2454 
2455  default: return;
2456  }
2457 
2459 }
2460 
2466 {
2467  for (Order *o : this->Orders()) {
2468  if (o->IsType(OT_GOTO_STATION) && o->GetLoadType() & (OLFB_FULL_LOAD | OLF_FULL_LOAD_ANY)) return true;
2469  }
2470  return false;
2471 }
2472 
2478 {
2479  for (Order *o : this->Orders()) {
2480  if (o->IsType(OT_CONDITIONAL)) return true;
2481  }
2482  return false;
2483 }
2484 
2490 {
2491  for (Order *o : this->Orders()) {
2492  if (o->IsType(OT_GOTO_DEPOT) && o->GetDepotActionType() & ODATFB_UNBUNCH) return true;
2493  }
2494  return false;
2495 }
2496 
2501 static bool PreviousOrderIsUnbunching(const Vehicle *v)
2502 {
2503  /* If we are headed for the first order, we must wrap around back to the last order. */
2504  bool is_first_order = (v->GetOrder(v->cur_implicit_order_index) == v->GetFirstOrder());
2505  Order *previous_order = (is_first_order) ? v->GetLastOrder() : v->GetOrder(v->cur_implicit_order_index - 1);
2506 
2507  if (previous_order == nullptr || !previous_order->IsType(OT_GOTO_DEPOT)) return false;
2508  return (previous_order->GetDepotActionType() & ODATFB_UNBUNCH) != 0;
2509 }
2510 
2515 {
2516  /* Don't do anything if this is not our unbunching order. */
2517  if (!PreviousOrderIsUnbunching(this)) return;
2518 
2519  /* Set the start point for this round trip time. */
2521 
2522  /* Tell the timetable we are now "on time." */
2523  this->lateness_counter = 0;
2525 
2526  /* Find the average travel time of vehicles that we share orders with. */
2527  int num_vehicles = 0;
2528  TimerGameTick::Ticks total_travel_time = 0;
2529 
2530  Vehicle *u = this->FirstShared();
2531  for (; u != nullptr; u = u->NextShared()) {
2532  /* Ignore vehicles that are manually stopped or crashed. */
2533  if (u->vehstatus & (VS_STOPPED | VS_CRASHED)) continue;
2534 
2535  num_vehicles++;
2536  total_travel_time += u->round_trip_time;
2537  }
2538 
2539  /* Make sure we cannot divide by 0. */
2540  num_vehicles = std::max(num_vehicles, 1);
2541 
2542  /* Calculate the separation by finding the average travel time, then calculating equal separation (minimum 1 tick) between vehicles. */
2543  TimerGameTick::Ticks separation = std::max((total_travel_time / num_vehicles / num_vehicles), 1);
2544  TimerGameTick::TickCounter next_departure = TimerGameTick::counter + separation;
2545 
2546  /* Set the departure time of all vehicles that we share orders with. */
2547  u = this->FirstShared();
2548  for (; u != nullptr; u = u->NextShared()) {
2549  /* Ignore vehicles that are manually stopped or crashed. */
2550  if (u->vehstatus & (VS_STOPPED | VS_CRASHED)) continue;
2551 
2552  u->depot_unbunching_next_departure = next_departure;
2554  }
2555 }
2556 
2562 {
2563  assert(this->IsInDepot());
2564 
2565  /* Don't bother if there are no vehicles sharing orders. */
2566  if (!this->IsOrderListShared()) return false;
2567 
2568  /* Don't do anything if there aren't enough orders. */
2569  if (this->GetNumOrders() <= 1) return false;
2570 
2571  /* Don't do anything if this is not our unbunching order. */
2572  if (!PreviousOrderIsUnbunching(this)) return false;
2573 
2575 };
2576 
2584 {
2585  CommandCost ret = CheckOwnership(this->owner);
2586  if (ret.Failed()) return ret;
2587 
2588  if (this->vehstatus & VS_CRASHED) return CMD_ERROR;
2589  if (this->IsStoppedInDepot()) return CMD_ERROR;
2590 
2591  /* No matter why we're headed to the depot, unbunching data is no longer valid. */
2592  if (flags & DC_EXEC) this->ResetDepotUnbunching();
2593 
2594  if (this->current_order.IsType(OT_GOTO_DEPOT)) {
2595  bool halt_in_depot = (this->current_order.GetDepotActionType() & ODATFB_HALT) != 0;
2596  if (HasFlag(command, DepotCommand::Service) == halt_in_depot) {
2597  /* We called with a different DEPOT_SERVICE setting.
2598  * Now we change the setting to apply the new one and let the vehicle head for the same depot.
2599  * Note: the if is (true for requesting service == true for ordered to stop in depot) */
2600  if (flags & DC_EXEC) {
2604  }
2605  return CommandCost();
2606  }
2607 
2608  if (HasFlag(command, DepotCommand::DontCancel)) return CMD_ERROR; // Requested no cancellation of depot orders
2609  if (flags & DC_EXEC) {
2610  /* If the orders to 'goto depot' are in the orders list (forced servicing),
2611  * then skip to the next order; effectively cancelling this forced service */
2613 
2614  if (this->IsGroundVehicle()) {
2615  uint16_t &gv_flags = this->GetGroundVehicleFlags();
2617  }
2618 
2619  this->current_order.MakeDummy();
2621  }
2622  return CommandCost();
2623  }
2624 
2625  ClosestDepot closestDepot = this->FindClosestDepot();
2626  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};
2627  if (!closestDepot.found) return_cmd_error(no_depot[this->type]);
2628 
2629  if (flags & DC_EXEC) {
2630  if (this->current_order.IsType(OT_LOADING)) this->LeaveStation();
2631 
2632  if (this->IsGroundVehicle() && this->GetNumManualOrders() > 0) {
2633  uint16_t &gv_flags = this->GetGroundVehicleFlags();
2635  }
2636 
2637  this->SetDestTile(closestDepot.location);
2638  this->current_order.MakeGoToDepot(closestDepot.destination, ODTF_MANUAL);
2641 
2642  /* If there is no depot in front and the train is not already reversing, reverse automatically (trains only) */
2643  if (this->type == VEH_TRAIN && (closestDepot.reverse ^ HasBit(Train::From(this)->flags, VRF_REVERSING))) {
2645  }
2646 
2647  if (this->type == VEH_AIRCRAFT) {
2648  Aircraft *a = Aircraft::From(this);
2649  if (a->state == FLYING && a->targetairport != closestDepot.destination) {
2650  /* The aircraft is now heading for a different hangar than the next in the orders */
2652  }
2653  }
2654  }
2655 
2656  return CommandCost();
2657 
2658 }
2659 
2664 void Vehicle::UpdateVisualEffect(bool allow_power_change)
2665 {
2666  bool powered_before = HasBit(this->vcache.cached_vis_effect, VE_DISABLE_WAGON_POWER);
2667  const Engine *e = this->GetEngine();
2668 
2669  /* Evaluate properties */
2670  uint8_t visual_effect;
2671  switch (e->type) {
2672  case VEH_TRAIN: visual_effect = e->u.rail.visual_effect; break;
2673  case VEH_ROAD: visual_effect = e->u.road.visual_effect; break;
2674  case VEH_SHIP: visual_effect = e->u.ship.visual_effect; break;
2675  default: visual_effect = 1 << VE_DISABLE_EFFECT; break;
2676  }
2677 
2678  /* Check powered wagon / visual effect callback */
2680  uint16_t callback = GetVehicleCallback(CBID_VEHICLE_VISUAL_EFFECT, 0, 0, this->engine_type, this);
2681 
2682  if (callback != CALLBACK_FAILED) {
2683  if (callback >= 0x100 && e->GetGRF()->grf_version >= 8) ErrorUnknownCallbackResult(e->GetGRFID(), CBID_VEHICLE_VISUAL_EFFECT, callback);
2684 
2685  callback = GB(callback, 0, 8);
2686  /* Avoid accidentally setting 'visual_effect' to the default value
2687  * Since bit 6 (disable effects) is set anyways, we can safely erase some bits. */
2688  if (callback == VE_DEFAULT) {
2689  assert(HasBit(callback, VE_DISABLE_EFFECT));
2690  SB(callback, VE_TYPE_START, VE_TYPE_COUNT, 0);
2691  }
2692  visual_effect = callback;
2693  }
2694  }
2695 
2696  /* Apply default values */
2697  if (visual_effect == VE_DEFAULT ||
2698  (!HasBit(visual_effect, VE_DISABLE_EFFECT) && GB(visual_effect, VE_TYPE_START, VE_TYPE_COUNT) == VE_TYPE_DEFAULT)) {
2699  /* Only train engines have default effects.
2700  * Note: This is independent of whether the engine is a front engine or articulated part or whatever. */
2701  if (e->type != VEH_TRAIN || e->u.rail.railveh_type == RAILVEH_WAGON || !IsInsideMM(e->u.rail.engclass, EC_STEAM, EC_MONORAIL)) {
2702  if (visual_effect == VE_DEFAULT) {
2703  visual_effect = 1 << VE_DISABLE_EFFECT;
2704  } else {
2705  SetBit(visual_effect, VE_DISABLE_EFFECT);
2706  }
2707  } else {
2708  if (visual_effect == VE_DEFAULT) {
2709  /* Also set the offset */
2710  visual_effect = (VE_OFFSET_CENTRE - (e->u.rail.engclass == EC_STEAM ? 4 : 0)) << VE_OFFSET_START;
2711  }
2712  SB(visual_effect, VE_TYPE_START, VE_TYPE_COUNT, e->u.rail.engclass - EC_STEAM + VE_TYPE_STEAM);
2713  }
2714  }
2715 
2716  this->vcache.cached_vis_effect = visual_effect;
2717 
2718  if (!allow_power_change && powered_before != HasBit(this->vcache.cached_vis_effect, VE_DISABLE_WAGON_POWER)) {
2720  ShowNewGrfVehicleError(this->engine_type, STR_NEWGRF_BROKEN, STR_NEWGRF_BROKEN_POWERED_WAGON, GBUG_VEH_POWERED_WAGON, false);
2721  }
2722 }
2723 
2724 static const int8_t _vehicle_smoke_pos[8] = {
2725  1, 1, 1, 0, -1, -1, -1, 0
2726 };
2727 
2732 static void SpawnAdvancedVisualEffect(const Vehicle *v)
2733 {
2734  uint16_t callback = GetVehicleCallback(CBID_VEHICLE_SPAWN_VISUAL_EFFECT, 0, Random(), v->engine_type, v);
2735  if (callback == CALLBACK_FAILED) return;
2736 
2737  uint count = GB(callback, 0, 2);
2738  bool auto_center = HasBit(callback, 13);
2739  bool auto_rotate = !HasBit(callback, 14);
2740 
2741  int8_t l_center = 0;
2742  if (auto_center) {
2743  /* For road vehicles: Compute offset from vehicle position to vehicle center */
2744  if (v->type == VEH_ROAD) l_center = -(int)(VEHICLE_LENGTH - RoadVehicle::From(v)->gcache.cached_veh_length) / 2;
2745  } else {
2746  /* For trains: Compute offset from vehicle position to sprite position */
2747  if (v->type == VEH_TRAIN) l_center = (VEHICLE_LENGTH - Train::From(v)->gcache.cached_veh_length) / 2;
2748  }
2749 
2750  Direction l_dir = v->direction;
2751  if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_REVERSE_DIRECTION)) l_dir = ReverseDir(l_dir);
2752  Direction t_dir = ChangeDir(l_dir, DIRDIFF_90RIGHT);
2753 
2754  int8_t x_center = _vehicle_smoke_pos[l_dir] * l_center;
2755  int8_t y_center = _vehicle_smoke_pos[t_dir] * l_center;
2756 
2757  for (uint i = 0; i < count; i++) {
2758  uint32_t reg = GetRegister(0x100 + i);
2759  uint type = GB(reg, 0, 8);
2760  int8_t x = GB(reg, 8, 8);
2761  int8_t y = GB(reg, 16, 8);
2762  int8_t z = GB(reg, 24, 8);
2763 
2764  if (auto_rotate) {
2765  int8_t l = x;
2766  int8_t t = y;
2767  x = _vehicle_smoke_pos[l_dir] * l + _vehicle_smoke_pos[t_dir] * t;
2768  y = _vehicle_smoke_pos[t_dir] * l - _vehicle_smoke_pos[l_dir] * t;
2769  }
2770 
2771  if (type >= 0xF0) {
2772  switch (type) {
2773  case 0xF1: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_STEAM_SMOKE); break;
2774  case 0xF2: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_DIESEL_SMOKE); break;
2775  case 0xF3: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_ELECTRIC_SPARK); break;
2776  case 0xFA: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_BREAKDOWN_SMOKE_AIRCRAFT); break;
2777  default: break;
2778  }
2779  }
2780  }
2781 }
2782 
2788 {
2789  assert(this->IsPrimaryVehicle());
2790  bool sound = false;
2791 
2792  /* Do not show any smoke when:
2793  * - vehicle smoke is disabled by the player
2794  * - the vehicle is slowing down or stopped (by the player)
2795  * - the vehicle is moving very slowly
2796  */
2797  if (_settings_game.vehicle.smoke_amount == 0 ||
2798  this->vehstatus & (VS_TRAIN_SLOWING | VS_STOPPED) ||
2799  this->cur_speed < 2) {
2800  return;
2801  }
2802 
2803  /* Use the speed as limited by underground and orders. */
2804  uint max_speed = this->GetCurrentMaxSpeed();
2805 
2806  if (this->type == VEH_TRAIN) {
2807  const Train *t = Train::From(this);
2808  /* For trains, do not show any smoke when:
2809  * - the train is reversing
2810  * - is entering a station with an order to stop there and its speed is equal to maximum station entering speed
2811  */
2812  if (HasBit(t->flags, VRF_REVERSING) ||
2814  t->cur_speed >= max_speed)) {
2815  return;
2816  }
2817  }
2818 
2819  const Vehicle *v = this;
2820 
2821  do {
2822  bool advanced = HasBit(v->vcache.cached_vis_effect, VE_ADVANCED_EFFECT);
2824  VisualEffectSpawnModel effect_model = VESM_NONE;
2825  if (advanced) {
2826  effect_offset = VE_OFFSET_CENTRE;
2828  if (effect_model >= VESM_END) effect_model = VESM_NONE; // unknown spawning model
2829  } else {
2831  assert(effect_model != (VisualEffectSpawnModel)VE_TYPE_DEFAULT); // should have been resolved by UpdateVisualEffect
2832  static_assert((uint)VESM_STEAM == (uint)VE_TYPE_STEAM);
2833  static_assert((uint)VESM_DIESEL == (uint)VE_TYPE_DIESEL);
2834  static_assert((uint)VESM_ELECTRIC == (uint)VE_TYPE_ELECTRIC);
2835  }
2836 
2837  /* Show no smoke when:
2838  * - Smoke has been disabled for this vehicle
2839  * - The vehicle is not visible
2840  * - The vehicle is under a bridge
2841  * - The vehicle is on a depot tile
2842  * - The vehicle is on a tunnel tile
2843  * - The vehicle is a train engine that is currently unpowered */
2844  if (effect_model == VESM_NONE ||
2845  v->vehstatus & VS_HIDDEN ||
2846  IsBridgeAbove(v->tile) ||
2847  IsDepotTile(v->tile) ||
2848  IsTunnelTile(v->tile) ||
2849  (v->type == VEH_TRAIN &&
2850  !HasPowerOnRail(Train::From(v)->railtype, GetTileRailType(v->tile)))) {
2851  continue;
2852  }
2853 
2854  EffectVehicleType evt = EV_END;
2855  switch (effect_model) {
2856  case VESM_STEAM:
2857  /* Steam smoke - amount is gradually falling until vehicle reaches its maximum speed, after that it's normal.
2858  * Details: while vehicle's current speed is gradually increasing, steam plumes' density decreases by one third each
2859  * third of its maximum speed spectrum. Steam emission finally normalises at very close to vehicle's maximum speed.
2860  * REGULATION:
2861  * - instead of 1, 4 / 2^smoke_amount (max. 2) is used to provide sufficient regulation to steam puffs' amount. */
2862  if (GB(v->tick_counter, 0, ((4 >> _settings_game.vehicle.smoke_amount) + ((this->cur_speed * 3) / max_speed))) == 0) {
2863  evt = EV_STEAM_SMOKE;
2864  }
2865  break;
2866 
2867  case VESM_DIESEL: {
2868  /* Diesel smoke - thicker when vehicle is starting, gradually subsiding till it reaches its maximum speed
2869  * when smoke emission stops.
2870  * Details: Vehicle's (max.) speed spectrum is divided into 32 parts. When max. speed is reached, chance for smoke
2871  * emission erodes by 32 (1/4). For trains, power and weight come in handy too to either increase smoke emission in
2872  * 6 steps (1000HP each) if the power is low or decrease smoke emission in 6 steps (512 tonnes each) if the train
2873  * isn't overweight. Power and weight contributions are expressed in a way that neither extreme power, nor
2874  * extreme weight can ruin the balance (e.g. FreightWagonMultiplier) in the formula. When the vehicle reaches
2875  * maximum speed no diesel_smoke is emitted.
2876  * REGULATION:
2877  * - up to which speed a diesel vehicle is emitting smoke (with reduced/small setting only until 1/2 of max_speed),
2878  * - in Chance16 - the last value is 512 / 2^smoke_amount (max. smoke when 128 = smoke_amount of 2). */
2879  int power_weight_effect = 0;
2880  if (v->type == VEH_TRAIN) {
2881  power_weight_effect = (32 >> (Train::From(this)->gcache.cached_power >> 10)) - (32 >> (Train::From(this)->gcache.cached_weight >> 9));
2882  }
2883  if (this->cur_speed < (max_speed >> (2 >> _settings_game.vehicle.smoke_amount)) &&
2884  Chance16((64 - ((this->cur_speed << 5) / max_speed) + power_weight_effect), (512 >> _settings_game.vehicle.smoke_amount))) {
2885  evt = EV_DIESEL_SMOKE;
2886  }
2887  break;
2888  }
2889 
2890  case VESM_ELECTRIC:
2891  /* Electric train's spark - more often occurs when train is departing (more load)
2892  * Details: Electric locomotives are usually at least twice as powerful as their diesel counterparts, so spark
2893  * emissions are kept simple. Only when starting, creating huge force are sparks more likely to happen, but when
2894  * reaching its max. speed, quarter by quarter of it, chance decreases until the usual 2,22% at train's top speed.
2895  * REGULATION:
2896  * - in Chance16 the last value is 360 / 2^smoke_amount (max. sparks when 90 = smoke_amount of 2). */
2897  if (GB(v->tick_counter, 0, 2) == 0 &&
2898  Chance16((6 - ((this->cur_speed << 2) / max_speed)), (360 >> _settings_game.vehicle.smoke_amount))) {
2899  evt = EV_ELECTRIC_SPARK;
2900  }
2901  break;
2902 
2903  default:
2904  NOT_REACHED();
2905  }
2906 
2907  if (evt != EV_END && advanced) {
2908  sound = true;
2910  } else if (evt != EV_END) {
2911  sound = true;
2912 
2913  /* The effect offset is relative to a point 4 units behind the vehicle's
2914  * front (which is the center of an 8/8 vehicle). Shorter vehicles need a
2915  * correction factor. */
2916  if (v->type == VEH_TRAIN) effect_offset += (VEHICLE_LENGTH - Train::From(v)->gcache.cached_veh_length) / 2;
2917 
2918  int x = _vehicle_smoke_pos[v->direction] * effect_offset;
2919  int y = _vehicle_smoke_pos[(v->direction + 2) % 8] * effect_offset;
2920 
2921  if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_REVERSE_DIRECTION)) {
2922  x = -x;
2923  y = -y;
2924  }
2925 
2926  CreateEffectVehicleRel(v, x, y, 10, evt);
2927  }
2928  } while ((v = v->Next()) != nullptr);
2929 
2930  if (sound) PlayVehicleSound(this, VSE_VISUAL_EFFECT);
2931 }
2932 
2938 {
2939  assert(this != next);
2940 
2941  if (this->next != nullptr) {
2942  /* We had an old next vehicle. Update the first and previous pointers */
2943  for (Vehicle *v = this->next; v != nullptr; v = v->Next()) {
2944  v->first = this->next;
2945  }
2946  this->next->previous = nullptr;
2947  }
2948 
2949  this->next = next;
2950 
2951  if (this->next != nullptr) {
2952  /* A new next vehicle. Update the first and previous pointers */
2953  if (this->next->previous != nullptr) this->next->previous->next = nullptr;
2954  this->next->previous = this;
2955  for (Vehicle *v = this->next; v != nullptr; v = v->Next()) {
2956  v->first = this->first;
2957  }
2958  }
2959 }
2960 
2966 void Vehicle::AddToShared(Vehicle *shared_chain)
2967 {
2968  assert(this->previous_shared == nullptr && this->next_shared == nullptr);
2969 
2970  if (shared_chain->orders == nullptr) {
2971  assert(shared_chain->previous_shared == nullptr);
2972  assert(shared_chain->next_shared == nullptr);
2973  this->orders = shared_chain->orders = new OrderList(nullptr, shared_chain);
2974  }
2975 
2976  this->next_shared = shared_chain->next_shared;
2977  this->previous_shared = shared_chain;
2978 
2979  shared_chain->next_shared = this;
2980 
2981  if (this->next_shared != nullptr) this->next_shared->previous_shared = this;
2982 
2983  shared_chain->orders->AddVehicle(this);
2984 }
2985 
2990 {
2991  /* Remember if we were first and the old window number before RemoveVehicle()
2992  * as this changes first if needed. */
2993  bool were_first = (this->FirstShared() == this);
2994  VehicleListIdentifier vli(VL_SHARED_ORDERS, this->type, this->owner, this->FirstShared()->index);
2995 
2996  this->orders->RemoveVehicle(this);
2997 
2998  if (!were_first) {
2999  /* We are not the first shared one, so only relink our previous one. */
3000  this->previous_shared->next_shared = this->NextShared();
3001  }
3002 
3003  if (this->next_shared != nullptr) this->next_shared->previous_shared = this->previous_shared;
3004 
3005 
3006  if (this->orders->GetNumVehicles() == 1) {
3007  /* When there is only one vehicle, remove the shared order list window. */
3010  } else if (were_first) {
3011  /* If we were the first one, update to the new first one.
3012  * Note: FirstShared() is already the new first */
3013  InvalidateWindowData(GetWindowClassForVehicleType(this->type), vli.Pack(), this->FirstShared()->index | (1U << 31));
3014  }
3015 
3016  this->next_shared = nullptr;
3017  this->previous_shared = nullptr;
3018 }
3019 
3020 static IntervalTimer<TimerGameEconomy> _economy_vehicles_yearly({TimerGameEconomy::YEAR, TimerGameEconomy::Priority::VEHICLE}, [](auto)
3021 {
3022  for (Vehicle *v : Vehicle::Iterate()) {
3023  if (v->IsPrimaryVehicle()) {
3024  /* show warning if vehicle is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */
3025  Money profit = v->GetDisplayProfitThisYear();
3026  if (v->economy_age >= VEHICLE_PROFIT_MIN_AGE && profit < 0) {
3028  SetDParam(0, v->index);
3029  SetDParam(1, profit);
3031  TimerGameEconomy::UsingWallclockUnits() ? STR_NEWS_VEHICLE_UNPROFITABLE_PERIOD : STR_NEWS_VEHICLE_UNPROFITABLE_YEAR,
3032  v->index);
3033  }
3034  AI::NewEvent(v->owner, new ScriptEventVehicleUnprofitable(v->index));
3035  }
3036 
3038  v->profit_this_year = 0;
3040  }
3041  }
3047 });
3048 
3058 bool CanVehicleUseStation(EngineID engine_type, const Station *st)
3059 {
3060  const Engine *e = Engine::GetIfValid(engine_type);
3061  assert(e != nullptr);
3062 
3063  switch (e->type) {
3064  case VEH_TRAIN:
3065  return (st->facilities & FACIL_TRAIN) != 0;
3066 
3067  case VEH_ROAD:
3068  /* For road vehicles we need the vehicle to know whether it can actually
3069  * use the station, but if it doesn't have facilities for RVs it is
3070  * certainly not possible that the station can be used. */
3071  return (st->facilities & (FACIL_BUS_STOP | FACIL_TRUCK_STOP)) != 0;
3072 
3073  case VEH_SHIP:
3074  return (st->facilities & FACIL_DOCK) != 0;
3075 
3076  case VEH_AIRCRAFT:
3077  return (st->facilities & FACIL_AIRPORT) != 0 &&
3079 
3080  default:
3081  return false;
3082  }
3083 }
3084 
3091 bool CanVehicleUseStation(const Vehicle *v, const Station *st)
3092 {
3093  if (v->type == VEH_ROAD) return st->GetPrimaryRoadStop(RoadVehicle::From(v)) != nullptr;
3094 
3095  return CanVehicleUseStation(v->engine_type, st);
3096 }
3097 
3105 {
3106  switch (v->type) {
3107  case VEH_TRAIN:
3108  return STR_ERROR_NO_RAIL_STATION;
3109 
3110  case VEH_ROAD: {
3111  const RoadVehicle *rv = RoadVehicle::From(v);
3112  RoadStop *rs = st->GetPrimaryRoadStop(rv->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK);
3113 
3114  StringID err = rv->IsBus() ? STR_ERROR_NO_BUS_STATION : STR_ERROR_NO_TRUCK_STATION;
3115 
3116  for (; rs != nullptr; rs = rs->next) {
3117  /* Articulated vehicles cannot use bay road stops, only drive-through. Make sure the vehicle can actually use this bay stop */
3119  err = STR_ERROR_NO_STOP_ARTICULATED_VEHICLE;
3120  continue;
3121  }
3122 
3123  /* Bay stop errors take precedence, but otherwise the vehicle may not be compatible with the roadtype/tramtype of this station tile.
3124  * We give bay stop errors precedence because they are usually a bus sent to a tram station or vice versa. */
3125  if (!HasTileAnyRoadType(rs->xy, rv->compatible_roadtypes) && err != STR_ERROR_NO_STOP_ARTICULATED_VEHICLE) {
3126  err = RoadTypeIsRoad(rv->roadtype) ? STR_ERROR_NO_STOP_COMPATIBLE_ROAD_TYPE : STR_ERROR_NO_STOP_COMPATIBLE_TRAM_TYPE;
3127  continue;
3128  }
3129  }
3130 
3131  return err;
3132  }
3133 
3134  case VEH_SHIP:
3135  return STR_ERROR_NO_DOCK;
3136 
3137  case VEH_AIRCRAFT:
3138  if ((st->facilities & FACIL_AIRPORT) == 0) return STR_ERROR_NO_AIRPORT;
3139  if (v->GetEngine()->u.air.subtype & AIR_CTOL) {
3140  return STR_ERROR_AIRPORT_NO_PLANES;
3141  } else {
3142  return STR_ERROR_AIRPORT_NO_HELICOPTERS;
3143  }
3144 
3145  default:
3146  return INVALID_STRING_ID;
3147  }
3148 }
3149 
3156 {
3157  assert(this->IsGroundVehicle());
3158  if (this->type == VEH_TRAIN) {
3159  return &Train::From(this)->gcache;
3160  } else {
3161  return &RoadVehicle::From(this)->gcache;
3162  }
3163 }
3164 
3171 {
3172  assert(this->IsGroundVehicle());
3173  if (this->type == VEH_TRAIN) {
3174  return &Train::From(this)->gcache;
3175  } else {
3176  return &RoadVehicle::From(this)->gcache;
3177  }
3178 }
3179 
3186 {
3187  assert(this->IsGroundVehicle());
3188  if (this->type == VEH_TRAIN) {
3189  return Train::From(this)->gv_flags;
3190  } else {
3191  return RoadVehicle::From(this)->gv_flags;
3192  }
3193 }
3194 
3200 const uint16_t &Vehicle::GetGroundVehicleFlags() const
3201 {
3202  assert(this->IsGroundVehicle());
3203  if (this->type == VEH_TRAIN) {
3204  return Train::From(this)->gv_flags;
3205  } else {
3206  return RoadVehicle::From(this)->gv_flags;
3207  }
3208 }
3209 
3218 void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8_t num_vehicles)
3219 {
3220  if (v->type == VEH_TRAIN) {
3221  Train *u = Train::From(v);
3222  /* Only include whole vehicles, so start with the first articulated part */
3223  u = u->GetFirstEnginePart();
3224 
3225  /* Include num_vehicles vehicles, not counting articulated parts */
3226  for (; u != nullptr && num_vehicles > 0; num_vehicles--) {
3227  do {
3228  /* Include current vehicle in the selection. */
3229  include(set, u->index);
3230 
3231  /* If the vehicle is multiheaded, add the other part too. */
3232  if (u->IsMultiheaded()) include(set, u->other_multiheaded_part->index);
3233 
3234  u = u->Next();
3235  } while (u != nullptr && u->IsArticulatedPart());
3236  }
3237  }
3238 }
3239 
3245 {
3246  uint32_t max_weight = 0;
3247 
3248  for (const Vehicle *u = this; u != nullptr; u = u->Next()) {
3249  max_weight += u->GetMaxWeight();
3250  }
3251 
3252  return max_weight;
3253 }
3254 
3260 {
3261  uint32_t max_weight = GetDisplayMaxWeight();
3262  if (max_weight == 0) return 0;
3263  return GetGroundVehicleCache()->cached_power * 10u / max_weight;
3264 }
3265 
3272 bool VehiclesHaveSameEngineList(const Vehicle *v1, const Vehicle *v2)
3273 {
3274  while (true) {
3275  if (v1 == nullptr && v2 == nullptr) return true;
3276  if (v1 == nullptr || v2 == nullptr) return false;
3277  if (v1->GetEngine() != v2->GetEngine()) return false;
3278  v1 = v1->GetNextVehicle();
3279  v2 = v2->GetNextVehicle();
3280  }
3281 }
3282 
3289 bool VehiclesHaveSameOrderList(const Vehicle *v1, const Vehicle *v2)
3290 {
3291  const Order *o1 = v1->GetFirstOrder();
3292  const Order *o2 = v2->GetFirstOrder();
3293  while (true) {
3294  if (o1 == nullptr && o2 == nullptr) return true;
3295  if (o1 == nullptr || o2 == nullptr) return false;
3296  if (!o1->Equals(*o2)) return false;
3297  o1 = o1->next;
3298  o2 = o2->next;
3299  }
3300 }
Base functions for all AIs.
Base for aircraft.
Station * GetTargetAirportIfValid(const Aircraft *v)
Returns aircraft's target station if v->target_airport is a valid station with airport.
void AircraftNextAirportPos_and_Order(Aircraft *v)
set the right pos when heading to other airports after takeoff
@ AIR_SHADOW
shadow of the aircraft
Definition: aircraft.h:31
void HandleAircraftEnterHangar(Aircraft *v)
Handle Aircraft specific tasks when an Aircraft enters a hangar.
@ FLYING
Vehicle is flying in the air.
Definition: airport.h:75
CargoTypes GetCargoTypesOfArticulatedVehicle(const Vehicle *v, CargoID *cargo_type)
Get cargo mask of all cargoes carried by an articulated vehicle.
void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type, CargoTypes *union_mask, CargoTypes *intersection_mask)
Merges the refit_masks of all articulated parts.
CargoTypes GetCargoTypesOfArticulatedParts(EngineID engine)
Get the cargo mask of the parts of a given engine.
Functions related to articulated vehicles.
Command definitions related to autoreplace.
Functions related to autoreplacing.
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.
bool EngineHasReplacementForCompany(const Company *c, EngineID engine, GroupID group)
Check if a company has a replacement set up for the given engine.
void InvalidateAutoreplaceWindow(EngineID e, GroupID id_g)
Rebuild the left autoreplace list if an engine is removed or added.
Functions related to the autoreplace GUIs.
Class for backupping variables and making sure they are restored later.
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SB(T &x, const uint8_t s, const uint8_t n, const U d)
Set n bits in x starting at bit s to d.
#define CLRBITS(x, y)
Clears several bits in a variable.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr uint8_t FindFirstBit(T x)
Search the first set bit in a value.
constexpr static debug_inline uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
constexpr bool HasAtMostOneBit(T value)
Test whether value has at most 1 bit set.
constexpr T ToggleBit(T &x, const uint8_t y)
Toggles a bit in a variable.
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
Map accessor functions for bridges.
bool IsBridgeAbove(Tile t)
checks if a bridge is set above the ground of this tile
Definition: bridge_map.h:45
uint8_t CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:22
bool IsValidCargoID(CargoID t)
Test whether cargo type is not INVALID_CARGO.
Definition: cargo_type.h:107
bool IsCargoInClass(CargoID c, CargoClass cc)
Does cargo c have cargo class cc?
Definition: cargotype.h:232
@ CC_PASSENGERS
Passengers.
Definition: cargotype.h:50
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition: ai_core.cpp:243
void OnCleanPool()
Empty the cargo list, but don't free the cargo packets; the cargo packets are cleaned by CargoPacket'...
@ MTA_LOAD
Load the cargo from the station.
Definition: cargopacket.h:300
Common return value for all commands.
Definition: command_type.h:23
bool Succeeded() const
Did this command succeed?
Definition: command_type.h:162
Money GetCost() const
The costs as made up to this moment.
Definition: command_type.h:83
bool Failed() const
Did this command fail?
Definition: command_type.h:171
StringID GetErrorMessage() const
Returns the error message of a command.
Definition: command_type.h:142
static constexpr int DAYS_IN_ECONOMY_MONTH
Days in an economy month, when in wallclock timekeeping mode.
UnitID UseID(UnitID index)
Use a unit number.
Definition: vehicle.cpp:1863
void ReleaseID(UnitID index)
Release a unit number.
Definition: vehicle.cpp:1880
UnitID NextID() const
Find first unused unit number.
Definition: vehicle.cpp:1848
bool GRFBugReverse(uint32_t grfid, uint16_t internal_id)
Logs GRF bug - rail vehicle has different length after reversing.
Definition: gamelog.cpp:482
An interval timer will fire every interval, and will continue to fire until it is deleted.
Definition: timer.h:76
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
static void Reset(PerformanceElement elem)
Store the previous accumulator value and reset for a new cycle of accumulating measurements.
RAII class for measuring simple elements of performance.
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
static Date date
Current date in days (day counter).
static DateFract date_fract
Fractional part of the day.
static constexpr TimerGame< struct Economy >::Date MAX_DATE
The date of the last day of the max year.
static constexpr int DAYS_IN_LEAP_YEAR
sometimes, you need one day more...
static Date date
Current date in days (day counter).
static bool UsingWallclockUnits(bool newgame=false)
Check if we are using wallclock units.
static DateFract date_fract
Fractional part of the day.
uint64_t TickCounter
The type that the tick counter is stored in.
static TickCounter counter
Monotonic counter, in ticks, since start of game.
int32_t Ticks
The type to store ticks in.
static constexpr Date DateAtStartOfYear(Year year)
Calculate the date of the first day of a given year.
CargoList that is used for vehicles.
Definition: cargopacket.h:351
uint ActionCount(MoveToAction action) const
Returns the amount of cargo designated for a given purpose.
Definition: cargopacket.h:424
uint Truncate(uint max_move=UINT_MAX)
Truncates the cargo in this list to the given amount.
uint Return(uint max_move, StationCargoList *dest, StationID next_station, TileIndex current_tile)
Returns reserved cargo to the station and removes it from the cache.
void KeepAll()
Marks all cargo in the vehicle as to be kept.
Definition: cargopacket.h:488
void AgeCargo()
Ages the all cargo in this list.
uint StoredCount() const
Returns sum of cargo on board the vehicle (ie not only reserved).
Definition: cargopacket.h:434
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:28
#define return_cmd_error(errcode)
Returns from a function with a specific StringID as error.
Definition: command_func.h:38
DoCommandFlag
List of flags for a command.
Definition: command_type.h:374
@ DC_EXEC
execute the given command
Definition: command_type.h:376
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
void SubtractMoneyFromCompany(const CommandCost &cost)
Subtract money from the _current_company, if the company is valid.
Money GetAvailableMoney(CompanyID company)
Get the amount of money that a company has available, or INT64_MAX if there is no such valid company.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:52
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:53
Functions related to companies.
bool IsLocalCompany()
Is the current company the local company?
Definition: company_func.h:47
Owner
Enum for all companies/owners.
Definition: company_type.h:18
Some simple functions to help with accessing containers.
bool include(Container &container, typename Container::const_reference &item)
Helper function to append an item to a container if it is not already contained.
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
Functions related to depots.
void DeleteDepotHighlightOfVehicle(const Vehicle *v)
Removes the highlight of a vehicle in a depot window.
Definition: depot_gui.cpp:1181
Map related accessors for depots.
bool IsDepotTile(Tile tile)
Is the given tile a tile with a depot on it?
Definition: depot_map.h:41
DirDiff DirDifference(Direction d0, Direction d1)
Calculate the difference between two directions.
Direction ReverseDir(Direction d)
Return the reverse of a direction.
Direction ChangeDir(Direction d, DirDiff delta)
Change a direction by a given difference.
Direction
Defines the 8 directions on the map.
@ DIR_SW
Southwest.
@ DIR_NW
Northwest.
@ DIR_N
North.
@ DIR_SE
Southeast.
@ DIR_S
South.
@ DIR_NE
Northeast.
@ DIR_W
West.
@ DIR_E
East.
@ INVALID_DIAGDIR
Flag for an invalid DiagDirection.
DirDiff
Allow incrementing of Direction variables.
@ DIRDIFF_45LEFT
Angle of 45 degrees left.
@ DIRDIFF_REVERSE
One direction is the opposite of the other one.
@ DIRDIFF_45RIGHT
Angle of 45 degrees right.
@ DIRDIFF_SAME
Both directions faces to the same direction.
@ DIRDIFF_90RIGHT
Angle of 90 degrees right.
void ReleaseDisasterVehicle(VehicleID vehicle)
Notify disasters that we are about to delete a vehicle.
void LoadUnloadStation(Station *st)
Load/unload the vehicles in this station according to the order they entered.
Definition: economy.cpp:1953
void PrepareUnload(Vehicle *front_v)
Prepare the vehicle to be unloaded.
Definition: economy.cpp:1281
Base classes related to the economy.
@ EXPENSES_NEW_VEHICLES
New vehicles.
Definition: economy_type.h:174
EffectVehicle * CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicleType type)
Create an effect vehicle above a particular vehicle.
Base class for all effect vehicles.
Functions related to effect vehicles.
EffectVehicleType
Effect vehicle types.
@ EV_BREAKDOWN_SMOKE
Smoke of broken vehicles except aircraft.
@ EV_STEAM_SMOKE
Smoke of steam engines.
@ EV_DIESEL_SMOKE
Smoke of diesel engines.
@ EV_BREAKDOWN_SMOKE_AIRCRAFT
Smoke of broken aircraft.
@ EV_ELECTRIC_SPARK
Sparcs of electric engines.
@ EC_DIESEL
Diesel rail engine.
Definition: engine_type.h:35
@ EC_STEAM
Steam rail engine.
Definition: engine_type.h:34
@ EC_MAGLEV
Maglev engine.
Definition: engine_type.h:38
@ EC_ELECTRIC
Electric rail engine.
Definition: engine_type.h:36
@ EC_MONORAIL
Mono rail engine.
Definition: engine_type.h:37
@ RAILVEH_WAGON
simple wagon, not motorized
Definition: engine_type.h:29
static const EngineID INVALID_ENGINE
Constant denoting an invalid engine.
Definition: engine_type.h:206
uint16_t EngineID
Unique identification number of an engine.
Definition: engine_type.h:21
@ AIR_CTOL
Conventional Take Off and Landing, i.e. planes.
Definition: engine_type.h:95
@ EF_USES_2CC
Vehicle uses two company colours.
Definition: engine_type.h:170
@ EF_ROAD_TRAM
Road vehicle is a tram/light rail vehicle.
Definition: engine_type.h:169
@ EF_RAIL_IS_MU
Rail vehicle is a multiple-unit (DMU/EMU)
Definition: engine_type.h:171
@ EF_NO_BREAKDOWN_SMOKE
Do not show black smoke during a breakdown.
Definition: engine_type.h:175
constexpr debug_inline bool HasFlag(const T x, const T y)
Checks if a value in a bitset enum is set.
Definition: enum_type.hpp:58
Functions related to errors.
void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc)
Display an error message in a window.
Definition: error_gui.cpp:367
@ WL_CRITICAL
Critical errors, the MessageBox is shown in all cases.
Definition: error.h:27
Types for recording game performance data.
@ PFE_GL_SHIPS
Time spent processing ships.
@ PFE_GL_AIRCRAFT
Time spent processing aircraft.
@ PFE_GL_ECONOMY
Time spent processing cargo movement.
@ PFE_GL_ROADVEHS
Time spend processing road vehicles.
@ PFE_GL_TRAINS
Time spent processing trains.
Gamelog _gamelog
Gamelog instance.
Definition: gamelog.cpp:31
Functions to be called to log fundamental changes to the game.
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:988
@ Normal
The most basic (normal) sprite.
uint32_t PaletteID
The number of the palette.
Definition: gfx_type.h:19
@ GVF_SUPPRESS_IMPLICIT_ORDERS
Disable insertion and removal of automatic orders until the vehicle completes the real order.
bool 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:2022
void MarkTilesDirty(bool cargo_change) const
Marks the tiles of the station as dirty.
Definition: station.cpp:243
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:2057
virtual void MarkDirty()
Marks the vehicles to be redrawn and updates cached variables.
Definition: vehicle_base.h:407
void DeleteGroupHighlightOfVehicle(const Vehicle *v)
Removes the highlight of a vehicle in a group window.
Definition: group_gui.cpp:1252
Functions/definitions that have something to do with groups.
static const GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition: group_type.h:17
static const GroupID INVALID_GROUP
Sentinel for invalid groups.
Definition: group_type.h:18
const TileTypeProcs *const _tile_type_procs[16]
Tile callback functions for each type of tile.
Definition: landscape.cpp:65
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:79
Declaration of link graph classes used for cargo distribution.
static const uint8_t LIT_ALL
Show the liveries of all companies.
Definition: livery.h:18
LiveryScheme
List of different livery schemes.
Definition: livery.h:21
static const uint8_t LIT_COMPANY
Show the liveries of your own company.
Definition: livery.h:17
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:425
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:415
static debug_inline TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition: map_func.h:404
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition: math_func.hpp:23
constexpr uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
Definition: math_func.hpp:320
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:79
constexpr bool IsInsideMM(const T x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
Definition: math_func.hpp:268
Miscellaneous command definitions.
void HideFillingPercent(TextEffectID *te_id)
Hide vehicle loading indicators.
Definition: misc_gui.cpp:648
void ShowCostOrIncomeAnimation(int x, int y, int z, Money cost)
Display animated income or costs on the map.
Definition: misc_gui.cpp:570
bool _networking
are we in networking mode?
Definition: network.cpp:65
Basic functions/variables used all over the place.
@ SAT_TRAIN_DEPARTS
Trigger platform when train leaves.
@ CBID_VEHICLE_SPAWN_VISUAL_EFFECT
Called to spawn visual effects for vehicles.
@ CBID_VEHICLE_COLOUR_MAPPING
Called to determine if a specific colour map should be used for a vehicle instead of the default live...
@ CBID_VEHICLE_32DAY_CALLBACK
Called for every vehicle every 32 days (not all on same date though).
@ CBID_VEHICLE_VISUAL_EFFECT
Visual effects and wagon power.
@ CBM_VEHICLE_COLOUR_REMAP
Change colour mapping of vehicle.
@ CBM_VEHICLE_VISUAL_EFFECT
Visual effects and wagon power (trains, road vehicles and ships)
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
void ErrorUnknownCallbackResult(uint32_t grfid, uint16_t cbid, uint16_t cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
GRFConfig * GetGRFConfig(uint32_t grfid, uint32_t mask)
Retrieve a NewGRF from the current config by its grfid.
GRFBugs
Encountered GRF bugs.
Definition: newgrf_config.h:42
@ GBUG_VEH_POWERED_WAGON
Powered wagon changed poweredness state when not inside a depot.
Definition: newgrf_config.h:45
@ GBUG_VEH_LENGTH
Length of rail vehicle changes when not inside a depot.
Definition: newgrf_config.h:43
Functions/types related to NewGRF debugging.
GrfSpecFeature GetGrfSpecFeature(TileIndex tile)
Get the GrfSpecFeature associated with the tile.
void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index)
Delete inspect window for a given feature and index.
bool UsesWagonOverride(const Vehicle *v)
Check if a wagon is currently using a wagon override.
uint16_t GetVehicleCallback(CallbackID callback, uint32_t param1, uint32_t param2, EngineID engine, const Vehicle *v)
Evaluate a newgrf callback for vehicles.
NewGRF definitions and structures for road stops.
@ RSRT_VEH_DEPARTS
Trigger roadstop when road vehicle leaves.
void TriggerRoadStopRandomisation(Station *st, TileIndex tile, RoadStopRandomTrigger trigger, CargoID cargo_type=INVALID_CARGO)
Trigger road stop randomisation.
bool PlayVehicleSound(const Vehicle *v, VehicleSoundEvent event, bool force)
Checks whether a NewGRF wants to play a different vehicle sound effect.
Functions related to NewGRF provided sounds.
@ VSE_VISUAL_EFFECT
Vehicle visual effect (steam, diesel smoke or electric spark) is shown.
Definition: newgrf_sound.h:24
@ VSE_RUNNING
Vehicle running normally.
Definition: newgrf_sound.h:22
@ VSE_STOPPED_16
Every 16 ticks while the vehicle is stopped (speed == 0).
Definition: newgrf_sound.h:26
@ VSE_RUNNING_16
Every 16 ticks while the vehicle is running (speed > 0).
Definition: newgrf_sound.h:25
@ VSE_BREAKDOWN
Vehicle breaking down.
Definition: newgrf_sound.h:21
uint32_t GetRegister(uint i)
Gets the value of a so-called newgrf "register".
void TriggerStationRandomisation(Station *st, TileIndex trigger_tile, StationRandomTrigger trigger, CargoID cargo_type)
Trigger station randomisation.
Header file for NewGRF stations.
@ SRT_TRAIN_DEPARTS
Trigger platform when train leaves.
Functions related to news.
void DeleteVehicleNews(VehicleID vid, StringID news)
Delete a news item type about a vehicle.
Definition: news_gui.cpp:930
void AddVehicleAdviceNewsItem(StringID string, VehicleID vehicle)
Adds a vehicle-advice news item.
Definition: news_func.h:40
@ PM_PAUSED_ERROR
A game paused because a (critical) error.
Definition: openttd.h:73
@ PM_PAUSED_NORMAL
A game normally paused.
Definition: openttd.h:70
Functions related to order backups.
void InsertOrder(Vehicle *v, Order *new_o, VehicleOrderID sel_ord)
Insert a new order but skip the validation.
Definition: order_cmd.cpp:912
void DeleteOrder(Vehicle *v, VehicleOrderID sel_ord)
Delete an order but skip the parameter validation.
Definition: order_cmd.cpp:1037
void InvalidateVehicleOrder(const Vehicle *v, int data)
Updates the widgets of a vehicle which contains the order-data.
Definition: order_cmd.cpp:235
void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indices)
Delete all orders from a vehicle.
Definition: order_cmd.cpp:1869
@ ODATFB_UNBUNCH
Service the vehicle and then unbunch it.
Definition: order_type.h:106
@ ODATFB_NEAREST_DEPOT
Send the vehicle to the nearest depot.
Definition: order_type.h:105
@ ODATFB_HALT
Service the vehicle and then halt it.
Definition: order_type.h:104
@ ODATF_SERVICE_ONLY
Only service the vehicle.
Definition: order_type.h:103
@ OLFB_FULL_LOAD
Full load all cargoes of the consist.
Definition: order_type.h:64
@ OLFB_NO_LOAD
Do not load anything.
Definition: order_type.h:66
@ OLF_FULL_LOAD_ANY
Full load a single cargo of the consist.
Definition: order_type.h:65
@ OUFB_NO_UNLOAD
Totally no unloading will be done.
Definition: order_type.h:56
static const VehicleOrderID MAX_VEH_ORDER_ID
Last valid VehicleOrderID.
Definition: order_type.h:23
@ ONSF_NO_STOP_AT_ANY_STATION
The vehicle will not stop at any stations it passes including the destination.
Definition: order_type.h:76
@ ONSF_STOP_EVERYWHERE
The vehicle will stop at any station it passes and the destination.
Definition: order_type.h:73
@ ODTFB_PART_OF_ORDERS
This depot order is because of a regular order.
Definition: order_type.h:96
@ ODTFB_SERVICE
This depot order is because of the servicing limit.
Definition: order_type.h:95
@ ODTF_MANUAL
Manually initiated order.
Definition: order_type.h:94
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
Some methods of Pool are placed here in order to reduce compilation time and binary size.
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
Definition: pool_func.hpp:237
bool HasAnyRailTypesAvail(const CompanyID company)
Test if any buildable railtype is available for a company.
Definition: rail.cpp:196
RailType GetTileRailType(Tile tile)
Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile.
Definition: rail.cpp:155
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:335
void SetDepotReservation(Tile t, bool b)
Set the reservation state of the depot.
Definition: rail_map.h:270
Pseudo random number generator.
uint32_t RandomRange(uint32_t limit, const std::source_location location=std::source_location::current())
Pick a random number between 0 and limit - 1, inclusive.
Definition: random_func.hpp:88
bool Chance16I(const uint32_t a, const uint32_t b, const uint32_t r)
Checks if a given randomize-number is below a given probability.
bool Chance16(const uint32_t a, const uint32_t b, const std::source_location location=std::source_location::current())
Flips a coin with given probability.
Definition of link refreshing utility.
bool HasAnyRoadTypesAvail(CompanyID company, RoadTramType rtt)
Test if any buildable RoadType is available for a company.
Definition: road.cpp:143
bool HasTileAnyRoadType(Tile t, RoadTypes rts)
Check if a tile has one of the specified road types.
Definition: road_map.h:222
Base class for roadstops.
Road vehicle states.
@ RVSB_IN_DT_ROAD_STOP
The vehicle is in a drive-through road stop.
Definition: roadveh.h:51
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:57
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:56
Base for ships.
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:650
Functions related to sound.
@ SND_3A_BREAKDOWN_TRAIN_SHIP_TOYLAND
58 == 0x3A Breakdown: train or ship (toyland)
Definition: sound_type.h:97
@ SND_10_BREAKDOWN_TRAIN_SHIP
14 == 0x0E Breakdown: train or ship (non-toyland)
Definition: sound_type.h:53
@ SND_0F_BREAKDOWN_ROADVEHICLE
13 == 0x0D Breakdown: road vehicle (non-toyland)
Definition: sound_type.h:52
@ SND_35_BREAKDOWN_ROADVEHICLE_TOYLAND
53 == 0x35 Breakdown: road vehicle (toyland)
Definition: sound_type.h:92
Functions to cache sprites in memory.
static const PaletteID PALETTE_RECOLOUR_START
First recolour sprite for company colours.
Definition: sprites.h:1574
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition: sprites.h:1605
Base classes/functions for stations.
void IncreaseStats(Station *st, CargoID cargo, StationID next_station_id, uint capacity, uint usage, uint32_t time, EdgeUpdateMode mode)
Increase capacity for a link stat given by station cargo and next hop.
bool IsStationRoadStopTile(Tile t)
Is tile t a road stop station?
Definition: station_map.h:234
bool IsBayRoadStopTile(Tile t)
Is tile t a bay (non-drive through) road stop station?
Definition: station_map.h:266
bool IsRailStationTile(Tile t)
Is this tile a station tile and a rail station?
Definition: station_map.h:102
StationID GetStationIndex(Tile t)
Get StationID from a tile.
Definition: station_map.h:28
RoadStopType GetRoadStopType(Tile t)
Get the road stop type of this tile.
Definition: station_map.h:56
@ ROADSTOP_BUS
A standard stop for buses.
Definition: station_type.h:46
@ ROADSTOP_TRUCK
A standard stop for trucks.
Definition: station_type.h:47
@ FACIL_DOCK
Station with a dock.
Definition: station_type.h:58
@ FACIL_BUS_STOP
Station with bus stops.
Definition: station_type.h:56
@ FACIL_AIRPORT
Station with an airport.
Definition: station_type.h:57
@ FACIL_TRUCK_STOP
Station with truck stops.
Definition: station_type.h:55
@ FACIL_TRAIN
Station with train station.
Definition: station_type.h:54
Definition of base types and functions in a cross-platform compatible way.
static void StrMakeValid(T &dst, const char *str, const char *last, StringValidationSettings settings)
Copies the valid (UTF-8) characters from str up to last to the dst.
Definition: string.cpp:107
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings.cpp:104
std::string GetString(StringID string)
Resolve the given StringID into a std::string with all the associated DParam lookups and formatting.
Definition: strings.cpp:319
void SetDParamStr(size_t n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition: strings.cpp:357
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:17
uint8_t subtype
Type of aircraft.
Definition: engine_type.h:104
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition: aircraft.h:72
uint8_t pos
Next desired position of the aircraft.
Definition: aircraft.h:74
uint8_t state
State of the airport.
Definition: aircraft.h:77
bool IsNormalAircraft() const
Check if the aircraft type is a normal flying device; eg not a rotor or a shadow.
Definition: aircraft.h:121
uint8_t previous_pos
Previous desired position of the aircraft.
Definition: aircraft.h:75
StationID targetairport
Airport to go to next.
Definition: aircraft.h:76
struct AirportFTA * layout
state machine for airport
Definition: airport.h:177
Flags flags
Flags for this airport type.
Definition: airport.h:180
@ AIRPLANES
Can planes land on this airport type?
Definition: airport.h:147
@ HELICOPTERS
Can helicopters land on this airport type?
Definition: airport.h:148
Internal structure used in openttd - Finite sTate mAchine --> FTA.
Definition: airport.h:190
uint64_t block
64 bit blocks (st->airport.flags), should be enough for the most complex airports
Definition: airport.h:192
uint64_t flags
stores which blocks on the airport are taken. was 16 bit earlier on, then 32
Definition: station_base.h:293
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:317
Class to backup a specific variable and restore it later.
Definition: backup_type.hpp:21
void Restore()
Restore the variable.
TimerGameTick::Ticks current_order_time
How many ticks have passed since this order started.
Definition: base_consist.h:21
TimerGameTick::TickCounter depot_unbunching_next_departure
When the vehicle will next try to leave its unbunching depot.
Definition: base_consist.h:26
VehicleOrderID cur_real_order_index
The index to the current real (non-implicit) order.
Definition: base_consist.h:31
TimerGameTick::Ticks round_trip_time
How many ticks for a single circumnavigation of the orders.
Definition: base_consist.h:27
TimerGameTick::TickCounter depot_unbunching_last_departure
When the vehicle last left its unbunching depot.
Definition: base_consist.h:25
VehicleOrderID cur_implicit_order_index
The index to the current implicit order.
Definition: base_consist.h:32
TimerGameTick::Ticks lateness_counter
How many ticks late (or early if negative) this vehicle is.
Definition: base_consist.h:22
uint16_t vehicle_flags
Used for gradual loading and other miscellaneous things (.
Definition: base_consist.h:34
void ResetDepotUnbunching()
Resets all the data used for depot unbunching.
StationFacility facilities
The facilities that this station has.
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:51
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Definition: cargotype.h:134
GUISettings gui
settings related to the GUI
Structure to return information about the closest depot location, and whether it could be found.
Definition: vehicle_base.h:230
DestinationID destination
The DestinationID as used for orders.
Definition: vehicle_base.h:232
CompanySettings settings
settings specific for each company
Definition: company_base.h:122
uint32_t engine_renew_money
minimum amount of money before autorenew is used
int16_t engine_renew_months
months before/after the maximum vehicle age a vehicle should be renewed
bool engine_renew
is autorenew enabled
GroupStatistics group_all[VEH_COMPANY_END]
NOSAVE: Statistics for the ALL_GROUP group.
Definition: company_base.h:144
uint8_t vehicle_breakdowns
likelihood of vehicles breaking down
Data about how and where to blit pixels.
Definition: gfx_type.h:157
A special vehicle is one of the following:
TransparencyOption GetTransparencyOption() const
Determines the transparency option affecting the effect.
uint16_t animation_state
State primarily used to change the graphics/behaviour.
uint8_t misc_flags
Miscellaneous flags.
Definition: engine_type.h:155
uint16_t callback_mask
Bitmask of vehicle callbacks that have to be called.
Definition: engine_type.h:156
CargoID GetDefaultCargoType() const
Determines the default cargo type of an engine.
Definition: engine_base.h:96
GRFFilePropsBase< NUM_CARGO+2 > grf_prop
Properties related the the grf file.
Definition: engine_base.h:77
uint32_t GetGRFID() const
Retrieve the GRF ID of the NewGRF the engine is tied to.
Definition: engine.cpp:157
CompanyMask company_avail
Bit for each company whether the engine is available for that company.
Definition: engine_base.h:53
VehicleType type
Vehicle type, ie VEH_ROAD, VEH_TRAIN, etc.
Definition: engine_base.h:56
const GRFFile * GetGRF() const
Retrieve the NewGRF the engine is tied to.
Definition: engine_base.h:167
uint16_t reliability
Current reliability of the engine.
Definition: engine_base.h:41
static Pool::IterateWrapperFiltered< Engine, EngineTypeFilter > IterateType(VehicleType vt, size_t from=0)
Returns an iterable ensemble of all valid engines of the given type.
Definition: engine_base.h:186
Information about GRF, used in the game and (part of it) in savegames.
uint32_t grf_bugs
NOSAVE: bugs in this GRF in this run,.
const char * GetName() const
Get the name of this grf.
uint16_t local_id
id defined by the grf file for this entity
const struct GRFFile * grffile
grf file that introduced this entity
Dynamic data of a loaded NewGRF.
Definition: newgrf.h:108
bool lost_vehicle_warn
if a vehicle can't find its destination, show a warning
bool vehicle_income_warn
if a vehicle isn't generating income, show a warning
bool show_track_reservation
highlight reserved tracks.
uint8_t liveries
options for displaying company liveries, 0=none, 1=self, 2=all
bool old_vehicle_warn
if a vehicle is getting old, show a warning
uint8_t landscape
the landscape we're currently in
DifficultySettings difficulty
settings related to the difficulty
GameCreationSettings game_creation
settings used during the creation of a game (map)
VehicleSettings vehicle
options for vehicles
OrderSettings order
settings related to orders
Position information of a vehicle after it moved.
Definition: vehicle_func.h:77
TileIndex new_tile
Tile of the vehicle after moving.
Definition: vehicle_func.h:80
int y
x and y position of the vehicle after moving
Definition: vehicle_func.h:78
TileIndex old_tile
Current tile of the vehicle.
Definition: vehicle_func.h:79
bool HasRating() const
Does this cargo have a rating at this station?
Definition: station_base.h:258
StationCargoList cargo
The cargo packets of cargo waiting in this station.
Definition: station_base.h:210
Cached, frequently calculated values.
EngineID first_engine
Cached EngineID of the front vehicle. INVALID_ENGINE for the front vehicle itself.
uint32_t cached_power
Total power of the consist (valid only for the first engine).
bool IsMultiheaded() const
Check if the vehicle is a multiheaded engine.
static void CountVehicle(const Vehicle *v, int delta)
Update num_vehicle when adding or removing a vehicle.
Definition: group_cmd.cpp:133
static void VehicleReachedMinAge(const Vehicle *v)
Add a vehicle to the profit sum of its group.
Definition: group_cmd.cpp:180
static void CountEngine(const Vehicle *v, int delta)
Update num_engines when adding/removing an engine.
Definition: group_cmd.cpp:158
uint16_t num_vehicle
Number of vehicles.
Definition: group.h:28
static void UpdateAutoreplace(CompanyID company)
Update autoreplace_defined and autoreplace_finished of all statistics of a company.
Definition: group_cmd.cpp:221
static void UpdateProfits()
Recompute the profits for all groups.
Definition: group_cmd.cpp:194
Group data.
Definition: group.h:72
Livery livery
Custom colour scheme for vehicles in this group.
Definition: group.h:78
GroupID parent
Parent group.
Definition: group.h:83
Information about a particular livery.
Definition: livery.h:78
Colours colour2
Second colour, for vehicles with 2CC support.
Definition: livery.h:81
Colours colour1
First colour, for all vehicles.
Definition: livery.h:80
uint8_t in_use
Bit 0 set if this livery should override the default livery first colour, Bit 1 for the second colour...
Definition: livery.h:79
bool revalidate_before_draw
We need to do a GetImage() and check bounds before drawing this sprite.
Definition: vehicle_base.h:197
VehicleSpriteSeq sprite_seq
Vehicle appearance.
Definition: vehicle_base.h:200
bool is_viewport_candidate
This vehicle can potentially be drawn on a viewport.
Definition: vehicle_base.h:198
Rect old_coord
Co-ordinates from the last valid bounding box.
Definition: vehicle_base.h:199
static void ClearVehicle(const Vehicle *v)
Clear/update the (clone) vehicle from an order backup.
Shared order list linking together the linked list of orders and the list of vehicles sharing this or...
Definition: order_base.h:259
uint GetNumVehicles() const
Return the number of vehicles that share this orders list.
Definition: order_base.h:350
void RemoveVehicle(Vehicle *v)
Removes the vehicle from the shared order list.
Definition: order_cmd.cpp:552
VehicleOrderID GetNumOrders() const
Get number of orders in the order list.
Definition: order_base.h:319
void AddVehicle([[maybe_unused]] Vehicle *v)
Adds the given vehicle to this shared order list.
Definition: order_base.h:358
bool no_servicing_if_no_breakdowns
don't send vehicles to depot when breakdowns are disabled
OrderDepotTypeFlags GetDepotOrderType() const
What caused us going to the depot?
Definition: order_base.h:144
CargoID GetRefitCargo() const
Get the cargo to to refit to.
Definition: order_base.h:131
bool Equals(const Order &other) const
Does this order have the same type, flags and destination?
Definition: order_cmd.cpp:175
DestinationID GetDestination() const
Gets the destination of this order.
Definition: order_base.h:103
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition: order_base.h:70
void SetNonStopType(OrderNonStopFlags non_stop_type)
Set whether we must stop at stations or not.
Definition: order_base.h:161
OrderType GetType() const
Get the type of order of this order.
Definition: order_base.h:76
void SetDepotOrderType(OrderDepotTypeFlags depot_order_type)
Set the cause to go to the depot.
Definition: order_base.h:165
OrderLoadFlags GetLoadType() const
How must the consist be loaded?
Definition: order_base.h:136
void MakeDummy()
Makes this order a Dummy order.
Definition: order_cmd.cpp:133
void MakeGoToDepot(DepotID destination, OrderDepotTypeFlags order, OrderNonStopFlags non_stop_type=ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS, OrderDepotActionFlags action=ODATF_SERVICE_ONLY, CargoID cargo=CARGO_NO_REFIT)
Makes this order a Go To Depot order.
Definition: order_cmd.cpp:90
Order * next
Pointer to next order. If nullptr, end of list.
Definition: order_base.h:59
void SetDepotActionType(OrderDepotActionFlags depot_service_type)
Set what we are going to do in the depot.
Definition: order_base.h:167
OrderDepotActionFlags GetDepotActionType() const
What are we going to do when in the depot.
Definition: order_base.h:146
void MakeLeaveStation()
Makes this order a Leave Station order.
Definition: order_cmd.cpp:124
bool CanLeaveWithCargo(bool has_cargo) const
A vehicle can leave the current station with cargo if:
Definition: order_cmd.cpp:2249
uint16_t GetTimetabledWait() const
Get the time in ticks a vehicle should wait at the destination or 0 if it's not timetabled.
Definition: order_base.h:188
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:2225
void MakeImplicit(StationID destination)
Makes this order an implicit order.
Definition: order_cmd.cpp:154
OrderNonStopFlags GetNonStopType() const
At which stations must we stop?
Definition: order_base.h:140
bool IsRefit() const
Is this order a refit order.
Definition: order_base.h:117
void MakeLoading(bool ordered)
Makes this order a Loading order.
Definition: order_cmd.cpp:115
SpriteID sprite
The 'real' sprite.
Definition: gfx_type.h:24
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition: gfx_type.h:25
Coordinates of a point in 2D.
static size_t GetPoolSize()
Returns first unused index.
Definition: pool_type.hpp:360
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
static bool CleaningPool()
Returns current state of pool cleaning - yes or no.
Definition: pool_type.hpp:318
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:328
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition: pool_type.hpp:309
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:350
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:388
Base class for all pools.
Definition: pool_type.hpp:80
uint8_t visual_effect
Bitstuffed NewGRF visual effect data.
Definition: engine_type.h:58
EngineClass engclass
Class of engine for this vehicle.
Definition: engine_type.h:53
Specification of a rectangle with absolute coordinates of all edges.
A Stop for a Road Vehicle.
Definition: roadstop_base.h:22
void Leave(RoadVehicle *rv)
Leave the road stop.
Definition: roadstop.cpp:214
RoadStop * next
Next stop of the given type at this station.
Definition: roadstop_base.h:70
TileIndex xy
Position on the map.
Definition: roadstop_base.h:69
static RoadStop * GetByTile(TileIndex tile, RoadStopType type)
Find a roadstop at given tile.
Definition: roadstop.cpp:264
uint8_t visual_effect
Bitstuffed NewGRF visual effect data.
Definition: engine_type.h:126
Buses, trucks and trams belong to this class.
Definition: roadveh.h:98
uint8_t state
Definition: roadveh.h:100
RoadTypes compatible_roadtypes
NOSAVE: Roadtypes this consist is powered on.
Definition: roadveh.h:110
bool IsBus() const
Check whether a roadvehicle is a bus.
Definition: roadveh_cmd.cpp:82
RoadType roadtype
NOSAVE: Roadtype of this vehicle.
Definition: roadveh.h:108
VehicleID disaster_vehicle
NOSAVE: Disaster vehicle targetting this vehicle.
Definition: roadveh.h:109
uint8_t visual_effect
Bitstuffed NewGRF visual effect data.
Definition: engine_type.h:76
All ships have this type.
Definition: ship.h:32
TrackBits state
The "track" the ship is following.
Definition: ship.h:34
void UpdateCache()
Update the caches of this ship.
Definition: ship_cmd.cpp:232
static Station * GetIfValid(size_t index)
Returns station if the index is a valid index for this station type.
static Pool::IterateWrapper< Station > Iterate(size_t from=0)
Returns an iterable ensemble of all valid stations of type T.
static Station * Get(size_t index)
Gets station with given index.
static bool IsValidID(size_t index)
Tests whether given index is a valid index for station of this type.
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
T * Next() const
Get next vehicle in the chain.
void UpdateViewport(bool force_update, bool update_delta)
Update vehicle sprite- and position caches.
T * GetFirstEnginePart()
Get the first part of an articulated engine.
Data structure describing a sprite.
Definition: spritecache.h:17
uint16_t width
Width of the sprite.
Definition: spritecache.h:19
uint16_t height
Height of the sprite.
Definition: spritecache.h:18
int16_t y_offs
Number of pixels to shift the sprite downwards.
Definition: spritecache.h:21
int16_t x_offs
Number of pixels to shift the sprite to the right.
Definition: spritecache.h:20
Station data structure.
Definition: station_base.h:439
GoodsEntry goods[NUM_CARGO]
Goods at this station.
Definition: station_base.h:468
Airport airport
Tile area the airport covers.
Definition: station_base.h:453
VehicleEnterTileProc * vehicle_enter_tile_proc
Called when a vehicle enters a tile.
Definition: tile_cmd.h:170
'Train' is either a loco or a wagon.
Definition: train.h:89
void ConsistChanged(ConsistChangeFlags allowed_changes)
Recalculates the cached stuff of a train.
Definition: train_cmd.cpp:110
uint16_t wait_counter
Ticks waiting in front of a signal, ticks being stuck or a counter for forced proceeding through sign...
Definition: train.h:92
uint8_t cached_vis_effect
Visual effect to show (see VisualEffect)
Definition: vehicle_base.h:129
uint16_t cached_cargo_age_period
Number of ticks before carried cargo is aged.
Definition: vehicle_base.h:127
The information about a vehicle list.
Definition: vehiclelist.h:28
uint32_t Pack() const
Pack a VehicleListIdentifier in a single uint32.
Definition: vehiclelist.cpp:23
UnitID max_ships
max ships in game per company
UnitID max_trains
max trains in game per company
uint8_t smoke_amount
amount of smoke/sparks locomotives produce
UnitID max_aircraft
max planes in game per company
UnitID max_roadveh
max trucks in game per company
Sprite sequence for a vehicle part.
Definition: vehicle_base.h:135
bool IsValid() const
Check whether the sequence contains any sprites.
Definition: vehicle_base.h:152
void GetBounds(Rect *bounds) const
Determine shared bounds of all sprites.
Definition: vehicle.cpp:103
void Draw(int x, int y, PaletteID default_pal, bool force_pal) const
Draw the sprite sequence.
Definition: vehicle.cpp:131
Vehicle data structure.
Definition: vehicle_base.h:244
Money GetDisplayProfitThisYear() const
Gets the profit vehicle had this year.
Definition: vehicle_base.h:617
CargoPayment * cargo_payment
The cargo payment we're currently in.
Definition: vehicle_base.h:277
EngineID engine_type
The type of engine used for this vehicle.
Definition: vehicle_base.h:323
uint16_t cargo_age_counter
Ticks till cargo is aged next.
Definition: vehicle_base.h:346
Vehicle * Previous() const
Get the previous vehicle of this vehicle.
Definition: vehicle_base.h:639
int32_t z_pos
z coordinate.
Definition: vehicle_base.h:306
uint16_t & GetGroundVehicleFlags()
Access the ground vehicle flags of the vehicle.
Definition: vehicle.cpp:3185
Direction direction
facing
Definition: vehicle_base.h:307
void ShiftDates(TimerGameEconomy::Date interval)
Shift all dates by given interval.
Definition: vehicle.cpp:777
TimerGameEconomy::Date economy_age
Age in economy days.
Definition: vehicle_base.h:293
bool IsOrderListShared() const
Check if we share our orders with another vehicle.
Definition: vehicle_base.h:732
const Engine * GetEngine() const
Retrieves the engine of the vehicle.
Definition: vehicle.cpp:747
void IncrementRealOrderIndex()
Advanced cur_real_order_index to the next real order, keeps care of the wrap-around and invalidates t...
Definition: vehicle_base.h:886
virtual uint Crash(bool flooded=false)
Crash the (whole) vehicle chain.
Definition: vehicle.cpp:280
bool IsStoppedInDepot() const
Check whether the vehicle is in the depot and stopped.
Definition: vehicle_base.h:560
bool HasDepotOrder() const
Checks if a vehicle has a depot in its order list.
Definition: order_cmd.cpp:1851
void LeaveStation()
Perform all actions when leaving a station.
Definition: vehicle.cpp:2350
void AddToShared(Vehicle *shared_chain)
Adds this vehicle to a shared vehicle chain.
Definition: vehicle.cpp:2966
VehicleCargoList cargo
The cargo this vehicle is carrying.
Definition: vehicle_base.h:341
Vehicle * First() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:645
uint8_t x_extent
x-extent of vehicle bounding box
Definition: vehicle_base.h:316
Vehicle ** hash_tile_prev
NOSAVE: Previous vehicle in the tile location hash.
Definition: vehicle_base.h:285
bool HasUnbunchingOrder() const
Check if the current vehicle has an unbunching order.
Definition: vehicle.cpp:2489
TimerGameEconomy::Date date_of_last_service
Last economy date the vehicle had a service at a depot.
Definition: vehicle_base.h:295
uint16_t cargo_cap
total capacity
Definition: vehicle_base.h:344
StationID last_loading_station
Last station the vehicle has stopped at and could possibly leave from with any cargo loaded.
Definition: vehicle_base.h:338
VehicleOrderID GetNumOrders() const
Get the number of orders this vehicle has.
Definition: vehicle_base.h:738
uint8_t subtype
subtype (Filled with values from AircraftSubType/DisasterSubType/EffectVehicleType/GroundVehicleSubty...
Definition: vehicle_base.h:355
void ReleaseUnitNumber()
Release the vehicle's unit number.
Definition: vehicle.cpp:2419
void UpdateBoundingBoxCoordinates(bool update_cache) const
Update the bounding box co-ordinates of the vehicle.
Definition: vehicle.cpp:1702
uint8_t day_counter
Increased by one for each day.
Definition: vehicle_base.h:349
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:2430
Money profit_this_year
Profit this year << 8, low 8 bits are fract.
Definition: vehicle_base.h:273
virtual void GetImage([[maybe_unused]] Direction direction, [[maybe_unused]] EngineImageType image_type, [[maybe_unused]] VehicleSpriteSeq *result) const
Gets the sprite to show for the given direction.
Definition: vehicle_base.h:486
bool HasArticulatedPart() const
Check if an engine has an articulated part.
Definition: vehicle_base.h:963
SpriteID colourmap
NOSAVE: cached colour mapping.
Definition: vehicle_base.h:288
uint8_t breakdown_ctr
Counter for managing breakdown events.
Definition: vehicle_base.h:299
uint8_t breakdown_delay
Counter for managing breakdown length.
Definition: vehicle_base.h:300
GroupID group_id
Index of group Pool array.
Definition: vehicle_base.h:366
CommandCost SendToDepot(DoCommandFlag flags, DepotCommand command)
Send this vehicle to the depot using the given command(s).
Definition: vehicle.cpp:2583
void IncrementImplicitOrderIndex()
Increments cur_implicit_order_index, keeps care of the wrap-around and invalidates the GUI.
Definition: vehicle_base.h:862
uint8_t z_extent
z-extent of vehicle bounding box
Definition: vehicle_base.h:318
TimerGameCalendar::Date date_of_last_service_newgrf
Last calendar date the vehicle had a service at a depot, unchanged by the date cheat to protect again...
Definition: vehicle_base.h:296
Vehicle * first
NOSAVE: pointer to the first vehicle in the chain.
Definition: vehicle_base.h:250
void CancelReservation(StationID next, Station *st)
Return all reserved cargo packets to the station and reset all packets staged for transfer.
Definition: vehicle.cpp:2334
Money profit_last_year
Profit last year << 8, low 8 bits are fract.
Definition: vehicle_base.h:274
bool IsEngineCountable() const
Check if a vehicle is counted in num_engines in each company struct.
Definition: vehicle.cpp:714
Order * GetOrder(int index) const
Returns order 'index' of a vehicle or nullptr when it doesn't exists.
Definition: vehicle_base.h:922
virtual ~Vehicle()
We want to 'destruct' the right class.
Definition: vehicle.cpp:893
bool IsArticulatedPart() const
Check if the vehicle is an articulated part of an engine.
Definition: vehicle_base.h:954
bool NeedsAutorenewing(const Company *c, bool use_renew_setting=true) const
Function to tell if a vehicle needs to be autorenewed.
Definition: vehicle.cpp:145
void UpdateVisualEffect(bool allow_power_change=true)
Update the cached visual effect.
Definition: vehicle.cpp:2664
void LeaveUnbunchingDepot()
Leave an unbunching depot and calculate the next departure time for shared order vehicles.
Definition: vehicle.cpp:2514
int8_t y_offs
y offset for vehicle sprite
Definition: vehicle_base.h:322
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition: vehicle_base.h:632
debug_inline bool IsFrontEngine() const
Check if the vehicle is a front engine.
Definition: vehicle_base.h:945
Vehicle * previous_shared
NOSAVE: pointer to the previous vehicle in the shared order chain.
Definition: vehicle_base.h:253
VehicleOrderID GetNumManualOrders() const
Get the number of manually added orders this vehicle has.
Definition: vehicle_base.h:744
int8_t trip_occupancy
NOSAVE: Occupancy of vehicle of the current trip (updated after leaving a station).
Definition: vehicle_base.h:347
int8_t x_bb_offs
x offset of vehicle bounding box
Definition: vehicle_base.h:319
Order current_order
The current order (+ status, like: loading)
Definition: vehicle_base.h:356
void PreDestructor()
Destroy all stuff that (still) needs the virtual functions to work properly.
Definition: vehicle.cpp:826
TimerGameTick::TickCounter last_loading_tick
Last TimerGameTick::counter tick that the vehicle has stopped at a station and could possibly leave w...
Definition: vehicle_base.h:339
CargoID cargo_type
type of cargo this vehicle is carrying
Definition: vehicle_base.h:342
void HandlePathfindingResult(bool path_found)
Handle the pathfinding result, especially the lost status.
Definition: vehicle.cpp:791
int8_t x_offs
x offset for vehicle sprite
Definition: vehicle_base.h:321
int32_t y_pos
y coordinate.
Definition: vehicle_base.h:305
int32_t x_pos
x coordinate.
Definition: vehicle_base.h:304
const GRFFile * GetGRF() const
Retrieve the NewGRF the vehicle is tied to.
Definition: vehicle.cpp:757
OrderList * orders
Pointer to the order list for this vehicle.
Definition: vehicle_base.h:359
uint32_t GetDisplayMinPowerToWeight() const
Calculates the minimum power-to-weight ratio using the maximum weight of the ground vehicle.
Definition: vehicle.cpp:3259
uint8_t y_extent
y-extent of vehicle bounding box
Definition: vehicle_base.h:317
virtual ClosestDepot FindClosestDepot()
Find the closest depot for this vehicle and tell us the location, DestinationID and whether we should...
Definition: vehicle_base.h:805
void UpdateViewport(bool dirty)
Update the vehicle on the viewport, updating the right hash and setting the new coordinates.
Definition: vehicle.cpp:1735
Money value
Value of the vehicle.
Definition: vehicle_base.h:275
bool MarkAllViewportsDirty() const
Marks viewports dirty where the vehicle's image is.
Definition: vehicle.cpp:1774
uint16_t refit_cap
Capacity left over from before last refit.
Definition: vehicle_base.h:345
uint8_t vehstatus
Status.
Definition: vehicle_base.h:354
VehicleCache vcache
Cache of often used vehicle values.
Definition: vehicle_base.h:364
uint32_t motion_counter
counter to occasionally play a vehicle sound.
Definition: vehicle_base.h:331
uint32_t GetGRFID() const
Retrieve the GRF ID of the NewGRF the vehicle is tied to.
Definition: vehicle.cpp:767
Order * GetFirstOrder() const
Get the first order of the vehicles order list.
Definition: vehicle_base.h:705
GroundVehicleCache * GetGroundVehicleCache()
Access the ground vehicle cache of the vehicle.
Definition: vehicle.cpp:3155
virtual void OnNewEconomyDay()
Calls the new economy day handler of the vehicle.
Definition: vehicle_base.h:582
Vehicle ** hash_tile_current
NOSAVE: Cache of the current hash chain.
Definition: vehicle_base.h:286
virtual void OnNewCalendarDay()
Calls the new calendar day handler of the vehicle.
Definition: vehicle_base.h:577
int8_t y_bb_offs
y offset of vehicle bounding box
Definition: vehicle_base.h:320
virtual int GetCurrentMaxSpeed() const
Calculates the maximum speed of the vehicle under its current conditions.
Definition: vehicle_base.h:536
bool HasFullLoadOrder() const
Check if the current vehicle has a full load order.
Definition: vehicle.cpp:2465
virtual void PlayLeaveStationSound([[maybe_unused]] bool force=false) const
Play the sound associated with leaving the station.
Definition: vehicle_base.h:472
virtual bool IsPrimaryVehicle() const
Whether this is the primary vehicle in the chain.
Definition: vehicle_base.h:477
void BeginLoading()
Prepare everything to begin the loading when arriving at a station.
Definition: vehicle.cpp:2203
Vehicle * hash_tile_next
NOSAVE: Next vehicle in the tile location hash.
Definition: vehicle_base.h:284
uint16_t cur_speed
current speed
Definition: vehicle_base.h:328
Vehicle * previous
NOSAVE: pointer to the previous vehicle in the chain.
Definition: vehicle_base.h:249
bool HasEngineType() const
Check whether Vehicle::engine_type has any meaning.
Definition: vehicle.cpp:731
TimerGameCalendar::Date age
Age in calendar days.
Definition: vehicle_base.h:292
bool IsWaitingForUnbunching() const
Check whether a vehicle inside a depot is waiting for unbunching.
Definition: vehicle.cpp:2561
TextEffectID fill_percent_te_id
a text-effect id to a loading indicator object
Definition: vehicle_base.h:325
IterateWrapper Orders() const
Returns an iterable ensemble of orders of a vehicle.
void SetNext(Vehicle *next)
Set the next vehicle of this vehicle.
Definition: vehicle.cpp:2937
Vehicle * FirstShared() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:726
uint8_t breakdowns_since_last_service
Counter for the amount of breakdowns.
Definition: vehicle_base.h:301
Vehicle * next
pointer to the next vehicle in the chain
Definition: vehicle_base.h:248
TimerGameCalendar::Date max_age
Maximum age.
Definition: vehicle_base.h:294
MutableSpriteCache sprite_cache
Cache of sprites and values related to recalculating them, see MutableSpriteCache.
Definition: vehicle_base.h:368
uint16_t reliability
Reliability.
Definition: vehicle_base.h:297
uint32_t GetDisplayMaxWeight() const
Calculates the maximum weight of the ground vehicle when loaded.
Definition: vehicle.cpp:3244
Vehicle * NextShared() const
Get the next vehicle of the shared vehicle chain.
Definition: vehicle_base.h:714
void RemoveFromShared()
Removes the vehicle from the shared order list.
Definition: vehicle.cpp:2989
bool HandleBreakdown()
Handle all of the aspects of a vehicle breakdown This includes adding smoke and sounds,...
Definition: vehicle.cpp:1363
Vehicle * GetNextVehicle() const
Get the next real (non-articulated part) vehicle in the consist.
debug_inline bool IsGroundVehicle() const
Check if the vehicle is a ground vehicle.
Definition: vehicle_base.h:515
void UpdatePositionAndViewport()
Update the position of the vehicle, and update the viewport.
Definition: vehicle.cpp:1764
Vehicle(VehicleType type=VEH_INVALID)
Vehicle constructor.
Definition: vehicle.cpp:361
Rect coord
NOSAVE: Graphical bounding box of the vehicle, i.e. what to redraw on moves.
Definition: vehicle_base.h:279
uint16_t reliability_spd_dec
Reliability decrease speed.
Definition: vehicle_base.h:298
uint8_t tick_counter
Increased by one for each tick.
Definition: vehicle_base.h:350
virtual bool IsInDepot() const
Check whether the vehicle is in the depot.
Definition: vehicle_base.h:548
TileIndex tile
Current tile index.
Definition: vehicle_base.h:264
virtual bool Tick()
Calls the tick handler of the vehicle.
Definition: vehicle_base.h:572
TileIndex dest_tile
Heading for this tile.
Definition: vehicle_base.h:271
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:190
bool HasConditionalOrder() const
Check if the current vehicle has a conditional order.
Definition: vehicle.cpp:2477
void UpdatePosition()
Update the position of the vehicle.
Definition: vehicle.cpp:1693
StationID last_station_visited
The last station we stopped at.
Definition: vehicle_base.h:337
void ResetRefitCaps()
Reset all refit_cap in the consist to cargo_cap.
Definition: vehicle.cpp:2411
uint8_t breakdown_chance
Current chance of breakdowns.
Definition: vehicle_base.h:302
void ShowVisualEffect() const
Draw visual effects (smoke and/or sparks) for a vehicle chain.
Definition: vehicle.cpp:2787
Owner owner
Which company owns the vehicle?
Definition: vehicle_base.h:309
Order * GetLastOrder() const
Returns the last order of a vehicle, or nullptr if it doesn't exists.
Definition: vehicle_base.h:931
UnitID unitnumber
unit number, for display purposes only
Definition: vehicle_base.h:326
Vehicle * next_shared
pointer to the next vehicle that shares the order
Definition: vehicle_base.h:252
bool NeedsAutomaticServicing() const
Checks if the current order should be interrupted for a service-in-depot order.
Definition: vehicle.cpp:272
void DeleteUnreachedImplicitOrders()
Delete all implicit orders which were not reached.
Definition: vehicle.cpp:2164
Vehicle ** hash_viewport_prev
NOSAVE: Previous vehicle in the visual location hash.
Definition: vehicle_base.h:282
Vehicle * hash_viewport_next
NOSAVE: Next vehicle in the visual location hash.
Definition: vehicle_base.h:281
Data structure for viewport, display of a part of the world.
Definition: viewport_type.h:22
int top
Screen coordinate top edge of the viewport.
Definition: viewport_type.h:24
int width
Screen width of the viewport.
Definition: viewport_type.h:25
ZoomLevel zoom
The zoom level of the viewport.
Definition: viewport_type.h:33
int virtual_top
Virtual top coordinate.
Definition: viewport_type.h:29
int virtual_left
Virtual left coordinate.
Definition: viewport_type.h:28
int left
Screen coordinate left edge of the viewport.
Definition: viewport_type.h:23
int height
Screen height of the viewport.
Definition: viewport_type.h:26
VehicleEnterTileStatus
The returned bits of VehicleEnterTile.
Definition: tile_cmd.h:21
int GetTileMaxPixelZ(TileIndex tile)
Get top height of the tile.
Definition: tile_map.h:312
static debug_inline TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition: tile_map.h:96
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition: tile_map.h:150
static const int MAX_VEHICLE_PIXEL_Y
Maximum height of a vehicle in pixels in #ZOOM_BASE.
Definition: tile_type.h:22
static const uint TILE_SIZE
Tile size in world coordinates.
Definition: tile_type.h:15
@ MP_STATION
A tile of a station.
Definition: tile_type.h:53
static const int MAX_VEHICLE_PIXEL_X
Maximum width of a vehicle in pixels in #ZOOM_BASE.
Definition: tile_type.h:21
Definition of Interval and OneShot timers.
Definition of the game-calendar-timer.
Definition of the game-economy-timer.
Definition of the tick-based game-timer.
Functions related to time tabling.
void UpdateVehicleTimetable(Vehicle *v, bool travelling)
Update the timetable for the vehicle.
bool TracksOverlap(TrackBits bits)
Checks if the given tracks overlap, ie form a crossing.
Definition: track_func.h:645
TrackBits
Allow incrementing of Track variables.
Definition: track_type.h:35
@ TRACK_BIT_DEPOT
Bitflag for a depot.
Definition: track_type.h:53
Base for the train class.
@ VRF_LEAVING_STATION
Train is just leaving a station.
Definition: train.h:33
@ VRF_TOGGLE_REVERSE
Used for vehicle var 0xFE bit 8 (toggled each time the train is reversed, accurate for first vehicle ...
Definition: train.h:31
@ VRF_REVERSE_DIRECTION
Reverse the visible direction of the vehicle.
Definition: train.h:28
@ CCF_ARRANGE
Valid changes for arranging the consist in a depot.
Definition: train.h:52
@ TFP_NONE
Normal operation.
Definition: train.h:38
Command definitions related to trains.
TransparencyOption
Transparency option bits: which position in _transparency_opt stands for which transparency.
Definition: transparency.h:22
@ TO_INVALID
Invalid transparency option.
Definition: transparency.h:33
bool IsTransparencySet(TransparencyOption to)
Check if the transparency option bit is set and if we aren't in the game menu (there's never transpar...
Definition: transparency.h:48
bool IsInvisibilitySet(TransparencyOption to)
Check if the invisibility option bit is set and if we aren't in the game menu (there's never transpar...
Definition: transparency.h:59
uint16_t UnitID
Type for the company global vehicle unit number.
Map accessors for tunnels.
bool IsTunnelTile(Tile t)
Is this a tunnel (entrance)?
Definition: tunnel_map.h:34
PaletteID GetVehiclePalette(const Vehicle *v)
Get the colour map for a vehicle.
Definition: vehicle.cpp:2152
static Vehicle * VehicleFromPosXY(int x, int y, void *data, VehicleFromPosProc *proc, bool find_first)
Helper function for FindVehicleOnPos/HasVehicleOnPos.
Definition: vehicle.cpp:418
bool CanBuildVehicleInfrastructure(VehicleType type, uint8_t subtype)
Check whether we can build infrastructure for the given vehicle type.
Definition: vehicle.cpp:1922
CommandCost EnsureNoVehicleOnGround(TileIndex tile)
Ensure there is no vehicle at the ground at the given position.
Definition: vehicle.cpp:546
bool VehiclesHaveSameEngineList(const Vehicle *v1, const Vehicle *v2)
Checks if two vehicle chains have the same list of engines.
Definition: vehicle.cpp:3272
bool VehiclesHaveSameOrderList(const Vehicle *v1, const Vehicle *v2)
Checks if two vehicles have the same list of orders.
Definition: vehicle.cpp:3289
static void SpawnAdvancedVisualEffect(const Vehicle *v)
Call CBID_VEHICLE_SPAWN_VISUAL_EFFECT and spawn requested effects.
Definition: vehicle.cpp:2732
void VehicleEnterDepot(Vehicle *v)
Vehicle entirely entered the depot, update its status, orders, vehicle windows, service it,...
Definition: vehicle.cpp:1552
const Livery * GetEngineLivery(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v, uint8_t livery_setting)
Determines the livery for a vehicle.
Definition: vehicle.cpp:2064
void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8_t num_vehicles)
Calculates the set of vehicles that will be affected by a given selection.
Definition: vehicle.cpp:3218
bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
Checks whether a vehicle in on a specific location.
Definition: vehicle.cpp:461
Vehicle * CheckClickOnVehicle(const Viewport *vp, int x, int y)
Find the vehicle close to the clicked coordinates.
Definition: vehicle.cpp:1248
UnitID GetFreeUnitNumber(VehicleType type)
Get an unused unit number for a vehicle (if allowed).
Definition: vehicle.cpp:1895
void RunVehicleCalendarDayProc()
Age all vehicles, spreading out the action using the current TimerGameCalendar::date_fract.
Definition: vehicle.cpp:937
static Vehicle * VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc, bool find_first)
Helper function for FindVehicleOnPos/HasVehicleOnPos.
Definition: vehicle.cpp:476
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:346
static Vehicle * GetVehicleTunnelBridgeProc(Vehicle *v, void *data)
Procedure called for every vehicle found in tunnel/bridge in the hash map.
Definition: vehicle.cpp:560
VehiclePool _vehicle_pool("Vehicle")
The pool with all our precious vehicles.
void VehicleServiceInDepot(Vehicle *v)
Service a vehicle and all subsequent vehicles in the consist.
Definition: vehicle.cpp:167
CommandCost EnsureNoTrainOnTrackBits(TileIndex tile, TrackBits track_bits)
Tests if a vehicle interacts with the specified track bits.
Definition: vehicle.cpp:608
void FindVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition: vehicle.cpp:445
static void RunEconomyVehicleDayProc()
Increases the day counter for all vehicles and calls 1-day and 32-day handlers.
Definition: vehicle.cpp:954
LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_type, const Vehicle *v)
Determines the LiveryScheme for a vehicle.
Definition: vehicle.cpp:1970
VehicleEnterTileStatus VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y)
Call the tile callback function for a vehicle entering a tile.
Definition: vehicle.cpp:1838
void ViewportAddVehicles(DrawPixelInfo *dpi)
Add the vehicle sprites that should be drawn at a part of the screen.
Definition: vehicle.cpp:1154
GetNewVehiclePosResult GetNewVehiclePos(const Vehicle *v)
Get position information of a vehicle when moving one pixel in the direction it is facing.
Definition: vehicle.cpp:1784
bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Checks whether a vehicle is on a specific location.
Definition: vehicle.cpp:520
void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition: vehicle.cpp:505
StringID GetVehicleCannotUseStationReason(const Vehicle *v, const Station *st)
Get reason string why this station can't be used by the given vehicle.
Definition: vehicle.cpp:3104
void DecreaseVehicleValue(Vehicle *v)
Decrease the value of a vehicle.
Definition: vehicle.cpp:1301
void EconomyAgeVehicle(Vehicle *v)
Update economy age of a vehicle.
Definition: vehicle.cpp:1429
uint8_t CalcPercentVehicleFilled(const Vehicle *front, StringID *colour)
Calculates how full a vehicle is.
Definition: vehicle.cpp:1493
CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle *ignore)
Finds vehicle in tunnel / bridge.
Definition: vehicle.cpp:575
PaletteID GetEnginePalette(EngineID engine_type, CompanyID company)
Get the colour map for an engine.
Definition: vehicle.cpp:2142
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:317
bool CanVehicleUseStation(EngineID engine_type, const Station *st)
Can this station be used by the given engine type?
Definition: vehicle.cpp:3058
void AgeVehicle(Vehicle *v)
Update age of a vehicle.
Definition: vehicle.cpp:1441
void VehicleEnteredDepotThisTick(Vehicle *v)
Adds a vehicle to the list of vehicles that visited a depot this tick.
Definition: vehicle.cpp:921
static Vehicle * EnsureNoVehicleProcZ(Vehicle *v, void *data)
Callback that returns 'real' vehicles lower or at height *(int*)data .
Definition: vehicle.cpp:531
std::map< VehicleID, bool > AutoreplaceMap
List of vehicles that should check for autoreplace this tick.
Definition: vehicle.cpp:694
static bool PreviousOrderIsUnbunching(const Vehicle *v)
Check if the previous order is a depot unbunching order.
Definition: vehicle.cpp:2501
static void DoDrawVehicle(const Vehicle *v)
Add vehicle sprite for drawing to the screen.
Definition: vehicle.cpp:1124
@ VF_STOP_LOADING
Don't load anymore during the next load cycle.
Definition: vehicle_base.h:51
@ VF_CARGO_UNLOADING
Vehicle is unloading cargo.
Definition: vehicle_base.h:46
@ VF_PATHFINDER_LOST
Vehicle's pathfinder is lost.
Definition: vehicle_base.h:52
@ VF_LOADING_FINISHED
Vehicle has finished loading.
Definition: vehicle_base.h:45
VisualEffectSpawnModel
Models for spawning visual effects.
Definition: vehicle_base.h:101
@ VESM_ELECTRIC
Electric model.
Definition: vehicle_base.h:105
@ VESM_STEAM
Steam model.
Definition: vehicle_base.h:103
@ VESM_DIESEL
Diesel model.
Definition: vehicle_base.h:104
@ VESM_NONE
No visual effect.
Definition: vehicle_base.h:102
@ VS_UNCLICKABLE
Vehicle is not clickable by the user (shadow vehicles).
Definition: vehicle_base.h:35
@ VS_TRAIN_SLOWING
Train is slowing down.
Definition: vehicle_base.h:37
@ VS_AIRCRAFT_BROKEN
Aircraft is broken down.
Definition: vehicle_base.h:39
@ VS_SHADOW
Vehicle is a shadow vehicle.
Definition: vehicle_base.h:38
@ VS_STOPPED
Vehicle is stopped by the player.
Definition: vehicle_base.h:34
@ VS_HIDDEN
Vehicle is not visible.
Definition: vehicle_base.h:33
@ VS_CRASHED
Vehicle is crashed.
Definition: vehicle_base.h:40
@ VS_DEFPAL
Use default vehicle palette.
Definition: vehicle_base.h:36
@ VE_TYPE_DEFAULT
Use default from engine class.
Definition: vehicle_base.h:88
@ VE_TYPE_COUNT
Number of bits used for the effect type.
Definition: vehicle_base.h:87
@ VE_OFFSET_CENTRE
Value of offset corresponding to a position above the centre of the vehicle.
Definition: vehicle_base.h:84
@ VE_TYPE_ELECTRIC
Electric sparks.
Definition: vehicle_base.h:91
@ VE_TYPE_START
First bit used for the type of effect.
Definition: vehicle_base.h:86
@ VE_OFFSET_COUNT
Number of bits used for the offset.
Definition: vehicle_base.h:83
@ VE_ADVANCED_EFFECT
Flag for advanced effects.
Definition: vehicle_base.h:94
@ VE_DISABLE_EFFECT
Flag to disable visual effect.
Definition: vehicle_base.h:93
@ VE_TYPE_STEAM
Steam plumes.
Definition: vehicle_base.h:89
@ VE_TYPE_DIESEL
Diesel fumes.
Definition: vehicle_base.h:90
@ VE_DEFAULT
Default value to indicate that visual effect should be based on engine class.
Definition: vehicle_base.h:97
@ VE_OFFSET_START
First bit that contains the offset (0 = front, 8 = centre, 15 = rear)
Definition: vehicle_base.h:82
@ VE_DISABLE_WAGON_POWER
Flag to disable wagon power.
Definition: vehicle_base.h:95
static const int32_t INVALID_COORD
Sentinel for an invalid coordinate.
Command definitions for vehicles.
Functions related to vehicles.
static const TimerGameEconomy::Date VEHICLE_PROFIT_MIN_AGE
Only vehicles older than this have a meaningful profit.
Definition: vehicle_func.h:28
bool IsCompanyBuildableVehicleType(VehicleType type)
Is the given vehicle type buildable by a company?
Definition: vehicle_func.h:91
@ VIWD_MODIFY_ORDERS
Other order modifications.
Definition: vehicle_gui.h:36
WindowClass GetWindowClassForVehicleType(VehicleType vt)
Get WindowClass for vehicle list of given vehicle type.
Definition: vehicle_gui.h:97
@ EIT_ON_MAP
Vehicle drawn in viewport.
Definition: vehicle_type.h:79
VehicleType
Available vehicle types.
Definition: vehicle_type.h:21
@ VEH_ROAD
Road vehicle type.
Definition: vehicle_type.h:25
@ VEH_DISASTER
Disaster vehicle type.
Definition: vehicle_type.h:32
@ VEH_AIRCRAFT
Aircraft vehicle type.
Definition: vehicle_type.h:27
@ VEH_SHIP
Ship vehicle type.
Definition: vehicle_type.h:26
@ VEH_EFFECT
Effect vehicle type (smoke, explosions, sparks, bubbles)
Definition: vehicle_type.h:31
@ VEH_TRAIN
Train vehicle type.
Definition: vehicle_type.h:24
static const VehicleID INVALID_VEHICLE
Constant representing a non-existing vehicle.
Definition: vehicle_type.h:54
static const uint VEHICLE_LENGTH
The length of a vehicle in tile units.
Definition: vehicle_type.h:69
DepotCommand
Flags for goto depot commands.
Definition: vehicle_type.h:57
@ DontCancel
Don't cancel current goto depot command if any.
@ Service
The vehicle will leave the depot right after arrival (service only)
@ WID_VV_START_STOP
Start or stop this vehicle, and show information about the current state.
Functions and type for generating vehicle lists.
void StartSpriteCombine()
Starts a block of sprites, which are "combined" into a single bounding box.
Definition: viewport.cpp:767
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:671
void EndSpriteCombine()
Terminates a block of sprites started by StartSpriteCombine.
Definition: viewport.cpp:777
Functions related to (drawing on) viewports.
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition: window.cpp:1140
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3119
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:3211
void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, WidgetID widget_index)
Mark a particular widget in a particular window as dirty (in need of repainting)
Definition: window.cpp:3106
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3093
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:3228
@ WC_ROADVEH_LIST
Road vehicle list; Window numbers:
Definition: window_type.h:314
@ WC_VEHICLE_ORDERS
Vehicle orders; Window numbers:
Definition: window_type.h:212
@ WC_VEHICLE_DEPOT
Depot view; Window numbers:
Definition: window_type.h:351
@ WC_SHIPS_LIST
Ships list; Window numbers:
Definition: window_type.h:320
@ WC_STATION_VIEW
Station view; Window numbers:
Definition: window_type.h:345
@ WC_TRAINS_LIST
Trains list; Window numbers:
Definition: window_type.h:308
@ WC_VEHICLE_REFIT
Vehicle refit; Window numbers:
Definition: window_type.h:206
@ WC_VEHICLE_DETAILS
Vehicle details; Window numbers:
Definition: window_type.h:200
@ WC_COMPANY
Company view; Window numbers:
Definition: window_type.h:369
@ WC_VEHICLE_VIEW
Vehicle view; Window numbers:
Definition: window_type.h:339
@ WC_VEHICLE_TIMETABLE
Vehicle timetable; Window numbers:
Definition: window_type.h:224
@ WC_AIRCRAFT_LIST
Aircraft list; Window numbers:
Definition: window_type.h:326
Functions related to zooming.
int ScaleByZoom(int value, ZoomLevel zoom)
Scale by zoom level, usually shift left (when zoom > ZOOM_LVL_MIN) When shifting right,...
Definition: zoom_func.h:22