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