OpenTTD
vehicle.cpp
Go to the documentation of this file.
1 /* $Id: vehicle.cpp 27592 2016-05-29 19:08:01Z frosch $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
12 #include "stdafx.h"
13 #include "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 
56 #include "table/strings.h"
57 
58 #include "safeguards.h"
59 
60 #define GEN_HASH(x, y) ((GB((y), 6 + ZOOM_LVL_SHIFT, 6) << 6) + GB((x), 7 + ZOOM_LVL_SHIFT, 6))
61 
62 VehicleID _new_vehicle_id;
65 
66 
68 VehiclePool _vehicle_pool("Vehicle");
70 
71 
77 bool Vehicle::NeedsAutorenewing(const Company *c, bool use_renew_setting) const
78 {
79  /* We can always generate the Company pointer when we have the vehicle.
80  * However this takes time and since the Company pointer is often present
81  * when this function is called then it's faster to pass the pointer as an
82  * argument rather than finding it again. */
83  assert(c == Company::Get(this->owner));
84 
85  if (use_renew_setting && !c->settings.engine_renew) return false;
86  if (this->age - this->max_age < (c->settings.engine_renew_months * 30)) return false;
87 
88  /* Only engines need renewing */
89  if (this->type == VEH_TRAIN && !Train::From(this)->IsEngine()) return false;
90 
91  return true;
92 }
93 
100 {
101  assert(v != NULL);
102  SetWindowDirty(WC_VEHICLE_DETAILS, v->index); // ensure that last service date and reliability are updated
103 
104  do {
107  v->reliability = v->GetEngine()->reliability;
108  /* Prevent vehicles from breaking down directly after exiting the depot. */
109  v->breakdown_chance /= 4;
110  v = v->Next();
111  } while (v != NULL && v->HasEngineType());
112 }
113 
121 {
122  /* Stopped or crashed vehicles will not move, as such making unmovable
123  * vehicles to go for service is lame. */
124  if (this->vehstatus & (VS_STOPPED | VS_CRASHED)) return false;
125 
126  /* Are we ready for the next service cycle? */
127  const Company *c = Company::Get(this->owner);
128  if (this->ServiceIntervalIsPercent() ?
129  (this->reliability >= this->GetEngine()->reliability * (100 - this->GetServiceInterval()) / 100) :
130  (this->date_of_last_service + this->GetServiceInterval() >= _date)) {
131  return false;
132  }
133 
134  /* If we're servicing anyway, because we have not disabled servicing when
135  * there are no breakdowns or we are playing with breakdowns, bail out. */
138  return true;
139  }
140 
141  /* Test whether there is some pending autoreplace.
142  * Note: We do this after the service-interval test.
143  * There are a lot more reasons for autoreplace to fail than we can test here reasonably. */
144  bool pending_replace = false;
145  Money needed_money = c->settings.engine_renew_money;
146  if (needed_money > c->money) return false;
147 
148  for (const Vehicle *v = this; v != NULL; v = (v->type == VEH_TRAIN) ? Train::From(v)->GetNextUnit() : NULL) {
149  bool replace_when_old = false;
150  EngineID new_engine = EngineReplacementForCompany(c, v->engine_type, v->group_id, &replace_when_old);
151 
152  /* Check engine availability */
153  if (new_engine == INVALID_ENGINE || !HasBit(Engine::Get(new_engine)->company_avail, v->owner)) continue;
154  /* Is the vehicle old if we are not always replacing? */
155  if (replace_when_old && !v->NeedsAutorenewing(c, false)) continue;
156 
157  /* Check refittability */
158  uint32 available_cargo_types, union_mask;
159  GetArticulatedRefitMasks(new_engine, true, &union_mask, &available_cargo_types);
160  /* Is there anything to refit? */
161  if (union_mask != 0) {
163  /* We cannot refit to mixed cargoes in an automated way */
164  if (IsArticulatedVehicleCarryingDifferentCargoes(v, &cargo_type)) continue;
165 
166  /* Did the old vehicle carry anything? */
167  if (cargo_type != CT_INVALID) {
168  /* We can't refit the vehicle to carry the cargo we want */
169  if (!HasBit(available_cargo_types, cargo_type)) continue;
170  }
171  }
172 
173  /* Check money.
174  * We want 2*(the price of the new vehicle) without looking at the value of the vehicle we are going to sell. */
175  pending_replace = true;
176  needed_money += 2 * Engine::Get(new_engine)->GetCost();
177  if (needed_money > c->money) return false;
178  }
179 
180  return pending_replace;
181 }
182 
189 {
190  if (this->HasDepotOrder()) return false;
191  if (this->current_order.IsType(OT_LOADING)) return false;
192  if (this->current_order.IsType(OT_GOTO_DEPOT) && this->current_order.GetDepotOrderType() != ODTFB_SERVICE) return false;
193  return NeedsServicing();
194 }
195 
196 uint Vehicle::Crash(bool flooded)
197 {
198  assert((this->vehstatus & VS_CRASHED) == 0);
199  assert(this->Previous() == NULL); // IsPrimaryVehicle fails for free-wagon-chains
200 
201  uint pass = 0;
202  /* Stop the vehicle. */
203  if (this->IsPrimaryVehicle()) this->vehstatus |= VS_STOPPED;
204  /* crash all wagons, and count passengers */
205  for (Vehicle *v = this; v != NULL; v = v->Next()) {
206  /* We do not transfer reserver cargo back, so TotalCount() instead of StoredCount() */
207  if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) pass += v->cargo.TotalCount();
208  v->vehstatus |= VS_CRASHED;
209  v->MarkAllViewportsDirty();
210  }
211 
212  /* Dirty some windows */
217 
218  delete this->cargo_payment;
219  assert(this->cargo_payment == NULL); // cleared by ~CargoPayment
220 
221  return RandomRange(pass + 1); // Randomise deceased passengers.
222 }
223 
224 
233 void ShowNewGrfVehicleError(EngineID engine, StringID part1, StringID part2, GRFBugs bug_type, bool critical)
234 {
235  const Engine *e = Engine::Get(engine);
236  GRFConfig *grfconfig = GetGRFConfig(e->GetGRFID());
237 
238  /* Missing GRF. Nothing useful can be done in this situation. */
239  if (grfconfig == NULL) return;
240 
241  if (!HasBit(grfconfig->grf_bugs, bug_type)) {
242  SetBit(grfconfig->grf_bugs, bug_type);
243  SetDParamStr(0, grfconfig->GetName());
244  SetDParam(1, engine);
245  ShowErrorMessage(part1, part2, WL_CRITICAL);
247  }
248 
249  /* debug output */
250  char buffer[512];
251 
252  SetDParamStr(0, grfconfig->GetName());
253  GetString(buffer, part1, lastof(buffer));
254  DEBUG(grf, 0, "%s", buffer + 3);
255 
256  SetDParam(1, engine);
257  GetString(buffer, part2, lastof(buffer));
258  DEBUG(grf, 0, "%s", buffer + 3);
259 }
260 
267 {
268  /* show a warning once for each engine in whole game and once for each GRF after each game load */
269  const Engine *engine = u->GetEngine();
270  uint32 grfid = engine->grf_prop.grffile->grfid;
271  GRFConfig *grfconfig = GetGRFConfig(grfid);
272  if (GamelogGRFBugReverse(grfid, engine->grf_prop.local_id) || !HasBit(grfconfig->grf_bugs, GBUG_VEH_LENGTH)) {
273  ShowNewGrfVehicleError(u->engine_type, STR_NEWGRF_BROKEN, STR_NEWGRF_BROKEN_VEHICLE_LENGTH, GBUG_VEH_LENGTH, true);
274  }
275 }
276 
282 {
283  this->type = type;
284  this->coord.left = INVALID_COORD;
285  this->group_id = DEFAULT_GROUP;
286  this->fill_percent_te_id = INVALID_TE_ID;
287  this->first = this;
288  this->colourmap = PAL_NONE;
289  this->cargo_age_counter = 1;
290  this->last_station_visited = INVALID_STATION;
291  this->last_loading_station = INVALID_STATION;
292 }
293 
299 {
300  return GB(Random(), 0, 8);
301 }
302 
303 /* Size of the hash, 6 = 64 x 64, 7 = 128 x 128. Larger sizes will (in theory) reduce hash
304  * lookup times at the expense of memory usage. */
305 const int HASH_BITS = 7;
306 const int HASH_SIZE = 1 << HASH_BITS;
307 const int HASH_MASK = HASH_SIZE - 1;
308 const int TOTAL_HASH_SIZE = 1 << (HASH_BITS * 2);
309 const int TOTAL_HASH_MASK = TOTAL_HASH_SIZE - 1;
310 
311 /* Resolution of the hash, 0 = 1*1 tile, 1 = 2*2 tiles, 2 = 4*4 tiles, etc.
312  * Profiling results show that 0 is fastest. */
313 const int HASH_RES = 0;
314 
315 static Vehicle *_vehicle_tile_hash[TOTAL_HASH_SIZE];
316 
317 static Vehicle *VehicleFromTileHash(int xl, int yl, int xu, int yu, void *data, VehicleFromPosProc *proc, bool find_first)
318 {
319  for (int y = yl; ; y = (y + (1 << HASH_BITS)) & (HASH_MASK << HASH_BITS)) {
320  for (int x = xl; ; x = (x + 1) & HASH_MASK) {
321  Vehicle *v = _vehicle_tile_hash[(x + y) & TOTAL_HASH_MASK];
322  for (; v != NULL; v = v->hash_tile_next) {
323  Vehicle *a = proc(v, data);
324  if (find_first && a != NULL) return a;
325  }
326  if (x == xu) break;
327  }
328  if (y == yu) break;
329  }
330 
331  return NULL;
332 }
333 
334 
346 static Vehicle *VehicleFromPosXY(int x, int y, void *data, VehicleFromPosProc *proc, bool find_first)
347 {
348  const int COLL_DIST = 6;
349 
350  /* Hash area to scan is from xl,yl to xu,yu */
351  int xl = GB((x - COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS);
352  int xu = GB((x + COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS);
353  int yl = GB((y - COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS) << HASH_BITS;
354  int yu = GB((y + COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS) << HASH_BITS;
355 
356  return VehicleFromTileHash(xl, yl, xu, yu, data, proc, find_first);
357 }
358 
373 void FindVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
374 {
375  VehicleFromPosXY(x, y, data, proc, false);
376 }
377 
389 bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
390 {
391  return VehicleFromPosXY(x, y, data, proc, true) != NULL;
392 }
393 
404 static Vehicle *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc, bool find_first)
405 {
406  int x = GB(TileX(tile), HASH_RES, HASH_BITS);
407  int y = GB(TileY(tile), HASH_RES, HASH_BITS) << HASH_BITS;
408 
409  Vehicle *v = _vehicle_tile_hash[(x + y) & TOTAL_HASH_MASK];
410  for (; v != NULL; v = v->hash_tile_next) {
411  if (v->tile != tile) continue;
412 
413  Vehicle *a = proc(v, data);
414  if (find_first && a != NULL) return a;
415  }
416 
417  return NULL;
418 }
419 
433 void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
434 {
435  VehicleFromPos(tile, data, proc, false);
436 }
437 
448 bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
449 {
450  return VehicleFromPos(tile, data, proc, true) != NULL;
451 }
452 
459 static Vehicle *EnsureNoVehicleProcZ(Vehicle *v, void *data)
460 {
461  int z = *(int*)data;
462 
463  if (v->type == VEH_DISASTER || (v->type == VEH_AIRCRAFT && v->subtype == AIR_SHADOW)) return NULL;
464  if (v->z_pos > z) return NULL;
465 
466  return v;
467 }
468 
475 {
476  int z = GetTileMaxPixelZ(tile);
477 
478  /* Value v is not safe in MP games, however, it is used to generate a local
479  * error message only (which may be different for different machines).
480  * Such a message does not affect MP synchronisation.
481  */
482  Vehicle *v = VehicleFromPos(tile, &z, &EnsureNoVehicleProcZ, true);
483  if (v != NULL) return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
484  return CommandCost();
485 }
486 
489 {
490  if (v->type != VEH_TRAIN && v->type != VEH_ROAD && v->type != VEH_SHIP) return NULL;
491  if (v == (const Vehicle *)data) return NULL;
492 
493  return v;
494 }
495 
504 {
505  /* Value v is not safe in MP games, however, it is used to generate a local
506  * error message only (which may be different for different machines).
507  * Such a message does not affect MP synchronisation.
508  */
509  Vehicle *v = VehicleFromPos(tile, const_cast<Vehicle *>(ignore), &GetVehicleTunnelBridgeProc, true);
510  if (v == NULL) v = VehicleFromPos(endtile, const_cast<Vehicle *>(ignore), &GetVehicleTunnelBridgeProc, true);
511 
512  if (v != NULL) return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
513  return CommandCost();
514 }
515 
516 static Vehicle *EnsureNoTrainOnTrackProc(Vehicle *v, void *data)
517 {
518  TrackBits rail_bits = *(TrackBits *)data;
519 
520  if (v->type != VEH_TRAIN) return NULL;
521 
522  Train *t = Train::From(v);
523  if ((t->track != rail_bits) && !TracksOverlap(t->track | rail_bits)) return NULL;
524 
525  return v;
526 }
527 
537 {
538  /* Value v is not safe in MP games, however, it is used to generate a local
539  * error message only (which may be different for different machines).
540  * Such a message does not affect MP synchronisation.
541  */
542  Vehicle *v = VehicleFromPos(tile, &track_bits, &EnsureNoTrainOnTrackProc, true);
543  if (v != NULL) return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
544  return CommandCost();
545 }
546 
547 static void UpdateVehicleTileHash(Vehicle *v, bool remove)
548 {
549  Vehicle **old_hash = v->hash_tile_current;
550  Vehicle **new_hash;
551 
552  if (remove) {
553  new_hash = NULL;
554  } else {
555  int x = GB(TileX(v->tile), HASH_RES, HASH_BITS);
556  int y = GB(TileY(v->tile), HASH_RES, HASH_BITS) << HASH_BITS;
557  new_hash = &_vehicle_tile_hash[(x + y) & TOTAL_HASH_MASK];
558  }
559 
560  if (old_hash == new_hash) return;
561 
562  /* Remove from the old position in the hash table */
563  if (old_hash != NULL) {
566  }
567 
568  /* Insert vehicle at beginning of the new position in the hash table */
569  if (new_hash != NULL) {
570  v->hash_tile_next = *new_hash;
572  v->hash_tile_prev = new_hash;
573  *new_hash = v;
574  }
575 
576  /* Remember current hash position */
577  v->hash_tile_current = new_hash;
578 }
579 
580 static Vehicle *_vehicle_viewport_hash[0x1000];
581 
582 static void UpdateVehicleViewportHash(Vehicle *v, int x, int y)
583 {
584  Vehicle **old_hash, **new_hash;
585  int old_x = v->coord.left;
586  int old_y = v->coord.top;
587 
588  new_hash = (x == INVALID_COORD) ? NULL : &_vehicle_viewport_hash[GEN_HASH(x, y)];
589  old_hash = (old_x == INVALID_COORD) ? NULL : &_vehicle_viewport_hash[GEN_HASH(old_x, old_y)];
590 
591  if (old_hash == new_hash) return;
592 
593  /* remove from hash table? */
594  if (old_hash != NULL) {
597  }
598 
599  /* insert into hash table? */
600  if (new_hash != NULL) {
601  v->hash_viewport_next = *new_hash;
603  v->hash_viewport_prev = new_hash;
604  *new_hash = v;
605  }
606 }
607 
608 void ResetVehicleHash()
609 {
610  Vehicle *v;
611  FOR_ALL_VEHICLES(v) { v->hash_tile_current = NULL; }
612  memset(_vehicle_viewport_hash, 0, sizeof(_vehicle_viewport_hash));
613  memset(_vehicle_tile_hash, 0, sizeof(_vehicle_tile_hash));
614 }
615 
616 void ResetVehicleColourMap()
617 {
618  Vehicle *v;
619  FOR_ALL_VEHICLES(v) { v->colourmap = PAL_NONE; }
620 }
621 
627 static AutoreplaceMap _vehicles_to_autoreplace;
628 
629 void InitializeVehicles()
630 {
631  _vehicles_to_autoreplace.Reset();
632  ResetVehicleHash();
633 }
634 
635 uint CountVehiclesInChain(const Vehicle *v)
636 {
637  uint count = 0;
638  do count++; while ((v = v->Next()) != NULL);
639  return count;
640 }
641 
647 {
648  switch (this->type) {
649  case VEH_AIRCRAFT: return Aircraft::From(this)->IsNormalAircraft(); // don't count plane shadows and helicopter rotors
650  case VEH_TRAIN:
651  return !this->IsArticulatedPart() && // tenders and other articulated parts
652  !Train::From(this)->IsRearDualheaded(); // rear parts of multiheaded engines
653  case VEH_ROAD: return RoadVehicle::From(this)->IsFrontEngine();
654  case VEH_SHIP: return true;
655  default: return false; // Only count company buildable vehicles
656  }
657 }
658 
664 {
665  switch (this->type) {
666  case VEH_AIRCRAFT: return Aircraft::From(this)->IsNormalAircraft();
667  case VEH_TRAIN:
668  case VEH_ROAD:
669  case VEH_SHIP: return true;
670  default: return false;
671  }
672 }
673 
680 {
681  return Engine::Get(this->engine_type);
682 }
683 
689 const GRFFile *Vehicle::GetGRF() const
690 {
691  return this->GetEngine()->GetGRF();
692 }
693 
699 uint32 Vehicle::GetGRFID() const
700 {
701  return this->GetEngine()->GetGRFID();
702 }
703 
711 void Vehicle::HandlePathfindingResult(bool path_found)
712 {
713  if (path_found) {
714  /* Route found, is the vehicle marked with "lost" flag? */
715  if (!HasBit(this->vehicle_flags, VF_PATHFINDER_LOST)) return;
716 
717  /* Clear the flag as the PF's problem was solved. */
719  /* Delete the news item. */
720  DeleteVehicleNews(this->index, STR_NEWS_VEHICLE_IS_LOST);
721  return;
722  }
723 
724  /* Were we already lost? */
725  if (HasBit(this->vehicle_flags, VF_PATHFINDER_LOST)) return;
726 
727  /* It is first time the problem occurred, set the "lost" flag. */
729  /* Notify user about the event. */
730  AI::NewEvent(this->owner, new ScriptEventVehicleLost(this->index));
731  if (_settings_client.gui.lost_vehicle_warn && this->owner == _local_company) {
732  SetDParam(0, this->index);
733  AddVehicleAdviceNewsItem(STR_NEWS_VEHICLE_IS_LOST, this->index);
734  }
735 }
736 
739 {
740  if (CleaningPool()) return;
741 
744  st->loading_vehicles.remove(this);
745 
747  this->CancelReservation(INVALID_STATION, st);
748  delete this->cargo_payment;
749  assert(this->cargo_payment == NULL); // cleared by ~CargoPayment
750  }
751 
752  if (this->IsEngineCountable()) {
754  if (this->IsPrimaryVehicle()) GroupStatistics::CountVehicle(this, -1);
756 
759  }
760 
761  if (this->type == VEH_AIRCRAFT && this->IsPrimaryVehicle()) {
762  Aircraft *a = Aircraft::From(this);
764  if (st != NULL) {
765  const AirportFTA *layout = st->airport.GetFTA()->layout;
766  CLRBITS(st->airport.flags, layout[a->previous_pos].block | layout[a->pos].block);
767  }
768  }
769 
770 
771  if (this->type == VEH_ROAD && this->IsPrimaryVehicle()) {
772  RoadVehicle *v = RoadVehicle::From(this);
773  if (!(v->vehstatus & VS_CRASHED) && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END)) {
774  /* Leave the drive through roadstop, when you have not already left it. */
776  }
777  }
778 
779  if (this->Previous() == NULL) {
781  }
782 
783  if (this->IsPrimaryVehicle()) {
791  }
793 
794  this->cargo.Truncate();
795  DeleteVehicleOrders(this);
797 
798  extern void StopGlobalFollowVehicle(const Vehicle *v);
799  StopGlobalFollowVehicle(this);
800 
802 }
803 
805 {
806  if (CleaningPool()) {
807  this->cargo.OnCleanPool();
808  return;
809  }
810 
811  /* sometimes, eg. for disaster vehicles, when company bankrupts, when removing crashed/flooded vehicles,
812  * it may happen that vehicle chain is deleted when visible */
813  if (!(this->vehstatus & VS_HIDDEN)) this->MarkAllViewportsDirty();
814 
815  Vehicle *v = this->Next();
816  this->SetNext(NULL);
817 
818  delete v;
819 
820  UpdateVehicleTileHash(this, true);
821  UpdateVehicleViewportHash(this, INVALID_COORD, 0);
824 }
825 
831 {
832  /* Vehicle should stop in the depot if it was in 'stopping' state */
833  _vehicles_to_autoreplace[v] = !(v->vehstatus & VS_STOPPED);
834 
835  /* We ALWAYS set the stopped state. Even when the vehicle does not plan on
836  * stopping in the depot, so we stop it to ensure that it will not reserve
837  * the path out of the depot before we might autoreplace it to a different
838  * engine. The new engine would not own the reserved path we store that we
839  * stopped the vehicle, so autoreplace can start it again */
840  v->vehstatus |= VS_STOPPED;
841 }
842 
848 static void RunVehicleDayProc()
849 {
850  if (_game_mode != GM_NORMAL) return;
851 
852  /* Run the day_proc for every DAY_TICKS vehicle starting at _date_fract. */
853  for (size_t i = _date_fract; i < Vehicle::GetPoolSize(); i += DAY_TICKS) {
854  Vehicle *v = Vehicle::Get(i);
855  if (v == NULL) continue;
856 
857  /* Call the 32-day callback if needed */
858  if ((v->day_counter & 0x1F) == 0 && v->HasEngineType()) {
859  uint16 callback = GetVehicleCallback(CBID_VEHICLE_32DAY_CALLBACK, 0, 0, v->engine_type, v);
860  if (callback != CALLBACK_FAILED) {
861  if (HasBit(callback, 0)) {
862  TriggerVehicle(v, VEHICLE_TRIGGER_CALLBACK_32); // Trigger vehicle trigger 10
863  }
864 
865  /* After a vehicle trigger, the graphics and properties of the vehicle could change.
866  * Note: MarkDirty also invalidates the palette, which is the meaning of bit 1. So, nothing special there. */
867  if (callback != 0) v->First()->MarkDirty();
868 
869  if (callback & ~3) ErrorUnknownCallbackResult(v->GetGRFID(), CBID_VEHICLE_32DAY_CALLBACK, callback);
870  }
871  }
872 
873  /* This is called once per day for each vehicle, but not in the first tick of the day */
874  v->OnNewDay();
875  }
876 }
877 
878 void CallVehicleTicks()
879 {
880  _vehicles_to_autoreplace.Clear();
881 
883 
884  Station *st;
885  FOR_ALL_STATIONS(st) LoadUnloadStation(st);
886 
887  Vehicle *v;
888  FOR_ALL_VEHICLES(v) {
889  /* Vehicle could be deleted in this tick */
890  if (!v->Tick()) {
891  assert(Vehicle::Get(vehicle_index) == NULL);
892  continue;
893  }
894 
895  assert(Vehicle::Get(vehicle_index) == v);
896 
897  switch (v->type) {
898  default: break;
899 
900  case VEH_TRAIN:
901  case VEH_ROAD:
902  case VEH_AIRCRAFT:
903  case VEH_SHIP: {
904  Vehicle *front = v->First();
905 
906  if (v->vcache.cached_cargo_age_period != 0) {
907  v->cargo_age_counter = min(v->cargo_age_counter, v->vcache.cached_cargo_age_period);
908  if (--v->cargo_age_counter == 0) {
909  v->cargo.AgeCargo();
910  v->cargo_age_counter = v->vcache.cached_cargo_age_period;
911  }
912  }
913 
914  /* Do not play any sound when crashed */
915  if (front->vehstatus & VS_CRASHED) continue;
916 
917  /* Do not play any sound when in depot or tunnel */
918  if (v->vehstatus & VS_HIDDEN) continue;
919 
920  /* Do not play any sound when stopped */
921  if ((front->vehstatus & VS_STOPPED) && (front->type != VEH_TRAIN || front->cur_speed == 0)) continue;
922 
923  /* Check vehicle type specifics */
924  switch (v->type) {
925  case VEH_TRAIN:
926  if (Train::From(v)->IsWagon()) continue;
927  break;
928 
929  case VEH_ROAD:
930  if (!RoadVehicle::From(v)->IsFrontEngine()) continue;
931  break;
932 
933  case VEH_AIRCRAFT:
934  if (!Aircraft::From(v)->IsNormalAircraft()) continue;
935  break;
936 
937  default:
938  break;
939  }
940 
941  v->motion_counter += front->cur_speed;
942  /* Play a running sound if the motion counter passes 256 (Do we not skip sounds?) */
943  if (GB(v->motion_counter, 0, 8) < front->cur_speed) PlayVehicleSound(v, VSE_RUNNING);
944 
945  /* Play an alternating running sound every 16 ticks */
946  if (GB(v->tick_counter, 0, 4) == 0) {
947  /* Play running sound when speed > 0 and not braking */
948  bool running = (front->cur_speed > 0) && !(front->vehstatus & (VS_STOPPED | VS_TRAIN_SLOWING));
950  }
951 
952  break;
953  }
954  }
955  }
956 
957  Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
958  for (AutoreplaceMap::iterator it = _vehicles_to_autoreplace.Begin(); it != _vehicles_to_autoreplace.End(); it++) {
959  v = it->first;
960  /* Autoreplace needs the current company set as the vehicle owner */
961  cur_company.Change(v->owner);
962 
963  /* Start vehicle if we stopped them in VehicleEnteredDepotThisTick()
964  * We need to stop them between VehicleEnteredDepotThisTick() and here or we risk that
965  * they are already leaving the depot again before being replaced. */
966  if (it->second) v->vehstatus &= ~VS_STOPPED;
967 
968  /* Store the position of the effect as the vehicle pointer will become invalid later */
969  int x = v->x_pos;
970  int y = v->y_pos;
971  int z = v->z_pos;
972 
975  CommandCost res = DoCommand(0, v->index, 0, DC_EXEC, CMD_AUTOREPLACE_VEHICLE);
977 
978  if (!IsLocalCompany()) continue;
979 
980  if (res.Succeeded()) {
981  ShowCostOrIncomeAnimation(x, y, z, res.GetCost());
982  continue;
983  }
984 
985  StringID error_message = res.GetErrorMessage();
986  if (error_message == STR_ERROR_AUTOREPLACE_NOTHING_TO_DO || error_message == INVALID_STRING_ID) continue;
987 
988  if (error_message == STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY) error_message = STR_ERROR_AUTOREPLACE_MONEY_LIMIT;
989 
990  StringID message;
991  if (error_message == STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT) {
992  message = error_message;
993  } else {
994  message = STR_NEWS_VEHICLE_AUTORENEW_FAILED;
995  }
996 
997  SetDParam(0, v->index);
998  SetDParam(1, error_message);
999  AddVehicleAdviceNewsItem(message, v->index);
1000  }
1001 
1002  cur_company.Restore();
1003 }
1004 
1009 static void DoDrawVehicle(const Vehicle *v)
1010 {
1011  SpriteID image = v->cur_image;
1012  PaletteID pal = PAL_NONE;
1013 
1015 
1016  /* Check whether the vehicle shall be transparent due to the game state */
1017  bool shadowed = (v->vehstatus & VS_SHADOW) != 0;
1018 
1019  if (v->type == VEH_EFFECT) {
1020  /* Check whether the vehicle shall be transparent/invisible due to GUI settings.
1021  * However, transparent smoke and bubbles look weird, so always hide them. */
1023  if (to != TO_INVALID && (IsTransparencySet(to) || IsInvisibilitySet(to))) return;
1024  }
1025 
1026  AddSortableSpriteToDraw(image, pal, v->x_pos + v->x_offs, v->y_pos + v->y_offs,
1027  v->x_extent, v->y_extent, v->z_extent, v->z_pos, shadowed, v->x_bb_offs, v->y_bb_offs);
1028 }
1029 
1035 {
1036  /* The bounding rectangle */
1037  const int l = dpi->left;
1038  const int r = dpi->left + dpi->width;
1039  const int t = dpi->top;
1040  const int b = dpi->top + dpi->height;
1041 
1042  /* The hash area to scan */
1043  int xl, xu, yl, yu;
1044 
1045  if (dpi->width + (70 * ZOOM_LVL_BASE) < (1 << (7 + 6 + ZOOM_LVL_SHIFT))) {
1046  xl = GB(l - (70 * ZOOM_LVL_BASE), 7 + ZOOM_LVL_SHIFT, 6);
1047  xu = GB(r, 7 + ZOOM_LVL_SHIFT, 6);
1048  } else {
1049  /* scan whole hash row */
1050  xl = 0;
1051  xu = 0x3F;
1052  }
1053 
1054  if (dpi->height + (70 * ZOOM_LVL_BASE) < (1 << (6 + 6 + ZOOM_LVL_SHIFT))) {
1055  yl = GB(t - (70 * ZOOM_LVL_BASE), 6 + ZOOM_LVL_SHIFT, 6) << 6;
1056  yu = GB(b, 6 + ZOOM_LVL_SHIFT, 6) << 6;
1057  } else {
1058  /* scan whole column */
1059  yl = 0;
1060  yu = 0x3F << 6;
1061  }
1062 
1063  for (int y = yl;; y = (y + (1 << 6)) & (0x3F << 6)) {
1064  for (int x = xl;; x = (x + 1) & 0x3F) {
1065  const Vehicle *v = _vehicle_viewport_hash[x + y]; // already masked & 0xFFF
1066 
1067  while (v != NULL) {
1068  if (!(v->vehstatus & VS_HIDDEN) &&
1069  l <= v->coord.right &&
1070  t <= v->coord.bottom &&
1071  r >= v->coord.left &&
1072  b >= v->coord.top) {
1073  DoDrawVehicle(v);
1074  }
1075  v = v->hash_viewport_next;
1076  }
1077 
1078  if (x == xu) break;
1079  }
1080 
1081  if (y == yu) break;
1082  }
1083 }
1084 
1092 Vehicle *CheckClickOnVehicle(const ViewPort *vp, int x, int y)
1093 {
1094  Vehicle *found = NULL, *v;
1095  uint dist, best_dist = UINT_MAX;
1096 
1097  if ((uint)(x -= vp->left) >= (uint)vp->width || (uint)(y -= vp->top) >= (uint)vp->height) return NULL;
1098 
1099  x = ScaleByZoom(x, vp->zoom) + vp->virtual_left;
1100  y = ScaleByZoom(y, vp->zoom) + vp->virtual_top;
1101 
1102  FOR_ALL_VEHICLES(v) {
1103  if ((v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0 &&
1104  x >= v->coord.left && x <= v->coord.right &&
1105  y >= v->coord.top && y <= v->coord.bottom) {
1106 
1107  dist = max(
1108  abs(((v->coord.left + v->coord.right) >> 1) - x),
1109  abs(((v->coord.top + v->coord.bottom) >> 1) - y)
1110  );
1111 
1112  if (dist < best_dist) {
1113  found = v;
1114  best_dist = dist;
1115  }
1116  }
1117  }
1118 
1119  return found;
1120 }
1121 
1127 {
1128  v->value -= v->value >> 8;
1130 }
1131 
1132 static const byte _breakdown_chance[64] = {
1133  3, 3, 3, 3, 3, 3, 3, 3,
1134  4, 4, 5, 5, 6, 6, 7, 7,
1135  8, 8, 9, 9, 10, 10, 11, 11,
1136  12, 13, 13, 13, 13, 14, 15, 16,
1137  17, 19, 21, 25, 28, 31, 34, 37,
1138  40, 44, 48, 52, 56, 60, 64, 68,
1139  72, 80, 90, 100, 110, 120, 130, 140,
1140  150, 170, 190, 210, 230, 250, 250, 250,
1141 };
1142 
1143 void CheckVehicleBreakdown(Vehicle *v)
1144 {
1145  int rel, rel_old;
1146 
1147  /* decrease reliability */
1148  v->reliability = rel = max((rel_old = v->reliability) - v->reliability_spd_dec, 0);
1149  if ((rel_old >> 8) != (rel >> 8)) SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
1150 
1151  if (v->breakdown_ctr != 0 || (v->vehstatus & VS_STOPPED) ||
1153  v->cur_speed < 5 || _game_mode == GM_MENU) {
1154  return;
1155  }
1156 
1157  uint32 r = Random();
1158 
1159  /* increase chance of failure */
1160  int chance = v->breakdown_chance + 1;
1161  if (Chance16I(1, 25, r)) chance += 25;
1162  v->breakdown_chance = min(255, chance);
1163 
1164  /* calculate reliability value to use in comparison */
1165  rel = v->reliability;
1166  if (v->type == VEH_SHIP) rel += 0x6666;
1167 
1168  /* reduced breakdowns? */
1169  if (_settings_game.difficulty.vehicle_breakdowns == 1) rel += 0x6666;
1170 
1171  /* check if to break down */
1172  if (_breakdown_chance[(uint)min(rel, 0xffff) >> 10] <= v->breakdown_chance) {
1173  v->breakdown_ctr = GB(r, 16, 6) + 0x3F;
1174  v->breakdown_delay = GB(r, 24, 7) + 0x80;
1175  v->breakdown_chance = 0;
1176  }
1177 }
1178 
1186 {
1187  /* Possible states for Vehicle::breakdown_ctr
1188  * 0 - vehicle is running normally
1189  * 1 - vehicle is currently broken down
1190  * 2 - vehicle is going to break down now
1191  * >2 - vehicle is counting down to the actual breakdown event */
1192  switch (this->breakdown_ctr) {
1193  case 0:
1194  return false;
1195 
1196  case 2:
1197  this->breakdown_ctr = 1;
1198 
1199  if (this->breakdowns_since_last_service != 255) {
1201  }
1202 
1203  if (this->type == VEH_AIRCRAFT) {
1204  /* Aircraft just need this flag, the rest is handled elsewhere */
1205  this->vehstatus |= VS_AIRCRAFT_BROKEN;
1206  } else {
1207  this->cur_speed = 0;
1208 
1209  if (!PlayVehicleSound(this, VSE_BREAKDOWN)) {
1210  bool train_or_ship = this->type == VEH_TRAIN || this->type == VEH_SHIP;
1211  SndPlayVehicleFx((_settings_game.game_creation.landscape != LT_TOYLAND) ?
1212  (train_or_ship ? SND_10_TRAIN_BREAKDOWN : SND_0F_VEHICLE_BREAKDOWN) :
1213  (train_or_ship ? SND_3A_COMEDY_BREAKDOWN_2 : SND_35_COMEDY_BREAKDOWN), this);
1214  }
1215 
1216  if (!(this->vehstatus & VS_HIDDEN) && !HasBit(EngInfo(this->engine_type)->misc_flags, EF_NO_BREAKDOWN_SMOKE)) {
1218  if (u != NULL) u->animation_state = this->breakdown_delay * 2;
1219  }
1220  }
1221 
1222  this->MarkDirty(); // Update graphics after speed is zeroed
1225 
1226  /* FALL THROUGH */
1227  case 1:
1228  /* Aircraft breakdowns end only when arriving at the airport */
1229  if (this->type == VEH_AIRCRAFT) return false;
1230 
1231  /* For trains this function is called twice per tick, so decrease v->breakdown_delay at half the rate */
1232  if ((this->tick_counter & (this->type == VEH_TRAIN ? 3 : 1)) == 0) {
1233  if (--this->breakdown_delay == 0) {
1234  this->breakdown_ctr = 0;
1235  this->MarkDirty();
1237  }
1238  }
1239  return true;
1240 
1241  default:
1242  if (!this->current_order.IsType(OT_LOADING)) this->breakdown_ctr--;
1243  return false;
1244  }
1245 }
1246 
1252 {
1253  if (v->age < MAX_DAY) {
1254  v->age++;
1256  }
1257 
1258  if (!v->IsPrimaryVehicle() && (v->type != VEH_TRAIN || !Train::From(v)->IsEngine())) return;
1259 
1260  int age = v->age - v->max_age;
1261  if (age == DAYS_IN_LEAP_YEAR * 0 || age == DAYS_IN_LEAP_YEAR * 1 ||
1262  age == DAYS_IN_LEAP_YEAR * 2 || age == DAYS_IN_LEAP_YEAR * 3 || age == DAYS_IN_LEAP_YEAR * 4) {
1263  v->reliability_spd_dec <<= 1;
1264  }
1265 
1267 
1268  /* Don't warn about non-primary or not ours vehicles or vehicles that are crashed */
1269  if (v->Previous() != NULL || v->owner != _local_company || (v->vehstatus & VS_CRASHED) != 0) return;
1270 
1271  /* Don't warn if a renew is active */
1272  if (Company::Get(v->owner)->settings.engine_renew && v->GetEngine()->company_avail != 0) return;
1273 
1274  StringID str;
1275  if (age == -DAYS_IN_LEAP_YEAR) {
1276  str = STR_NEWS_VEHICLE_IS_GETTING_OLD;
1277  } else if (age == 0) {
1278  str = STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD;
1279  } else if (age > 0 && (age % DAYS_IN_LEAP_YEAR) == 0) {
1280  str = STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD_AND;
1281  } else {
1282  return;
1283  }
1284 
1285  SetDParam(0, v->index);
1287 }
1288 
1298 uint8 CalcPercentVehicleFilled(const Vehicle *front, StringID *colour)
1299 {
1300  int count = 0;
1301  int max = 0;
1302  int cars = 0;
1303  int unloading = 0;
1304  bool loading = false;
1305 
1306  bool is_loading = front->current_order.IsType(OT_LOADING);
1307 
1308  /* The station may be NULL when the (colour) string does not need to be set. */
1309  const Station *st = Station::GetIfValid(front->last_station_visited);
1310  assert(colour == NULL || (st != NULL && is_loading));
1311 
1312  bool order_no_load = is_loading && (front->current_order.GetLoadType() & OLFB_NO_LOAD);
1313  bool order_full_load = is_loading && (front->current_order.GetLoadType() & OLFB_FULL_LOAD);
1314 
1315  /* Count up max and used */
1316  for (const Vehicle *v = front; v != NULL; v = v->Next()) {
1317  count += v->cargo.StoredCount();
1318  max += v->cargo_cap;
1319  if (v->cargo_cap != 0 && colour != NULL) {
1320  unloading += HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) ? 1 : 0;
1321  loading |= !order_no_load &&
1322  (order_full_load || st->goods[v->cargo_type].HasRating()) &&
1324  cars++;
1325  }
1326  }
1327 
1328  if (colour != NULL) {
1329  if (unloading == 0 && loading) {
1330  *colour = STR_PERCENT_UP;
1331  } else if (unloading == 0 && !loading) {
1332  *colour = STR_PERCENT_NONE;
1333  } else if (cars == unloading || !loading) {
1334  *colour = STR_PERCENT_DOWN;
1335  } else {
1336  *colour = STR_PERCENT_UP_DOWN;
1337  }
1338  }
1339 
1340  /* Train without capacity */
1341  if (max == 0) return 100;
1342 
1343  /* Return the percentage */
1344  if (count * 2 < max) {
1345  /* Less than 50%; round up, so that 0% means really empty. */
1346  return CeilDiv(count * 100, max);
1347  } else {
1348  /* More than 50%; round down, so that 100% means really full. */
1349  return (count * 100) / max;
1350  }
1351 }
1352 
1358 {
1359  /* Always work with the front of the vehicle */
1360  assert(v == v->First());
1361 
1362  switch (v->type) {
1363  case VEH_TRAIN: {
1364  Train *t = Train::From(v);
1366  /* Clear path reservation */
1367  SetDepotReservation(t->tile, false);
1369 
1371  t->wait_counter = 0;
1372  t->force_proceed = TFP_NONE;
1373  ClrBit(t->flags, VRF_TOGGLE_REVERSE);
1375  break;
1376  }
1377 
1378  case VEH_ROAD:
1380  break;
1381 
1382  case VEH_SHIP: {
1384  Ship *ship = Ship::From(v);
1385  ship->state = TRACK_BIT_DEPOT;
1386  ship->UpdateCache();
1387  ship->UpdateViewport(true, true);
1389  break;
1390  }
1391 
1392  case VEH_AIRCRAFT:
1395  break;
1396  default: NOT_REACHED();
1397  }
1399 
1400  if (v->type != VEH_TRAIN) {
1401  /* Trains update the vehicle list when the first unit enters the depot and calls VehicleEnterDepot() when the last unit enters.
1402  * 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 */
1404  }
1406 
1407  v->vehstatus |= VS_HIDDEN;
1408  v->cur_speed = 0;
1409 
1411 
1412  /* After a vehicle trigger, the graphics and properties of the vehicle could change. */
1413  TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
1414  v->MarkDirty();
1415 
1416  if (v->current_order.IsType(OT_GOTO_DEPOT)) {
1418 
1419  const Order *real_order = v->GetOrder(v->cur_real_order_index);
1420 
1421  /* Test whether we are heading for this depot. If not, do nothing.
1422  * Note: The target depot for nearest-/manual-depot-orders is only updated on junctions, but we want to accept every depot. */
1424  real_order != NULL && !(real_order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) &&
1425  (v->type == VEH_AIRCRAFT ? v->current_order.GetDestination() != GetStationIndex(v->tile) : v->dest_tile != v->tile)) {
1426  /* We are heading for another depot, keep driving. */
1427  return;
1428  }
1429 
1430  if (v->current_order.IsRefit()) {
1431  Backup<CompanyByte> cur_company(_current_company, v->owner, FILE_LINE);
1432  CommandCost cost = DoCommand(v->tile, v->index, v->current_order.GetRefitCargo() | 0xFF << 8, DC_EXEC, GetCmdRefitVeh(v));
1433  cur_company.Restore();
1434 
1435  if (cost.Failed()) {
1436  _vehicles_to_autoreplace[v] = false;
1437  if (v->owner == _local_company) {
1438  /* Notify the user that we stopped the vehicle */
1439  SetDParam(0, v->index);
1440  AddVehicleAdviceNewsItem(STR_NEWS_ORDER_REFIT_FAILED, v->index);
1441  }
1442  } else if (cost.GetCost() != 0) {
1443  v->profit_this_year -= cost.GetCost() << 8;
1444  if (v->owner == _local_company) {
1445  ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
1446  }
1447  }
1448  }
1449 
1451  /* Part of orders */
1453  UpdateVehicleTimetable(v, true);
1455  }
1457  /* Vehicles are always stopped on entering depots. Do not restart this one. */
1458  _vehicles_to_autoreplace[v] = false;
1459  /* Invalidate last_loading_station. As the link from the station
1460  * before the stop to the station after the stop can't be predicted
1461  * we shouldn't construct it when the vehicle visits the next stop. */
1462  v->last_loading_station = INVALID_STATION;
1463  if (v->owner == _local_company) {
1464  SetDParam(0, v->index);
1465  AddVehicleAdviceNewsItem(STR_NEWS_TRAIN_IS_WAITING + v->type, v->index);
1466  }
1467  AI::NewEvent(v->owner, new ScriptEventVehicleWaitingInDepot(v->index));
1468  }
1469  v->current_order.MakeDummy();
1470  }
1471 }
1472 
1473 
1479 {
1480  UpdateVehicleTileHash(this, false);
1481 }
1482 
1488 void Vehicle::UpdateViewport(bool dirty)
1489 {
1490  int img = this->cur_image;
1491  Point pt = RemapCoords(this->x_pos + this->x_offs, this->y_pos + this->y_offs, this->z_pos);
1492  const Sprite *spr = GetSprite(img, ST_NORMAL);
1493 
1494  pt.x += spr->x_offs;
1495  pt.y += spr->y_offs;
1496 
1497  UpdateVehicleViewportHash(this, pt.x, pt.y);
1498 
1499  Rect old_coord = this->coord;
1500  this->coord.left = pt.x;
1501  this->coord.top = pt.y;
1502  this->coord.right = pt.x + spr->width + 2 * ZOOM_LVL_BASE;
1503  this->coord.bottom = pt.y + spr->height + 2 * ZOOM_LVL_BASE;
1504 
1505  if (dirty) {
1506  if (old_coord.left == INVALID_COORD) {
1507  this->MarkAllViewportsDirty();
1508  } else {
1510  min(old_coord.left, this->coord.left),
1511  min(old_coord.top, this->coord.top),
1512  max(old_coord.right, this->coord.right),
1513  max(old_coord.bottom, this->coord.bottom));
1514  }
1515  }
1516 }
1517 
1522 {
1523  this->UpdatePosition();
1524  this->UpdateViewport(true);
1525 }
1526 
1531 {
1532  ::MarkAllViewportsDirty(this->coord.left, this->coord.top, this->coord.right, this->coord.bottom);
1533 }
1534 
1541 {
1542  static const int8 _delta_coord[16] = {
1543  -1,-1,-1, 0, 1, 1, 1, 0, /* x */
1544  -1, 0, 1, 1, 1, 0,-1,-1, /* y */
1545  };
1546 
1547  int x = v->x_pos + _delta_coord[v->direction];
1548  int y = v->y_pos + _delta_coord[v->direction + 8];
1549 
1551  gp.x = x;
1552  gp.y = y;
1553  gp.old_tile = v->tile;
1554  gp.new_tile = TileVirtXY(x, y);
1555  return gp;
1556 }
1557 
1558 static const Direction _new_direction_table[] = {
1559  DIR_N, DIR_NW, DIR_W,
1560  DIR_NE, DIR_SE, DIR_SW,
1561  DIR_E, DIR_SE, DIR_S
1562 };
1563 
1564 Direction GetDirectionTowards(const Vehicle *v, int x, int y)
1565 {
1566  int i = 0;
1567 
1568  if (y >= v->y_pos) {
1569  if (y != v->y_pos) i += 3;
1570  i += 3;
1571  }
1572 
1573  if (x >= v->x_pos) {
1574  if (x != v->x_pos) i++;
1575  i++;
1576  }
1577 
1578  Direction dir = v->direction;
1579 
1580  DirDiff dirdiff = DirDifference(_new_direction_table[i], dir);
1581  if (dirdiff == DIRDIFF_SAME) return dir;
1582  return ChangeDir(dir, dirdiff > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT);
1583 }
1584 
1595 {
1596  return _tile_type_procs[GetTileType(tile)]->vehicle_enter_tile_proc(v, tile, x, y);
1597 }
1598 
1606 FreeUnitIDGenerator::FreeUnitIDGenerator(VehicleType type, CompanyID owner) : cache(NULL), maxid(0), curid(0)
1607 {
1608  /* Find maximum */
1609  const Vehicle *v;
1610  FOR_ALL_VEHICLES(v) {
1611  if (v->type == type && v->owner == owner) {
1612  this->maxid = max<UnitID>(this->maxid, v->unitnumber);
1613  }
1614  }
1615 
1616  if (this->maxid == 0) return;
1617 
1618  /* Reserving 'maxid + 2' because we need:
1619  * - space for the last item (with v->unitnumber == maxid)
1620  * - one free slot working as loop terminator in FreeUnitIDGenerator::NextID() */
1621  this->cache = CallocT<bool>(this->maxid + 2);
1622 
1623  /* Fill the cache */
1624  FOR_ALL_VEHICLES(v) {
1625  if (v->type == type && v->owner == owner) {
1626  this->cache[v->unitnumber] = true;
1627  }
1628  }
1629 }
1630 
1633 {
1634  if (this->maxid <= this->curid) return ++this->curid;
1635 
1636  while (this->cache[++this->curid]) { } // it will stop, we reserved more space than needed
1637 
1638  return this->curid;
1639 }
1640 
1647 {
1648  /* Check whether it is allowed to build another vehicle. */
1649  uint max_veh;
1650  switch (type) {
1651  case VEH_TRAIN: max_veh = _settings_game.vehicle.max_trains; break;
1652  case VEH_ROAD: max_veh = _settings_game.vehicle.max_roadveh; break;
1653  case VEH_SHIP: max_veh = _settings_game.vehicle.max_ships; break;
1654  case VEH_AIRCRAFT: max_veh = _settings_game.vehicle.max_aircraft; break;
1655  default: NOT_REACHED();
1656  }
1657 
1659  if (c->group_all[type].num_vehicle >= max_veh) return UINT16_MAX; // Currently already at the limit, no room to make a new one.
1660 
1662 
1663  return gen.NextID();
1664 }
1665 
1666 
1676 {
1677  assert(IsCompanyBuildableVehicleType(type));
1678 
1679  if (!Company::IsValidID(_local_company)) return false;
1681 
1682  UnitID max;
1683  switch (type) {
1684  case VEH_TRAIN: max = _settings_game.vehicle.max_trains; break;
1685  case VEH_ROAD: max = _settings_game.vehicle.max_roadveh; break;
1686  case VEH_SHIP: max = _settings_game.vehicle.max_ships; break;
1687  case VEH_AIRCRAFT: max = _settings_game.vehicle.max_aircraft; break;
1688  default: NOT_REACHED();
1689  }
1690 
1691  /* We can build vehicle infrastructure when we may build the vehicle type */
1692  if (max > 0) {
1693  /* Can we actually build the vehicle type? */
1694  const Engine *e;
1695  FOR_ALL_ENGINES_OF_TYPE(e, type) {
1696  if (HasBit(e->company_avail, _local_company)) return true;
1697  }
1698  return false;
1699  }
1700 
1701  /* We should be able to build infrastructure when we have the actual vehicle type */
1702  const Vehicle *v;
1703  FOR_ALL_VEHICLES(v) {
1704  if (v->owner == _local_company && v->type == type) return true;
1705  }
1706 
1707  return false;
1708 }
1709 
1710 
1718 LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_type, const Vehicle *v)
1719 {
1720  CargoID cargo_type = v == NULL ? (CargoID)CT_INVALID : v->cargo_type;
1721  const Engine *e = Engine::Get(engine_type);
1722  switch (e->type) {
1723  default: NOT_REACHED();
1724  case VEH_TRAIN:
1725  if (v != NULL && parent_engine_type != INVALID_ENGINE && (UsesWagonOverride(v) || (v->IsArticulatedPart() && e->u.rail.railveh_type != RAILVEH_WAGON))) {
1726  /* Wagonoverrides use the colour scheme of the front engine.
1727  * Articulated parts use the colour scheme of the first part. (Not supported for articulated wagons) */
1728  engine_type = parent_engine_type;
1729  e = Engine::Get(engine_type);
1730  /* Note: Luckily cargo_type is not needed for engines */
1731  }
1732 
1733  if (cargo_type == CT_INVALID) cargo_type = e->GetDefaultCargoType();
1734  if (cargo_type == CT_INVALID) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo
1735  if (e->u.rail.railveh_type == RAILVEH_WAGON) {
1736  if (!CargoSpec::Get(cargo_type)->is_freight) {
1737  if (parent_engine_type == INVALID_ENGINE) {
1738  return LS_PASSENGER_WAGON_STEAM;
1739  } else {
1740  switch (RailVehInfo(parent_engine_type)->engclass) {
1741  default: NOT_REACHED();
1742  case EC_STEAM: return LS_PASSENGER_WAGON_STEAM;
1743  case EC_DIESEL: return LS_PASSENGER_WAGON_DIESEL;
1744  case EC_ELECTRIC: return LS_PASSENGER_WAGON_ELECTRIC;
1745  case EC_MONORAIL: return LS_PASSENGER_WAGON_MONORAIL;
1746  case EC_MAGLEV: return LS_PASSENGER_WAGON_MAGLEV;
1747  }
1748  }
1749  } else {
1750  return LS_FREIGHT_WAGON;
1751  }
1752  } else {
1753  bool is_mu = HasBit(e->info.misc_flags, EF_RAIL_IS_MU);
1754 
1755  switch (e->u.rail.engclass) {
1756  default: NOT_REACHED();
1757  case EC_STEAM: return LS_STEAM;
1758  case EC_DIESEL: return is_mu ? LS_DMU : LS_DIESEL;
1759  case EC_ELECTRIC: return is_mu ? LS_EMU : LS_ELECTRIC;
1760  case EC_MONORAIL: return LS_MONORAIL;
1761  case EC_MAGLEV: return LS_MAGLEV;
1762  }
1763  }
1764 
1765  case VEH_ROAD:
1766  /* Always use the livery of the front */
1767  if (v != NULL && parent_engine_type != INVALID_ENGINE) {
1768  engine_type = parent_engine_type;
1769  e = Engine::Get(engine_type);
1770  cargo_type = v->First()->cargo_type;
1771  }
1772  if (cargo_type == CT_INVALID) cargo_type = e->GetDefaultCargoType();
1773  if (cargo_type == CT_INVALID) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo
1774 
1775  /* Important: Use Tram Flag of front part. Luckily engine_type refers to the front part here. */
1776  if (HasBit(e->info.misc_flags, EF_ROAD_TRAM)) {
1777  /* Tram */
1778  return IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_TRAM : LS_FREIGHT_TRAM;
1779  } else {
1780  /* Bus or truck */
1781  return IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_BUS : LS_TRUCK;
1782  }
1783 
1784  case VEH_SHIP:
1785  if (cargo_type == CT_INVALID) cargo_type = e->GetDefaultCargoType();
1786  if (cargo_type == CT_INVALID) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo
1787  return IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_SHIP : LS_FREIGHT_SHIP;
1788 
1789  case VEH_AIRCRAFT:
1790  switch (e->u.air.subtype) {
1791  case AIR_HELI: return LS_HELICOPTER;
1792  case AIR_CTOL: return LS_SMALL_PLANE;
1793  case AIR_CTOL | AIR_FAST: return LS_LARGE_PLANE;
1794  default: NOT_REACHED();
1795  }
1796  }
1797 }
1798 
1808 const Livery *GetEngineLivery(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v, byte livery_setting)
1809 {
1810  const Company *c = Company::Get(company);
1811  LiveryScheme scheme = LS_DEFAULT;
1812 
1813  /* The default livery is always available for use, but its in_use flag determines
1814  * whether any _other_ liveries are in use. */
1815  if (c->livery[LS_DEFAULT].in_use && (livery_setting == LIT_ALL || (livery_setting == LIT_COMPANY && company == _local_company))) {
1816  /* Determine the livery scheme to use */
1817  scheme = GetEngineLiveryScheme(engine_type, parent_engine_type, v);
1818 
1819  /* Switch back to the default scheme if the resolved scheme is not in use */
1820  if (!c->livery[scheme].in_use) scheme = LS_DEFAULT;
1821  }
1822 
1823  return &c->livery[scheme];
1824 }
1825 
1826 
1827 static PaletteID GetEngineColourMap(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v)
1828 {
1829  PaletteID map = (v != NULL) ? v->colourmap : PAL_NONE;
1830 
1831  /* Return cached value if any */
1832  if (map != PAL_NONE) return map;
1833 
1834  const Engine *e = Engine::Get(engine_type);
1835 
1836  /* Check if we should use the colour map callback */
1838  uint16 callback = GetVehicleCallback(CBID_VEHICLE_COLOUR_MAPPING, 0, 0, engine_type, v);
1839  /* Failure means "use the default two-colour" */
1840  if (callback != CALLBACK_FAILED) {
1841  assert_compile(PAL_NONE == 0); // Returning 0x4000 (resp. 0xC000) coincidences with default value (PAL_NONE)
1842  map = GB(callback, 0, 14);
1843  /* If bit 14 is set, then the company colours are applied to the
1844  * map else it's returned as-is. */
1845  if (!HasBit(callback, 14)) {
1846  /* Update cache */
1847  if (v != NULL) const_cast<Vehicle *>(v)->colourmap = map;
1848  return map;
1849  }
1850  }
1851  }
1852 
1853  bool twocc = HasBit(e->info.misc_flags, EF_USES_2CC);
1854 
1855  if (map == PAL_NONE) map = twocc ? (PaletteID)SPR_2CCMAP_BASE : (PaletteID)PALETTE_RECOLOUR_START;
1856 
1857  /* Spectator has news shown too, but has invalid company ID - as well as dedicated server */
1858  if (!Company::IsValidID(company)) return map;
1859 
1860  const Livery *livery = GetEngineLivery(engine_type, company, parent_engine_type, v, _settings_client.gui.liveries);
1861 
1862  map += livery->colour1;
1863  if (twocc) map += livery->colour2 * 16;
1864 
1865  /* Update cache */
1866  if (v != NULL) const_cast<Vehicle *>(v)->colourmap = map;
1867  return map;
1868 }
1869 
1877 {
1878  return GetEngineColourMap(engine_type, company, INVALID_ENGINE, NULL);
1879 }
1880 
1887 {
1888  if (v->IsGroundVehicle()) {
1889  return GetEngineColourMap(v->engine_type, v->owner, v->GetGroundVehicleCache()->first_engine, v);
1890  }
1891 
1892  return GetEngineColourMap(v->engine_type, v->owner, INVALID_ENGINE, v);
1893 }
1894 
1899 {
1900  if (this->IsGroundVehicle()) {
1901  uint16 &gv_flags = this->GetGroundVehicleFlags();
1902  if (HasBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS)) {
1903  /* Do not delete orders, only skip them */
1906  InvalidateVehicleOrder(this, 0);
1907  return;
1908  }
1909  }
1910 
1911  const Order *order = this->GetOrder(this->cur_implicit_order_index);
1912  while (order != NULL) {
1913  if (this->cur_implicit_order_index == this->cur_real_order_index) break;
1914 
1915  if (order->IsType(OT_IMPLICIT)) {
1917  /* DeleteOrder does various magic with order_indices, so resync 'order' with 'cur_implicit_order_index' */
1918  order = this->GetOrder(this->cur_implicit_order_index);
1919  } else {
1920  /* Skip non-implicit orders, e.g. service-orders */
1921  order = order->next;
1922  this->cur_implicit_order_index++;
1923  }
1924 
1925  /* Wrap around */
1926  if (order == NULL) {
1927  order = this->GetOrder(0);
1928  this->cur_implicit_order_index = 0;
1929  }
1930  }
1931 }
1932 
1938 {
1939  assert(IsTileType(this->tile, MP_STATION) || this->type == VEH_SHIP);
1940 
1941  if (this->current_order.IsType(OT_GOTO_STATION) &&
1944 
1945  /* Now both order indices point to the destination station, and we can start loading */
1946  this->current_order.MakeLoading(true);
1947  UpdateVehicleTimetable(this, true);
1948 
1949  /* Furthermore add the Non Stop flag to mark that this station
1950  * is the actual destination of the vehicle, which is (for example)
1951  * necessary to be known for HandleTrainLoading to determine
1952  * whether the train is lost or not; not marking a train lost
1953  * that arrives at random stations is bad. */
1955 
1956  } else {
1957  /* We weren't scheduled to stop here. Insert an implicit order
1958  * to show that we are stopping here.
1959  * While only groundvehicles have implicit orders, e.g. aircraft might still enter
1960  * the 'wrong' terminal when skipping orders etc. */
1961  Order *in_list = this->GetOrder(this->cur_implicit_order_index);
1962  if (this->IsGroundVehicle() &&
1963  (in_list == NULL || !in_list->IsType(OT_IMPLICIT) ||
1964  in_list->GetDestination() != this->last_station_visited)) {
1965  bool suppress_implicit_orders = HasBit(this->GetGroundVehicleFlags(), GVF_SUPPRESS_IMPLICIT_ORDERS);
1966  /* Do not create consecutive duplicates of implicit orders */
1967  Order *prev_order = this->cur_implicit_order_index > 0 ? this->GetOrder(this->cur_implicit_order_index - 1) : (this->GetNumOrders() > 1 ? this->GetLastOrder() : NULL);
1968  if (prev_order == NULL ||
1969  (!prev_order->IsType(OT_IMPLICIT) && !prev_order->IsType(OT_GOTO_STATION)) ||
1970  prev_order->GetDestination() != this->last_station_visited) {
1971 
1972  /* Prefer deleting implicit orders instead of inserting new ones,
1973  * so test whether the right order follows later. In case of only
1974  * implicit orders treat the last order in the list like an
1975  * explicit one, except if the overall number of orders surpasses
1976  * IMPLICIT_ORDER_ONLY_CAP. */
1977  int target_index = this->cur_implicit_order_index;
1978  bool found = false;
1979  while (target_index != this->cur_real_order_index || this->GetNumManualOrders() == 0) {
1980  const Order *order = this->GetOrder(target_index);
1981  if (order == NULL) break; // No orders.
1982  if (order->IsType(OT_IMPLICIT) && order->GetDestination() == this->last_station_visited) {
1983  found = true;
1984  break;
1985  }
1986  target_index++;
1987  if (target_index >= this->orders.list->GetNumOrders()) {
1988  if (this->GetNumManualOrders() == 0 &&
1990  break;
1991  }
1992  target_index = 0;
1993  }
1994  if (target_index == this->cur_implicit_order_index) break; // Avoid infinite loop.
1995  }
1996 
1997  if (found) {
1998  if (suppress_implicit_orders) {
1999  /* Skip to the found order */
2000  this->cur_implicit_order_index = target_index;
2001  InvalidateVehicleOrder(this, 0);
2002  } else {
2003  /* Delete all implicit orders up to the station we just reached */
2004  const Order *order = this->GetOrder(this->cur_implicit_order_index);
2005  while (!order->IsType(OT_IMPLICIT) || order->GetDestination() != this->last_station_visited) {
2006  if (order->IsType(OT_IMPLICIT)) {
2008  /* DeleteOrder does various magic with order_indices, so resync 'order' with 'cur_implicit_order_index' */
2009  order = this->GetOrder(this->cur_implicit_order_index);
2010  } else {
2011  /* Skip non-implicit orders, e.g. service-orders */
2012  order = order->next;
2013  this->cur_implicit_order_index++;
2014  }
2015 
2016  /* Wrap around */
2017  if (order == NULL) {
2018  order = this->GetOrder(0);
2019  this->cur_implicit_order_index = 0;
2020  }
2021  assert(order != NULL);
2022  }
2023  }
2024  } else if (!suppress_implicit_orders &&
2025  ((this->orders.list == NULL ? OrderList::CanAllocateItem() : this->orders.list->GetNumOrders() < MAX_VEH_ORDER_ID)) &&
2027  /* Insert new implicit order */
2028  Order *implicit_order = new Order();
2029  implicit_order->MakeImplicit(this->last_station_visited);
2030  InsertOrder(this, implicit_order, this->cur_implicit_order_index);
2031  if (this->cur_implicit_order_index > 0) --this->cur_implicit_order_index;
2032 
2033  /* InsertOrder disabled creation of implicit orders for all vehicles with the same implicit order.
2034  * Reenable it for this vehicle */
2035  uint16 &gv_flags = this->GetGroundVehicleFlags();
2037  }
2038  }
2039  }
2040  this->current_order.MakeLoading(false);
2041  }
2042 
2043  if (this->last_loading_station != INVALID_STATION &&
2044  this->last_loading_station != this->last_station_visited &&
2045  ((this->current_order.GetLoadType() & OLFB_NO_LOAD) == 0 ||
2046  (this->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0)) {
2048  }
2049 
2050  PrepareUnload(this);
2051 
2056 
2057  Station::Get(this->last_station_visited)->MarkTilesDirty(true);
2058  this->cur_speed = 0;
2059  this->MarkDirty();
2060 }
2061 
2067 void Vehicle::CancelReservation(StationID next, Station *st)
2068 {
2069  for (Vehicle *v = this; v != NULL; v = v->next) {
2071  if (cargo.ActionCount(VehicleCargoList::MTA_LOAD) > 0) {
2072  DEBUG(misc, 1, "cancelling cargo reservation");
2073  cargo.Return(UINT_MAX, &st->goods[v->cargo_type].cargo, next);
2074  cargo.SetTransferLoadPlace(st->xy);
2075  }
2076  cargo.KeepAll();
2077  }
2078 }
2079 
2085 {
2086  assert(this->current_order.IsType(OT_LOADING));
2087 
2088  delete this->cargo_payment;
2089  assert(this->cargo_payment == NULL); // cleared by ~CargoPayment
2090 
2091  /* Only update the timetable if the vehicle was supposed to stop here. */
2093 
2094  if ((this->current_order.GetLoadType() & OLFB_NO_LOAD) == 0 ||
2095  (this->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
2096  if (this->current_order.CanLeaveWithCargo(this->last_loading_station != INVALID_STATION)) {
2097  /* Refresh next hop stats to make sure we've done that at least once
2098  * during the stop and that refit_cap == cargo_cap for each vehicle in
2099  * the consist. */
2100  this->ResetRefitCaps();
2101  LinkRefresher::Run(this);
2102 
2103  /* if the vehicle could load here or could stop with cargo loaded set the last loading station */
2105  } else {
2106  /* if the vehicle couldn't load and had to unload or transfer everything
2107  * set the last loading station to invalid as it will leave empty. */
2108  this->last_loading_station = INVALID_STATION;
2109  }
2110  }
2111 
2114  this->CancelReservation(INVALID_STATION, st);
2115  st->loading_vehicles.remove(this);
2116 
2118 
2119  if (this->type == VEH_TRAIN && !(this->vehstatus & VS_CRASHED)) {
2120  /* Trigger station animation (trains only) */
2121  if (IsTileType(this->tile, MP_STATION)) {
2123  TriggerStationAnimation(st, this->tile, SAT_TRAIN_DEPARTS);
2124  }
2125 
2126  SetBit(Train::From(this)->flags, VRF_LEAVING_STATION);
2127  }
2128 
2129  this->MarkDirty();
2130 }
2131 
2136 {
2137  for (Vehicle *v = this; v != NULL; v = v->Next()) v->refit_cap = v->cargo_cap;
2138 }
2139 
2145 void Vehicle::HandleLoading(bool mode)
2146 {
2147  switch (this->current_order.GetType()) {
2148  case OT_LOADING: {
2149  uint wait_time = max(this->current_order.GetTimetabledWait() - this->lateness_counter, 0);
2150 
2151  /* Not the first call for this tick, or still loading */
2152  if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) || this->current_order_time < wait_time) return;
2153 
2154  this->PlayLeaveStationSound();
2155 
2156  this->LeaveStation();
2157 
2158  /* Only advance to next order if we just loaded at the current one */
2159  const Order *order = this->GetOrder(this->cur_implicit_order_index);
2160  if (order == NULL ||
2161  (!order->IsType(OT_IMPLICIT) && !order->IsType(OT_GOTO_STATION)) ||
2162  order->GetDestination() != this->last_station_visited) {
2163  return;
2164  }
2165  break;
2166  }
2167 
2168  case OT_DUMMY: break;
2169 
2170  default: return;
2171  }
2172 
2174 }
2175 
2181 {
2182  for (const Vehicle *v = this; v != NULL; v = v->Next()) {
2183  if (v->cargo_cap == 0) continue;
2184  SmallPair<CargoID, uint> *pair = capacities.Find(v->cargo_type);
2185  if (pair == capacities.End()) {
2186  pair = capacities.Append();
2187  pair->first = v->cargo_type;
2188  pair->second = v->cargo_cap - v->cargo.StoredCount();
2189  } else {
2190  pair->second += v->cargo_cap - v->cargo.StoredCount();
2191  }
2192  }
2193 }
2194 
2195 uint Vehicle::GetConsistTotalCapacity() const
2196 {
2197  uint result = 0;
2198  for (const Vehicle *v = this; v != NULL; v = v->Next()) {
2199  result += v->cargo_cap;
2200  }
2201  return result;
2202 }
2203 
2211 {
2212  CommandCost ret = CheckOwnership(this->owner);
2213  if (ret.Failed()) return ret;
2214 
2215  if (this->vehstatus & VS_CRASHED) return CMD_ERROR;
2216  if (this->IsStoppedInDepot()) return CMD_ERROR;
2217 
2218  if (this->current_order.IsType(OT_GOTO_DEPOT)) {
2219  bool halt_in_depot = (this->current_order.GetDepotActionType() & ODATFB_HALT) != 0;
2220  if (!!(command & DEPOT_SERVICE) == halt_in_depot) {
2221  /* We called with a different DEPOT_SERVICE setting.
2222  * Now we change the setting to apply the new one and let the vehicle head for the same depot.
2223  * Note: the if is (true for requesting service == true for ordered to stop in depot) */
2224  if (flags & DC_EXEC) {
2228  }
2229  return CommandCost();
2230  }
2231 
2232  if (command & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders
2233  if (flags & DC_EXEC) {
2234  /* If the orders to 'goto depot' are in the orders list (forced servicing),
2235  * then skip to the next order; effectively cancelling this forced service */
2237 
2238  if (this->IsGroundVehicle()) {
2239  uint16 &gv_flags = this->GetGroundVehicleFlags();
2241  }
2242 
2243  this->current_order.MakeDummy();
2245  }
2246  return CommandCost();
2247  }
2248 
2249  TileIndex location;
2250  DestinationID destination;
2251  bool reverse;
2252  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};
2253  if (!this->FindClosestDepot(&location, &destination, &reverse)) return_cmd_error(no_depot[this->type]);
2254 
2255  if (flags & DC_EXEC) {
2256  if (this->current_order.IsType(OT_LOADING)) this->LeaveStation();
2257 
2258  if (this->IsGroundVehicle() && this->GetNumManualOrders() > 0) {
2259  uint16 &gv_flags = this->GetGroundVehicleFlags();
2261  }
2262 
2263  this->dest_tile = location;
2264  this->current_order.MakeGoToDepot(destination, ODTF_MANUAL);
2265  if (!(command & DEPOT_SERVICE)) this->current_order.SetDepotActionType(ODATFB_HALT);
2267 
2268  /* If there is no depot in front, reverse automatically (trains only) */
2269  if (this->type == VEH_TRAIN && reverse) DoCommand(this->tile, this->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
2270 
2271  if (this->type == VEH_AIRCRAFT) {
2272  Aircraft *a = Aircraft::From(this);
2273  if (a->state == FLYING && a->targetairport != destination) {
2274  /* The aircraft is now heading for a different hangar than the next in the orders */
2277  }
2278  }
2279  }
2280 
2281  return CommandCost();
2282 
2283 }
2284 
2289 void Vehicle::UpdateVisualEffect(bool allow_power_change)
2290 {
2291  bool powered_before = HasBit(this->vcache.cached_vis_effect, VE_DISABLE_WAGON_POWER);
2292  const Engine *e = this->GetEngine();
2293 
2294  /* Evaluate properties */
2295  byte visual_effect;
2296  switch (e->type) {
2297  case VEH_TRAIN: visual_effect = e->u.rail.visual_effect; break;
2298  case VEH_ROAD: visual_effect = e->u.road.visual_effect; break;
2299  case VEH_SHIP: visual_effect = e->u.ship.visual_effect; break;
2300  default: visual_effect = 1 << VE_DISABLE_EFFECT; break;
2301  }
2302 
2303  /* Check powered wagon / visual effect callback */
2305  uint16 callback = GetVehicleCallback(CBID_VEHICLE_VISUAL_EFFECT, 0, 0, this->engine_type, this);
2306 
2307  if (callback != CALLBACK_FAILED) {
2308  if (callback >= 0x100 && e->GetGRF()->grf_version >= 8) ErrorUnknownCallbackResult(e->GetGRFID(), CBID_VEHICLE_VISUAL_EFFECT, callback);
2309 
2310  callback = GB(callback, 0, 8);
2311  /* Avoid accidentally setting 'visual_effect' to the default value
2312  * Since bit 6 (disable effects) is set anyways, we can safely erase some bits. */
2313  if (callback == VE_DEFAULT) {
2314  assert(HasBit(callback, VE_DISABLE_EFFECT));
2315  SB(callback, VE_TYPE_START, VE_TYPE_COUNT, 0);
2316  }
2317  visual_effect = callback;
2318  }
2319  }
2320 
2321  /* Apply default values */
2322  if (visual_effect == VE_DEFAULT ||
2323  (!HasBit(visual_effect, VE_DISABLE_EFFECT) && GB(visual_effect, VE_TYPE_START, VE_TYPE_COUNT) == VE_TYPE_DEFAULT)) {
2324  /* Only train engines have default effects.
2325  * Note: This is independent of whether the engine is a front engine or articulated part or whatever. */
2326  if (e->type != VEH_TRAIN || e->u.rail.railveh_type == RAILVEH_WAGON || !IsInsideMM(e->u.rail.engclass, EC_STEAM, EC_MONORAIL)) {
2327  if (visual_effect == VE_DEFAULT) {
2328  visual_effect = 1 << VE_DISABLE_EFFECT;
2329  } else {
2330  SetBit(visual_effect, VE_DISABLE_EFFECT);
2331  }
2332  } else {
2333  if (visual_effect == VE_DEFAULT) {
2334  /* Also set the offset */
2335  visual_effect = (VE_OFFSET_CENTRE - (e->u.rail.engclass == EC_STEAM ? 4 : 0)) << VE_OFFSET_START;
2336  }
2337  SB(visual_effect, VE_TYPE_START, VE_TYPE_COUNT, e->u.rail.engclass - EC_STEAM + VE_TYPE_STEAM);
2338  }
2339  }
2340 
2341  this->vcache.cached_vis_effect = visual_effect;
2342 
2343  if (!allow_power_change && powered_before != HasBit(this->vcache.cached_vis_effect, VE_DISABLE_WAGON_POWER)) {
2345  ShowNewGrfVehicleError(this->engine_type, STR_NEWGRF_BROKEN, STR_NEWGRF_BROKEN_POWERED_WAGON, GBUG_VEH_POWERED_WAGON, false);
2346  }
2347 }
2348 
2349 static const int8 _vehicle_smoke_pos[8] = {
2350  1, 1, 1, 0, -1, -1, -1, 0
2351 };
2352 
2357 static void SpawnAdvancedVisualEffect(const Vehicle *v)
2358 {
2359  uint16 callback = GetVehicleCallback(CBID_VEHICLE_SPAWN_VISUAL_EFFECT, 0, Random(), v->engine_type, v);
2360  if (callback == CALLBACK_FAILED) return;
2361 
2362  uint count = GB(callback, 0, 2);
2363  bool auto_center = HasBit(callback, 13);
2364  bool auto_rotate = !HasBit(callback, 14);
2365 
2366  int8 l_center = 0;
2367  if (auto_center) {
2368  /* For road vehicles: Compute offset from vehicle position to vehicle center */
2369  if (v->type == VEH_ROAD) l_center = -(int)(VEHICLE_LENGTH - RoadVehicle::From(v)->gcache.cached_veh_length) / 2;
2370  } else {
2371  /* For trains: Compute offset from vehicle position to sprite position */
2372  if (v->type == VEH_TRAIN) l_center = (VEHICLE_LENGTH - Train::From(v)->gcache.cached_veh_length) / 2;
2373  }
2374 
2375  Direction l_dir = v->direction;
2376  if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_REVERSE_DIRECTION)) l_dir = ReverseDir(l_dir);
2377  Direction t_dir = ChangeDir(l_dir, DIRDIFF_90RIGHT);
2378 
2379  int8 x_center = _vehicle_smoke_pos[l_dir] * l_center;
2380  int8 y_center = _vehicle_smoke_pos[t_dir] * l_center;
2381 
2382  for (uint i = 0; i < count; i++) {
2383  uint32 reg = GetRegister(0x100 + i);
2384  uint type = GB(reg, 0, 8);
2385  int8 x = GB(reg, 8, 8);
2386  int8 y = GB(reg, 16, 8);
2387  int8 z = GB(reg, 24, 8);
2388 
2389  if (auto_rotate) {
2390  int8 l = x;
2391  int8 t = y;
2392  x = _vehicle_smoke_pos[l_dir] * l + _vehicle_smoke_pos[t_dir] * t;
2393  y = _vehicle_smoke_pos[t_dir] * l - _vehicle_smoke_pos[l_dir] * t;
2394  }
2395 
2396  if (type >= 0xF0) {
2397  switch (type) {
2398  case 0xF1: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_STEAM_SMOKE); break;
2399  case 0xF2: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_DIESEL_SMOKE); break;
2400  case 0xF3: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_ELECTRIC_SPARK); break;
2401  case 0xFA: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_BREAKDOWN_SMOKE_AIRCRAFT); break;
2402  default: break;
2403  }
2404  }
2405  }
2406 }
2407 
2413 {
2414  assert(this->IsPrimaryVehicle());
2415  bool sound = false;
2416 
2417  /* Do not show any smoke when:
2418  * - vehicle smoke is disabled by the player
2419  * - the vehicle is slowing down or stopped (by the player)
2420  * - the vehicle is moving very slowly
2421  */
2422  if (_settings_game.vehicle.smoke_amount == 0 ||
2423  this->vehstatus & (VS_TRAIN_SLOWING | VS_STOPPED) ||
2424  this->cur_speed < 2) {
2425  return;
2426  }
2427 
2428  /* Use the speed as limited by underground and orders. */
2429  uint max_speed = this->GetCurrentMaxSpeed();
2430 
2431  if (this->type == VEH_TRAIN) {
2432  const Train *t = Train::From(this);
2433  /* For trains, do not show any smoke when:
2434  * - the train is reversing
2435  * - is entering a station with an order to stop there and its speed is equal to maximum station entering speed
2436  */
2437  if (HasBit(t->flags, VRF_REVERSING) ||
2439  t->cur_speed >= max_speed)) {
2440  return;
2441  }
2442  }
2443 
2444  const Vehicle *v = this;
2445 
2446  do {
2447  bool advanced = HasBit(v->vcache.cached_vis_effect, VE_ADVANCED_EFFECT);
2449  VisualEffectSpawnModel effect_model = VESM_NONE;
2450  if (advanced) {
2451  effect_offset = VE_OFFSET_CENTRE;
2453  if (effect_model >= VESM_END) effect_model = VESM_NONE; // unknown spawning model
2454  } else {
2456  assert(effect_model != (VisualEffectSpawnModel)VE_TYPE_DEFAULT); // should have been resolved by UpdateVisualEffect
2457  assert_compile((uint)VESM_STEAM == (uint)VE_TYPE_STEAM);
2458  assert_compile((uint)VESM_DIESEL == (uint)VE_TYPE_DIESEL);
2459  assert_compile((uint)VESM_ELECTRIC == (uint)VE_TYPE_ELECTRIC);
2460  }
2461 
2462  /* Show no smoke when:
2463  * - Smoke has been disabled for this vehicle
2464  * - The vehicle is not visible
2465  * - The vehicle is under a bridge
2466  * - The vehicle is on a depot tile
2467  * - The vehicle is on a tunnel tile
2468  * - The vehicle is a train engine that is currently unpowered */
2469  if (effect_model == VESM_NONE ||
2470  v->vehstatus & VS_HIDDEN ||
2471  IsBridgeAbove(v->tile) ||
2472  IsDepotTile(v->tile) ||
2473  IsTunnelTile(v->tile) ||
2474  (v->type == VEH_TRAIN &&
2475  !HasPowerOnRail(Train::From(v)->railtype, GetTileRailType(v->tile)))) {
2476  continue;
2477  }
2478 
2479  EffectVehicleType evt = EV_END;
2480  switch (effect_model) {
2481  case VESM_STEAM:
2482  /* Steam smoke - amount is gradually falling until vehicle reaches its maximum speed, after that it's normal.
2483  * Details: while vehicle's current speed is gradually increasing, steam plumes' density decreases by one third each
2484  * third of its maximum speed spectrum. Steam emission finally normalises at very close to vehicle's maximum speed.
2485  * REGULATION:
2486  * - instead of 1, 4 / 2^smoke_amount (max. 2) is used to provide sufficient regulation to steam puffs' amount. */
2487  if (GB(v->tick_counter, 0, ((4 >> _settings_game.vehicle.smoke_amount) + ((this->cur_speed * 3) / max_speed))) == 0) {
2488  evt = EV_STEAM_SMOKE;
2489  }
2490  break;
2491 
2492  case VESM_DIESEL: {
2493  /* Diesel smoke - thicker when vehicle is starting, gradually subsiding till it reaches its maximum speed
2494  * when smoke emission stops.
2495  * Details: Vehicle's (max.) speed spectrum is divided into 32 parts. When max. speed is reached, chance for smoke
2496  * emission erodes by 32 (1/4). For trains, power and weight come in handy too to either increase smoke emission in
2497  * 6 steps (1000HP each) if the power is low or decrease smoke emission in 6 steps (512 tonnes each) if the train
2498  * isn't overweight. Power and weight contributions are expressed in a way that neither extreme power, nor
2499  * extreme weight can ruin the balance (e.g. FreightWagonMultiplier) in the formula. When the vehicle reaches
2500  * maximum speed no diesel_smoke is emitted.
2501  * REGULATION:
2502  * - up to which speed a diesel vehicle is emitting smoke (with reduced/small setting only until 1/2 of max_speed),
2503  * - in Chance16 - the last value is 512 / 2^smoke_amount (max. smoke when 128 = smoke_amount of 2). */
2504  int power_weight_effect = 0;
2505  if (v->type == VEH_TRAIN) {
2506  power_weight_effect = (32 >> (Train::From(this)->gcache.cached_power >> 10)) - (32 >> (Train::From(this)->gcache.cached_weight >> 9));
2507  }
2508  if (this->cur_speed < (max_speed >> (2 >> _settings_game.vehicle.smoke_amount)) &&
2509  Chance16((64 - ((this->cur_speed << 5) / max_speed) + power_weight_effect), (512 >> _settings_game.vehicle.smoke_amount))) {
2510  evt = EV_DIESEL_SMOKE;
2511  }
2512  break;
2513  }
2514 
2515  case VESM_ELECTRIC:
2516  /* Electric train's spark - more often occurs when train is departing (more load)
2517  * Details: Electric locomotives are usually at least twice as powerful as their diesel counterparts, so spark
2518  * emissions are kept simple. Only when starting, creating huge force are sparks more likely to happen, but when
2519  * reaching its max. speed, quarter by quarter of it, chance decreases until the usual 2,22% at train's top speed.
2520  * REGULATION:
2521  * - in Chance16 the last value is 360 / 2^smoke_amount (max. sparks when 90 = smoke_amount of 2). */
2522  if (GB(v->tick_counter, 0, 2) == 0 &&
2523  Chance16((6 - ((this->cur_speed << 2) / max_speed)), (360 >> _settings_game.vehicle.smoke_amount))) {
2524  evt = EV_ELECTRIC_SPARK;
2525  }
2526  break;
2527 
2528  default:
2529  NOT_REACHED();
2530  }
2531 
2532  if (evt != EV_END && advanced) {
2533  sound = true;
2535  } else if (evt != EV_END) {
2536  sound = true;
2537 
2538  /* The effect offset is relative to a point 4 units behind the vehicle's
2539  * front (which is the center of an 8/8 vehicle). Shorter vehicles need a
2540  * correction factor. */
2541  if (v->type == VEH_TRAIN) effect_offset += (VEHICLE_LENGTH - Train::From(v)->gcache.cached_veh_length) / 2;
2542 
2543  int x = _vehicle_smoke_pos[v->direction] * effect_offset;
2544  int y = _vehicle_smoke_pos[(v->direction + 2) % 8] * effect_offset;
2545 
2546  if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_REVERSE_DIRECTION)) {
2547  x = -x;
2548  y = -y;
2549  }
2550 
2551  CreateEffectVehicleRel(v, x, y, 10, evt);
2552  }
2553  } while ((v = v->Next()) != NULL);
2554 
2555  if (sound) PlayVehicleSound(this, VSE_VISUAL_EFFECT);
2556 }
2557 
2563 {
2564  assert(this != next);
2565 
2566  if (this->next != NULL) {
2567  /* We had an old next vehicle. Update the first and previous pointers */
2568  for (Vehicle *v = this->next; v != NULL; v = v->Next()) {
2569  v->first = this->next;
2570  }
2571  this->next->previous = NULL;
2572  }
2573 
2574  this->next = next;
2575 
2576  if (this->next != NULL) {
2577  /* A new next vehicle. Update the first and previous pointers */
2578  if (this->next->previous != NULL) this->next->previous->next = NULL;
2579  this->next->previous = this;
2580  for (Vehicle *v = this->next; v != NULL; v = v->Next()) {
2581  v->first = this->first;
2582  }
2583  }
2584 }
2585 
2591 void Vehicle::AddToShared(Vehicle *shared_chain)
2592 {
2593  assert(this->previous_shared == NULL && this->next_shared == NULL);
2594 
2595  if (shared_chain->orders.list == NULL) {
2596  assert(shared_chain->previous_shared == NULL);
2597  assert(shared_chain->next_shared == NULL);
2598  this->orders.list = shared_chain->orders.list = new OrderList(NULL, shared_chain);
2599  }
2600 
2601  this->next_shared = shared_chain->next_shared;
2602  this->previous_shared = shared_chain;
2603 
2604  shared_chain->next_shared = this;
2605 
2606  if (this->next_shared != NULL) this->next_shared->previous_shared = this;
2607 
2608  shared_chain->orders.list->AddVehicle(this);
2609 }
2610 
2615 {
2616  /* Remember if we were first and the old window number before RemoveVehicle()
2617  * as this changes first if needed. */
2618  bool were_first = (this->FirstShared() == this);
2619  VehicleListIdentifier vli(VL_SHARED_ORDERS, this->type, this->owner, this->FirstShared()->index);
2620 
2621  this->orders.list->RemoveVehicle(this);
2622 
2623  if (!were_first) {
2624  /* We are not the first shared one, so only relink our previous one. */
2625  this->previous_shared->next_shared = this->NextShared();
2626  }
2627 
2628  if (this->next_shared != NULL) this->next_shared->previous_shared = this->previous_shared;
2629 
2630 
2631  if (this->orders.list->GetNumVehicles() == 1) {
2632  /* When there is only one vehicle, remove the shared order list window. */
2634  InvalidateVehicleOrder(this->FirstShared(), 0);
2635  } else if (were_first) {
2636  /* If we were the first one, update to the new first one.
2637  * Note: FirstShared() is already the new first */
2638  InvalidateWindowData(GetWindowClassForVehicleType(this->type), vli.Pack(), this->FirstShared()->index | (1U << 31));
2639  }
2640 
2641  this->next_shared = NULL;
2642  this->previous_shared = NULL;
2643 }
2644 
2645 void VehiclesYearlyLoop()
2646 {
2647  Vehicle *v;
2648  FOR_ALL_VEHICLES(v) {
2649  if (v->IsPrimaryVehicle()) {
2650  /* show warning if vehicle is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */
2651  Money profit = v->GetDisplayProfitThisYear();
2652  if (v->age >= 730 && profit < 0) {
2654  SetDParam(0, v->index);
2655  SetDParam(1, profit);
2656  AddVehicleAdviceNewsItem(STR_NEWS_VEHICLE_IS_UNPROFITABLE, v->index);
2657  }
2658  AI::NewEvent(v->owner, new ScriptEventVehicleUnprofitable(v->index));
2659  }
2660 
2662  v->profit_this_year = 0;
2664  }
2665  }
2671 }
2672 
2673 
2683 bool CanVehicleUseStation(EngineID engine_type, const Station *st)
2684 {
2685  const Engine *e = Engine::GetIfValid(engine_type);
2686  assert(e != NULL);
2687 
2688  switch (e->type) {
2689  case VEH_TRAIN:
2690  return (st->facilities & FACIL_TRAIN) != 0;
2691 
2692  case VEH_ROAD:
2693  /* For road vehicles we need the vehicle to know whether it can actually
2694  * use the station, but if it doesn't have facilities for RVs it is
2695  * certainly not possible that the station can be used. */
2696  return (st->facilities & (FACIL_BUS_STOP | FACIL_TRUCK_STOP)) != 0;
2697 
2698  case VEH_SHIP:
2699  return (st->facilities & FACIL_DOCK) != 0;
2700 
2701  case VEH_AIRCRAFT:
2702  return (st->facilities & FACIL_AIRPORT) != 0 &&
2704 
2705  default:
2706  return false;
2707  }
2708 }
2709 
2716 bool CanVehicleUseStation(const Vehicle *v, const Station *st)
2717 {
2718  if (v->type == VEH_ROAD) return st->GetPrimaryRoadStop(RoadVehicle::From(v)) != NULL;
2719 
2720  return CanVehicleUseStation(v->engine_type, st);
2721 }
2722 
2729 {
2730  assert(this->IsGroundVehicle());
2731  if (this->type == VEH_TRAIN) {
2732  return &Train::From(this)->gcache;
2733  } else {
2734  return &RoadVehicle::From(this)->gcache;
2735  }
2736 }
2737 
2744 {
2745  assert(this->IsGroundVehicle());
2746  if (this->type == VEH_TRAIN) {
2747  return &Train::From(this)->gcache;
2748  } else {
2749  return &RoadVehicle::From(this)->gcache;
2750  }
2751 }
2752 
2759 {
2760  assert(this->IsGroundVehicle());
2761  if (this->type == VEH_TRAIN) {
2762  return Train::From(this)->gv_flags;
2763  } else {
2764  return RoadVehicle::From(this)->gv_flags;
2765  }
2766 }
2767 
2773 const uint16 &Vehicle::GetGroundVehicleFlags() const
2774 {
2775  assert(this->IsGroundVehicle());
2776  if (this->type == VEH_TRAIN) {
2777  return Train::From(this)->gv_flags;
2778  } else {
2779  return RoadVehicle::From(this)->gv_flags;
2780  }
2781 }
2782 
2791 void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8 num_vehicles)
2792 {
2793  if (v->type == VEH_TRAIN) {
2794  Train *u = Train::From(v);
2795  /* Only include whole vehicles, so start with the first articulated part */
2796  u = u->GetFirstEnginePart();
2797 
2798  /* Include num_vehicles vehicles, not counting articulated parts */
2799  for (; u != NULL && num_vehicles > 0; num_vehicles--) {
2800  do {
2801  /* Include current vehicle in the selection. */
2802  set.Include(u->index);
2803 
2804  /* If the vehicle is multiheaded, add the other part too. */
2805  if (u->IsMultiheaded()) set.Include(u->other_multiheaded_part->index);
2806 
2807  u = u->Next();
2808  } while (u != NULL && u->IsArticulatedPart());
2809  }
2810  }
2811 }