OpenTTD
vehicle.cpp
Go to the documentation of this file.
1 /* $Id: vehicle.cpp 26879 2014-09-21 11:24:51Z rubidium $ */
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  this->cargo_payment = NULL;
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  }
750 
751  if (this->IsEngineCountable()) {
753  if (this->IsPrimaryVehicle()) GroupStatistics::CountVehicle(this, -1);
755 
758  }
759 
760  if (this->type == VEH_AIRCRAFT && this->IsPrimaryVehicle()) {
761  Aircraft *a = Aircraft::From(this);
763  if (st != NULL) {
764  const AirportFTA *layout = st->airport.GetFTA()->layout;
765  CLRBITS(st->airport.flags, layout[a->previous_pos].block | layout[a->pos].block);
766  }
767  }
768 
769 
770  if (this->type == VEH_ROAD && this->IsPrimaryVehicle()) {
771  RoadVehicle *v = RoadVehicle::From(this);
772  if (!(v->vehstatus & VS_CRASHED) && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END)) {
773  /* Leave the drive through roadstop, when you have not already left it. */
775  }
776  }
777 
778  if (this->Previous() == NULL) {
780  }
781 
782  if (this->IsPrimaryVehicle()) {
790  }
792 
793  this->cargo.Truncate();
794  DeleteVehicleOrders(this);
796 
797  extern void StopGlobalFollowVehicle(const Vehicle *v);
798  StopGlobalFollowVehicle(this);
799 
801 }
802 
804 {
805  if (CleaningPool()) {
806  this->cargo.OnCleanPool();
807  return;
808  }
809 
810  /* sometimes, eg. for disaster vehicles, when company bankrupts, when removing crashed/flooded vehicles,
811  * it may happen that vehicle chain is deleted when visible */
812  if (!(this->vehstatus & VS_HIDDEN)) this->MarkAllViewportsDirty();
813 
814  Vehicle *v = this->Next();
815  this->SetNext(NULL);
816 
817  delete v;
818 
819  UpdateVehicleTileHash(this, true);
820  UpdateVehicleViewportHash(this, INVALID_COORD, 0);
823 }
824 
830 {
831  /* Vehicle should stop in the depot if it was in 'stopping' state */
832  _vehicles_to_autoreplace[v] = !(v->vehstatus & VS_STOPPED);
833 
834  /* We ALWAYS set the stopped state. Even when the vehicle does not plan on
835  * stopping in the depot, so we stop it to ensure that it will not reserve
836  * the path out of the depot before we might autoreplace it to a different
837  * engine. The new engine would not own the reserved path we store that we
838  * stopped the vehicle, so autoreplace can start it again */
839  v->vehstatus |= VS_STOPPED;
840 }
841 
847 static void RunVehicleDayProc()
848 {
849  if (_game_mode != GM_NORMAL) return;
850 
851  /* Run the day_proc for every DAY_TICKS vehicle starting at _date_fract. */
852  for (size_t i = _date_fract; i < Vehicle::GetPoolSize(); i += DAY_TICKS) {
853  Vehicle *v = Vehicle::Get(i);
854  if (v == NULL) continue;
855 
856  /* Call the 32-day callback if needed */
857  if ((v->day_counter & 0x1F) == 0 && v->HasEngineType()) {
858  uint16 callback = GetVehicleCallback(CBID_VEHICLE_32DAY_CALLBACK, 0, 0, v->engine_type, v);
859  if (callback != CALLBACK_FAILED) {
860  if (HasBit(callback, 0)) {
861  TriggerVehicle(v, VEHICLE_TRIGGER_CALLBACK_32); // Trigger vehicle trigger 10
862  }
863 
864  /* After a vehicle trigger, the graphics and properties of the vehicle could change.
865  * Note: MarkDirty also invalidates the palette, which is the meaning of bit 1. So, nothing special there. */
866  if (callback != 0) v->First()->MarkDirty();
867 
868  if (callback & ~3) ErrorUnknownCallbackResult(v->GetGRFID(), CBID_VEHICLE_32DAY_CALLBACK, callback);
869  }
870  }
871 
872  /* This is called once per day for each vehicle, but not in the first tick of the day */
873  v->OnNewDay();
874  }
875 }
876 
877 void CallVehicleTicks()
878 {
879  _vehicles_to_autoreplace.Clear();
880 
882 
883  Station *st;
884  FOR_ALL_STATIONS(st) LoadUnloadStation(st);
885 
886  Vehicle *v;
887  FOR_ALL_VEHICLES(v) {
888  /* Vehicle could be deleted in this tick */
889  if (!v->Tick()) {
890  assert(Vehicle::Get(vehicle_index) == NULL);
891  continue;
892  }
893 
894  assert(Vehicle::Get(vehicle_index) == v);
895 
896  switch (v->type) {
897  default: break;
898 
899  case VEH_TRAIN:
900  case VEH_ROAD:
901  case VEH_AIRCRAFT:
902  case VEH_SHIP: {
903  Vehicle *front = v->First();
904 
905  if (v->vcache.cached_cargo_age_period != 0) {
906  v->cargo_age_counter = min(v->cargo_age_counter, v->vcache.cached_cargo_age_period);
907  if (--v->cargo_age_counter == 0) {
908  v->cargo.AgeCargo();
909  v->cargo_age_counter = v->vcache.cached_cargo_age_period;
910  }
911  }
912 
913  /* Do not play any sound when crashed */
914  if (front->vehstatus & VS_CRASHED) continue;
915 
916  /* Do not play any sound when in depot or tunnel */
917  if (v->vehstatus & VS_HIDDEN) continue;
918 
919  /* Do not play any sound when stopped */
920  if ((front->vehstatus & VS_STOPPED) && (front->type != VEH_TRAIN || front->cur_speed == 0)) continue;
921 
922  /* Check vehicle type specifics */
923  switch (v->type) {
924  case VEH_TRAIN:
925  if (Train::From(v)->IsWagon()) continue;
926  break;
927 
928  case VEH_ROAD:
929  if (!RoadVehicle::From(v)->IsFrontEngine()) continue;
930  break;
931 
932  case VEH_AIRCRAFT:
933  if (!Aircraft::From(v)->IsNormalAircraft()) continue;
934  break;
935 
936  default:
937  break;
938  }
939 
940  v->motion_counter += front->cur_speed;
941  /* Play a running sound if the motion counter passes 256 (Do we not skip sounds?) */
942  if (GB(v->motion_counter, 0, 8) < front->cur_speed) PlayVehicleSound(v, VSE_RUNNING);
943 
944  /* Play an alternating running sound every 16 ticks */
945  if (GB(v->tick_counter, 0, 4) == 0) {
946  /* Play running sound when speed > 0 and not braking */
947  bool running = (front->cur_speed > 0) && !(front->vehstatus & (VS_STOPPED | VS_TRAIN_SLOWING));
949  }
950 
951  break;
952  }
953  }
954  }
955 
956  Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
957  for (AutoreplaceMap::iterator it = _vehicles_to_autoreplace.Begin(); it != _vehicles_to_autoreplace.End(); it++) {
958  v = it->first;
959  /* Autoreplace needs the current company set as the vehicle owner */
960  cur_company.Change(v->owner);
961 
962  /* Start vehicle if we stopped them in VehicleEnteredDepotThisTick()
963  * We need to stop them between VehicleEnteredDepotThisTick() and here or we risk that
964  * they are already leaving the depot again before being replaced. */
965  if (it->second) v->vehstatus &= ~VS_STOPPED;
966 
967  /* Store the position of the effect as the vehicle pointer will become invalid later */
968  int x = v->x_pos;
969  int y = v->y_pos;
970  int z = v->z_pos;
971 
974  CommandCost res = DoCommand(0, v->index, 0, DC_EXEC, CMD_AUTOREPLACE_VEHICLE);
976 
977  if (!IsLocalCompany()) continue;
978 
979  if (res.Succeeded()) {
980  ShowCostOrIncomeAnimation(x, y, z, res.GetCost());
981  continue;
982  }
983 
984  StringID error_message = res.GetErrorMessage();
985  if (error_message == STR_ERROR_AUTOREPLACE_NOTHING_TO_DO || error_message == INVALID_STRING_ID) continue;
986 
987  if (error_message == STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY) error_message = STR_ERROR_AUTOREPLACE_MONEY_LIMIT;
988 
989  StringID message;
990  if (error_message == STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT) {
991  message = error_message;
992  } else {
993  message = STR_NEWS_VEHICLE_AUTORENEW_FAILED;
994  }
995 
996  SetDParam(0, v->index);
997  SetDParam(1, error_message);
998  AddVehicleAdviceNewsItem(message, v->index);
999  }
1000 
1001  cur_company.Restore();
1002 }
1003 
1008 static void DoDrawVehicle(const Vehicle *v)
1009 {
1010  SpriteID image = v->cur_image;
1011  PaletteID pal = PAL_NONE;
1012 
1014 
1015  /* Check whether the vehicle shall be transparent due to the game state */
1016  bool shadowed = (v->vehstatus & VS_SHADOW) != 0;
1017 
1018  if (v->type == VEH_EFFECT) {
1019  /* Check whether the vehicle shall be transparent/invisible due to GUI settings.
1020  * However, transparent smoke and bubbles look weird, so always hide them. */
1022  if (to != TO_INVALID && (IsTransparencySet(to) || IsInvisibilitySet(to))) return;
1023  }
1024 
1025  AddSortableSpriteToDraw(image, pal, v->x_pos + v->x_offs, v->y_pos + v->y_offs,
1026  v->x_extent, v->y_extent, v->z_extent, v->z_pos, shadowed, v->x_bb_offs, v->y_bb_offs);
1027 }
1028 
1034 {
1035  /* The bounding rectangle */
1036  const int l = dpi->left;
1037  const int r = dpi->left + dpi->width;
1038  const int t = dpi->top;
1039  const int b = dpi->top + dpi->height;
1040 
1041  /* The hash area to scan */
1042  int xl, xu, yl, yu;
1043 
1044  if (dpi->width + (70 * ZOOM_LVL_BASE) < (1 << (7 + 6 + ZOOM_LVL_SHIFT))) {
1045  xl = GB(l - (70 * ZOOM_LVL_BASE), 7 + ZOOM_LVL_SHIFT, 6);
1046  xu = GB(r, 7 + ZOOM_LVL_SHIFT, 6);
1047  } else {
1048  /* scan whole hash row */
1049  xl = 0;
1050  xu = 0x3F;
1051  }
1052 
1053  if (dpi->height + (70 * ZOOM_LVL_BASE) < (1 << (6 + 6 + ZOOM_LVL_SHIFT))) {
1054  yl = GB(t - (70 * ZOOM_LVL_BASE), 6 + ZOOM_LVL_SHIFT, 6) << 6;
1055  yu = GB(b, 6 + ZOOM_LVL_SHIFT, 6) << 6;
1056  } else {
1057  /* scan whole column */
1058  yl = 0;
1059  yu = 0x3F << 6;
1060  }
1061 
1062  for (int y = yl;; y = (y + (1 << 6)) & (0x3F << 6)) {
1063  for (int x = xl;; x = (x + 1) & 0x3F) {
1064  const Vehicle *v = _vehicle_viewport_hash[x + y]; // already masked & 0xFFF
1065 
1066  while (v != NULL) {
1067  if (!(v->vehstatus & VS_HIDDEN) &&
1068  l <= v->coord.right &&
1069  t <= v->coord.bottom &&
1070  r >= v->coord.left &&
1071  b >= v->coord.top) {
1072  DoDrawVehicle(v);
1073  }
1074  v = v->hash_viewport_next;
1075  }
1076 
1077  if (x == xu) break;
1078  }
1079 
1080  if (y == yu) break;
1081  }
1082 }
1083 
1091 Vehicle *CheckClickOnVehicle(const ViewPort *vp, int x, int y)
1092 {
1093  Vehicle *found = NULL, *v;
1094  uint dist, best_dist = UINT_MAX;
1095 
1096  if ((uint)(x -= vp->left) >= (uint)vp->width || (uint)(y -= vp->top) >= (uint)vp->height) return NULL;
1097 
1098  x = ScaleByZoom(x, vp->zoom) + vp->virtual_left;
1099  y = ScaleByZoom(y, vp->zoom) + vp->virtual_top;
1100 
1101  FOR_ALL_VEHICLES(v) {
1102  if ((v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0 &&
1103  x >= v->coord.left && x <= v->coord.right &&
1104  y >= v->coord.top && y <= v->coord.bottom) {
1105 
1106  dist = max(
1107  abs(((v->coord.left + v->coord.right) >> 1) - x),
1108  abs(((v->coord.top + v->coord.bottom) >> 1) - y)
1109  );
1110 
1111  if (dist < best_dist) {
1112  found = v;
1113  best_dist = dist;
1114  }
1115  }
1116  }
1117 
1118  return found;
1119 }
1120 
1126 {
1127  v->value -= v->value >> 8;
1129 }
1130 
1131 static const byte _breakdown_chance[64] = {
1132  3, 3, 3, 3, 3, 3, 3, 3,
1133  4, 4, 5, 5, 6, 6, 7, 7,
1134  8, 8, 9, 9, 10, 10, 11, 11,
1135  12, 13, 13, 13, 13, 14, 15, 16,
1136  17, 19, 21, 25, 28, 31, 34, 37,
1137  40, 44, 48, 52, 56, 60, 64, 68,
1138  72, 80, 90, 100, 110, 120, 130, 140,
1139  150, 170, 190, 210, 230, 250, 250, 250,
1140 };
1141 
1142 void CheckVehicleBreakdown(Vehicle *v)
1143 {
1144  int rel, rel_old;
1145 
1146  /* decrease reliability */
1147  v->reliability = rel = max((rel_old = v->reliability) - v->reliability_spd_dec, 0);
1148  if ((rel_old >> 8) != (rel >> 8)) SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
1149 
1150  if (v->breakdown_ctr != 0 || (v->vehstatus & VS_STOPPED) ||
1152  v->cur_speed < 5 || _game_mode == GM_MENU) {
1153  return;
1154  }
1155 
1156  uint32 r = Random();
1157 
1158  /* increase chance of failure */
1159  int chance = v->breakdown_chance + 1;
1160  if (Chance16I(1, 25, r)) chance += 25;
1161  v->breakdown_chance = min(255, chance);
1162 
1163  /* calculate reliability value to use in comparison */
1164  rel = v->reliability;
1165  if (v->type == VEH_SHIP) rel += 0x6666;
1166 
1167  /* reduced breakdowns? */
1168  if (_settings_game.difficulty.vehicle_breakdowns == 1) rel += 0x6666;
1169 
1170  /* check if to break down */
1171  if (_breakdown_chance[(uint)min(rel, 0xffff) >> 10] <= v->breakdown_chance) {
1172  v->breakdown_ctr = GB(r, 16, 6) + 0x3F;
1173  v->breakdown_delay = GB(r, 24, 7) + 0x80;
1174  v->breakdown_chance = 0;
1175  }
1176 }
1177 
1185 {
1186  /* Possible states for Vehicle::breakdown_ctr
1187  * 0 - vehicle is running normally
1188  * 1 - vehicle is currently broken down
1189  * 2 - vehicle is going to break down now
1190  * >2 - vehicle is counting down to the actual breakdown event */
1191  switch (this->breakdown_ctr) {
1192  case 0:
1193  return false;
1194 
1195  case 2:
1196  this->breakdown_ctr = 1;
1197 
1198  if (this->breakdowns_since_last_service != 255) {
1200  }
1201 
1202  if (this->type == VEH_AIRCRAFT) {
1203  /* Aircraft just need this flag, the rest is handled elsewhere */
1204  this->vehstatus |= VS_AIRCRAFT_BROKEN;
1205  } else {
1206  this->cur_speed = 0;
1207 
1208  if (!PlayVehicleSound(this, VSE_BREAKDOWN)) {
1209  bool train_or_ship = this->type == VEH_TRAIN || this->type == VEH_SHIP;
1210  SndPlayVehicleFx((_settings_game.game_creation.landscape != LT_TOYLAND) ?
1211  (train_or_ship ? SND_10_TRAIN_BREAKDOWN : SND_0F_VEHICLE_BREAKDOWN) :
1212  (train_or_ship ? SND_3A_COMEDY_BREAKDOWN_2 : SND_35_COMEDY_BREAKDOWN), this);
1213  }
1214 
1215  if (!(this->vehstatus & VS_HIDDEN) && !HasBit(EngInfo(this->engine_type)->misc_flags, EF_NO_BREAKDOWN_SMOKE)) {
1217  if (u != NULL) u->animation_state = this->breakdown_delay * 2;
1218  }
1219  }
1220 
1221  this->MarkDirty(); // Update graphics after speed is zeroed
1224 
1225  /* FALL THROUGH */
1226  case 1:
1227  /* Aircraft breakdowns end only when arriving at the airport */
1228  if (this->type == VEH_AIRCRAFT) return false;
1229 
1230  /* For trains this function is called twice per tick, so decrease v->breakdown_delay at half the rate */
1231  if ((this->tick_counter & (this->type == VEH_TRAIN ? 3 : 1)) == 0) {
1232  if (--this->breakdown_delay == 0) {
1233  this->breakdown_ctr = 0;
1234  this->MarkDirty();
1236  }
1237  }
1238  return true;
1239 
1240  default:
1241  if (!this->current_order.IsType(OT_LOADING)) this->breakdown_ctr--;
1242  return false;
1243  }
1244 }
1245 
1251 {
1252  if (v->age < MAX_DAY) {
1253  v->age++;
1255  }
1256 
1257  if (!v->IsPrimaryVehicle() && (v->type != VEH_TRAIN || !Train::From(v)->IsEngine())) return;
1258 
1259  int age = v->age - v->max_age;
1260  if (age == DAYS_IN_LEAP_YEAR * 0 || age == DAYS_IN_LEAP_YEAR * 1 ||
1261  age == DAYS_IN_LEAP_YEAR * 2 || age == DAYS_IN_LEAP_YEAR * 3 || age == DAYS_IN_LEAP_YEAR * 4) {
1262  v->reliability_spd_dec <<= 1;
1263  }
1264 
1266 
1267  /* Don't warn about non-primary or not ours vehicles or vehicles that are crashed */
1268  if (v->Previous() != NULL || v->owner != _local_company || (v->vehstatus & VS_CRASHED) != 0) return;
1269 
1270  /* Don't warn if a renew is active */
1271  if (Company::Get(v->owner)->settings.engine_renew && v->GetEngine()->company_avail != 0) return;
1272 
1273  StringID str;
1274  if (age == -DAYS_IN_LEAP_YEAR) {
1275  str = STR_NEWS_VEHICLE_IS_GETTING_OLD;
1276  } else if (age == 0) {
1277  str = STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD;
1278  } else if (age > 0 && (age % DAYS_IN_LEAP_YEAR) == 0) {
1279  str = STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD_AND;
1280  } else {
1281  return;
1282  }
1283 
1284  SetDParam(0, v->index);
1286 }
1287 
1294 uint8 CalcPercentVehicleFilled(const Vehicle *front, StringID *colour)
1295 {
1296  int count = 0;
1297  int max = 0;
1298  int cars = 0;
1299  int unloading = 0;
1300  bool loading = false;
1301 
1302  bool is_loading = front->current_order.IsType(OT_LOADING);
1303 
1304  /* The station may be NULL when the (colour) string does not need to be set. */
1305  const Station *st = Station::GetIfValid(front->last_station_visited);
1306  assert(colour == NULL || (st != NULL && is_loading));
1307 
1308  bool order_no_load = is_loading && (front->current_order.GetLoadType() & OLFB_NO_LOAD);
1309  bool order_full_load = is_loading && (front->current_order.GetLoadType() & OLFB_FULL_LOAD);
1310 
1311  /* Count up max and used */
1312  for (const Vehicle *v = front; v != NULL; v = v->Next()) {
1313  count += v->cargo.StoredCount();
1314  max += v->cargo_cap;
1315  if (v->cargo_cap != 0 && colour != NULL) {
1316  unloading += HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) ? 1 : 0;
1317  loading |= !order_no_load &&
1318  (order_full_load || st->goods[v->cargo_type].HasRating()) &&
1320  cars++;
1321  }
1322  }
1323 
1324  if (colour != NULL) {
1325  if (unloading == 0 && loading) {
1326  *colour = STR_PERCENT_UP;
1327  } else if (unloading == 0 && !loading) {
1328  *colour = STR_PERCENT_NONE;
1329  } else if (cars == unloading || !loading) {
1330  *colour = STR_PERCENT_DOWN;
1331  } else {
1332  *colour = STR_PERCENT_UP_DOWN;
1333  }
1334  }
1335 
1336  /* Train without capacity */
1337  if (max == 0) return 100;
1338 
1339  /* Return the percentage */
1340  return (count * 100) / max;
1341 }
1342 
1348 {
1349  /* Always work with the front of the vehicle */
1350  assert(v == v->First());
1351 
1352  switch (v->type) {
1353  case VEH_TRAIN: {
1354  Train *t = Train::From(v);
1356  /* Clear path reservation */
1357  SetDepotReservation(t->tile, false);
1359 
1361  t->wait_counter = 0;
1362  t->force_proceed = TFP_NONE;
1363  ClrBit(t->flags, VRF_TOGGLE_REVERSE);
1365  break;
1366  }
1367 
1368  case VEH_ROAD:
1370  break;
1371 
1372  case VEH_SHIP: {
1374  Ship *ship = Ship::From(v);
1375  ship->state = TRACK_BIT_DEPOT;
1376  ship->UpdateCache();
1377  ship->UpdateViewport(true, true);
1379  break;
1380  }
1381 
1382  case VEH_AIRCRAFT:
1385  break;
1386  default: NOT_REACHED();
1387  }
1389 
1390  if (v->type != VEH_TRAIN) {
1391  /* Trains update the vehicle list when the first unit enters the depot and calls VehicleEnterDepot() when the last unit enters.
1392  * 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 */
1394  }
1396 
1397  v->vehstatus |= VS_HIDDEN;
1398  v->cur_speed = 0;
1399 
1401 
1402  /* After a vehicle trigger, the graphics and properties of the vehicle could change. */
1403  TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
1404  v->MarkDirty();
1405 
1406  if (v->current_order.IsType(OT_GOTO_DEPOT)) {
1408 
1409  const Order *real_order = v->GetOrder(v->cur_real_order_index);
1410 
1411  /* Test whether we are heading for this depot. If not, do nothing.
1412  * Note: The target depot for nearest-/manual-depot-orders is only updated on junctions, but we want to accept every depot. */
1414  real_order != NULL && !(real_order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) &&
1415  (v->type == VEH_AIRCRAFT ? v->current_order.GetDestination() != GetStationIndex(v->tile) : v->dest_tile != v->tile)) {
1416  /* We are heading for another depot, keep driving. */
1417  return;
1418  }
1419 
1420  if (v->current_order.IsRefit()) {
1421  Backup<CompanyByte> cur_company(_current_company, v->owner, FILE_LINE);
1422  CommandCost cost = DoCommand(v->tile, v->index, v->current_order.GetRefitCargo() | 0xFF << 8, DC_EXEC, GetCmdRefitVeh(v));
1423  cur_company.Restore();
1424 
1425  if (cost.Failed()) {
1426  _vehicles_to_autoreplace[v] = false;
1427  if (v->owner == _local_company) {
1428  /* Notify the user that we stopped the vehicle */
1429  SetDParam(0, v->index);
1430  AddVehicleAdviceNewsItem(STR_NEWS_ORDER_REFIT_FAILED, v->index);
1431  }
1432  } else if (cost.GetCost() != 0) {
1433  v->profit_this_year -= cost.GetCost() << 8;
1434  if (v->owner == _local_company) {
1435  ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
1436  }
1437  }
1438  }
1439 
1441  /* Part of orders */
1443  UpdateVehicleTimetable(v, true);
1445  }
1447  /* Vehicles are always stopped on entering depots. Do not restart this one. */
1448  _vehicles_to_autoreplace[v] = false;
1449  /* Invalidate last_loading_station. As the link from the station
1450  * before the stop to the station after the stop can't be predicted
1451  * we shouldn't construct it when the vehicle visits the next stop. */
1452  v->last_loading_station = INVALID_STATION;
1453  if (v->owner == _local_company) {
1454  SetDParam(0, v->index);
1455  AddVehicleAdviceNewsItem(STR_NEWS_TRAIN_IS_WAITING + v->type, v->index);
1456  }
1457  AI::NewEvent(v->owner, new ScriptEventVehicleWaitingInDepot(v->index));
1458  }
1459  v->current_order.MakeDummy();
1460  }
1461 }
1462 
1463 
1469 {
1470  UpdateVehicleTileHash(this, false);
1471 }
1472 
1478 void Vehicle::UpdateViewport(bool dirty)
1479 {
1480  int img = this->cur_image;
1481  Point pt = RemapCoords(this->x_pos + this->x_offs, this->y_pos + this->y_offs, this->z_pos);
1482  const Sprite *spr = GetSprite(img, ST_NORMAL);
1483 
1484  pt.x += spr->x_offs;
1485  pt.y += spr->y_offs;
1486 
1487  UpdateVehicleViewportHash(this, pt.x, pt.y);
1488 
1489  Rect old_coord = this->coord;
1490  this->coord.left = pt.x;
1491  this->coord.top = pt.y;
1492  this->coord.right = pt.x + spr->width + 2 * ZOOM_LVL_BASE;
1493  this->coord.bottom = pt.y + spr->height + 2 * ZOOM_LVL_BASE;
1494 
1495  if (dirty) {
1496  if (old_coord.left == INVALID_COORD) {
1497  this->MarkAllViewportsDirty();
1498  } else {
1500  min(old_coord.left, this->coord.left),
1501  min(old_coord.top, this->coord.top),
1502  max(old_coord.right, this->coord.right) + 1 * ZOOM_LVL_BASE,
1503  max(old_coord.bottom, this->coord.bottom) + 1 * ZOOM_LVL_BASE
1504  );
1505  }
1506  }
1507 }
1508 
1513 {
1514  this->UpdatePosition();
1515  this->UpdateViewport(true);
1516 }
1517 
1522 {
1523  ::MarkAllViewportsDirty(this->coord.left, this->coord.top, this->coord.right + 1 * ZOOM_LVL_BASE, this->coord.bottom + 1 * ZOOM_LVL_BASE);
1524 }
1525 
1532 {
1533  static const int8 _delta_coord[16] = {
1534  -1,-1,-1, 0, 1, 1, 1, 0, /* x */
1535  -1, 0, 1, 1, 1, 0,-1,-1, /* y */
1536  };
1537 
1538  int x = v->x_pos + _delta_coord[v->direction];
1539  int y = v->y_pos + _delta_coord[v->direction + 8];
1540 
1542  gp.x = x;
1543  gp.y = y;
1544  gp.old_tile = v->tile;
1545  gp.new_tile = TileVirtXY(x, y);
1546  return gp;
1547 }
1548 
1549 static const Direction _new_direction_table[] = {
1550  DIR_N, DIR_NW, DIR_W,
1551  DIR_NE, DIR_SE, DIR_SW,
1552  DIR_E, DIR_SE, DIR_S
1553 };
1554 
1555 Direction GetDirectionTowards(const Vehicle *v, int x, int y)
1556 {
1557  int i = 0;
1558 
1559  if (y >= v->y_pos) {
1560  if (y != v->y_pos) i += 3;
1561  i += 3;
1562  }
1563 
1564  if (x >= v->x_pos) {
1565  if (x != v->x_pos) i++;
1566  i++;
1567  }
1568 
1569  Direction dir = v->direction;
1570 
1571  DirDiff dirdiff = DirDifference(_new_direction_table[i], dir);
1572  if (dirdiff == DIRDIFF_SAME) return dir;
1573  return ChangeDir(dir, dirdiff > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT);
1574 }
1575 
1586 {
1587  return _tile_type_procs[GetTileType(tile)]->vehicle_enter_tile_proc(v, tile, x, y);
1588 }
1589 
1597 FreeUnitIDGenerator::FreeUnitIDGenerator(VehicleType type, CompanyID owner) : cache(NULL), maxid(0), curid(0)
1598 {
1599  /* Find maximum */
1600  const Vehicle *v;
1601  FOR_ALL_VEHICLES(v) {
1602  if (v->type == type && v->owner == owner) {
1603  this->maxid = max<UnitID>(this->maxid, v->unitnumber);
1604  }
1605  }
1606 
1607  if (this->maxid == 0) return;
1608 
1609  /* Reserving 'maxid + 2' because we need:
1610  * - space for the last item (with v->unitnumber == maxid)
1611  * - one free slot working as loop terminator in FreeUnitIDGenerator::NextID() */
1612  this->cache = CallocT<bool>(this->maxid + 2);
1613 
1614  /* Fill the cache */
1615  FOR_ALL_VEHICLES(v) {
1616  if (v->type == type && v->owner == owner) {
1617  this->cache[v->unitnumber] = true;
1618  }
1619  }
1620 }
1621 
1624 {
1625  if (this->maxid <= this->curid) return ++this->curid;
1626 
1627  while (this->cache[++this->curid]) { } // it will stop, we reserved more space than needed
1628 
1629  return this->curid;
1630 }
1631 
1638 {
1639  /* Check whether it is allowed to build another vehicle. */
1640  uint max_veh;
1641  switch (type) {
1642  case VEH_TRAIN: max_veh = _settings_game.vehicle.max_trains; break;
1643  case VEH_ROAD: max_veh = _settings_game.vehicle.max_roadveh; break;
1644  case VEH_SHIP: max_veh = _settings_game.vehicle.max_ships; break;
1645  case VEH_AIRCRAFT: max_veh = _settings_game.vehicle.max_aircraft; break;
1646  default: NOT_REACHED();
1647  }
1648 
1650  if (c->group_all[type].num_vehicle >= max_veh) return UINT16_MAX; // Currently already at the limit, no room to make a new one.
1651 
1653 
1654  return gen.NextID();
1655 }
1656 
1657 
1667 {
1668  assert(IsCompanyBuildableVehicleType(type));
1669 
1670  if (!Company::IsValidID(_local_company)) return false;
1672 
1673  UnitID max;
1674  switch (type) {
1675  case VEH_TRAIN: max = _settings_game.vehicle.max_trains; break;
1676  case VEH_ROAD: max = _settings_game.vehicle.max_roadveh; break;
1677  case VEH_SHIP: max = _settings_game.vehicle.max_ships; break;
1678  case VEH_AIRCRAFT: max = _settings_game.vehicle.max_aircraft; break;
1679  default: NOT_REACHED();
1680  }
1681 
1682  /* We can build vehicle infrastructure when we may build the vehicle type */
1683  if (max > 0) {
1684  /* Can we actually build the vehicle type? */
1685  const Engine *e;
1686  FOR_ALL_ENGINES_OF_TYPE(e, type) {
1687  if (HasBit(e->company_avail, _local_company)) return true;
1688  }
1689  return false;
1690  }
1691 
1692  /* We should be able to build infrastructure when we have the actual vehicle type */
1693  const Vehicle *v;
1694  FOR_ALL_VEHICLES(v) {
1695  if (v->owner == _local_company && v->type == type) return true;
1696  }
1697 
1698  return false;
1699 }
1700 
1701 
1709 LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_type, const Vehicle *v)
1710 {
1711  CargoID cargo_type = v == NULL ? (CargoID)CT_INVALID : v->cargo_type;
1712  const Engine *e = Engine::Get(engine_type);
1713  switch (e->type) {
1714  default: NOT_REACHED();
1715  case VEH_TRAIN:
1716  if (v != NULL && parent_engine_type != INVALID_ENGINE && (UsesWagonOverride(v) || (v->IsArticulatedPart() && e->u.rail.railveh_type != RAILVEH_WAGON))) {
1717  /* Wagonoverrides use the colour scheme of the front engine.
1718  * Articulated parts use the colour scheme of the first part. (Not supported for articulated wagons) */
1719  engine_type = parent_engine_type;
1720  e = Engine::Get(engine_type);
1721  /* Note: Luckily cargo_type is not needed for engines */
1722  }
1723 
1724  if (cargo_type == CT_INVALID) cargo_type = e->GetDefaultCargoType();
1725  if (cargo_type == CT_INVALID) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo
1726  if (e->u.rail.railveh_type == RAILVEH_WAGON) {
1727  if (!CargoSpec::Get(cargo_type)->is_freight) {
1728  if (parent_engine_type == INVALID_ENGINE) {
1729  return LS_PASSENGER_WAGON_STEAM;
1730  } else {
1731  switch (RailVehInfo(parent_engine_type)->engclass) {
1732  default: NOT_REACHED();
1733  case EC_STEAM: return LS_PASSENGER_WAGON_STEAM;
1734  case EC_DIESEL: return LS_PASSENGER_WAGON_DIESEL;
1735  case EC_ELECTRIC: return LS_PASSENGER_WAGON_ELECTRIC;
1736  case EC_MONORAIL: return LS_PASSENGER_WAGON_MONORAIL;
1737  case EC_MAGLEV: return LS_PASSENGER_WAGON_MAGLEV;
1738  }
1739  }
1740  } else {
1741  return LS_FREIGHT_WAGON;
1742  }
1743  } else {
1744  bool is_mu = HasBit(e->info.misc_flags, EF_RAIL_IS_MU);
1745 
1746  switch (e->u.rail.engclass) {
1747  default: NOT_REACHED();
1748  case EC_STEAM: return LS_STEAM;
1749  case EC_DIESEL: return is_mu ? LS_DMU : LS_DIESEL;
1750  case EC_ELECTRIC: return is_mu ? LS_EMU : LS_ELECTRIC;
1751  case EC_MONORAIL: return LS_MONORAIL;
1752  case EC_MAGLEV: return LS_MAGLEV;
1753  }
1754  }
1755 
1756  case VEH_ROAD:
1757  /* Always use the livery of the front */
1758  if (v != NULL && parent_engine_type != INVALID_ENGINE) {
1759  engine_type = parent_engine_type;
1760  e = Engine::Get(engine_type);
1761  cargo_type = v->First()->cargo_type;
1762  }
1763  if (cargo_type == CT_INVALID) cargo_type = e->GetDefaultCargoType();
1764  if (cargo_type == CT_INVALID) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo
1765 
1766  /* Important: Use Tram Flag of front part. Luckily engine_type refers to the front part here. */
1767  if (HasBit(e->info.misc_flags, EF_ROAD_TRAM)) {
1768  /* Tram */
1769  return IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_TRAM : LS_FREIGHT_TRAM;
1770  } else {
1771  /* Bus or truck */
1772  return IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_BUS : LS_TRUCK;
1773  }
1774 
1775  case VEH_SHIP:
1776  if (cargo_type == CT_INVALID) cargo_type = e->GetDefaultCargoType();
1777  if (cargo_type == CT_INVALID) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo
1778  return IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_SHIP : LS_FREIGHT_SHIP;
1779 
1780  case VEH_AIRCRAFT:
1781  switch (e->u.air.subtype) {
1782  case AIR_HELI: return LS_HELICOPTER;
1783  case AIR_CTOL: return LS_SMALL_PLANE;
1784  case AIR_CTOL | AIR_FAST: return LS_LARGE_PLANE;
1785  default: NOT_REACHED();
1786  }
1787  }
1788 }
1789 
1799 const Livery *GetEngineLivery(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v, byte livery_setting)
1800 {
1801  const Company *c = Company::Get(company);
1802  LiveryScheme scheme = LS_DEFAULT;
1803 
1804  /* The default livery is always available for use, but its in_use flag determines
1805  * whether any _other_ liveries are in use. */
1806  if (c->livery[LS_DEFAULT].in_use && (livery_setting == LIT_ALL || (livery_setting == LIT_COMPANY && company == _local_company))) {
1807  /* Determine the livery scheme to use */
1808  scheme = GetEngineLiveryScheme(engine_type, parent_engine_type, v);
1809 
1810  /* Switch back to the default scheme if the resolved scheme is not in use */
1811  if (!c->livery[scheme].in_use) scheme = LS_DEFAULT;
1812  }
1813 
1814  return &c->livery[scheme];
1815 }
1816 
1817 
1818 static PaletteID GetEngineColourMap(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v)
1819 {
1820  PaletteID map = (v != NULL) ? v->colourmap : PAL_NONE;
1821 
1822  /* Return cached value if any */
1823  if (map != PAL_NONE) return map;
1824 
1825  const Engine *e = Engine::Get(engine_type);
1826 
1827  /* Check if we should use the colour map callback */
1829  uint16 callback = GetVehicleCallback(CBID_VEHICLE_COLOUR_MAPPING, 0, 0, engine_type, v);
1830  /* Failure means "use the default two-colour" */
1831  if (callback != CALLBACK_FAILED) {
1832  assert_compile(PAL_NONE == 0); // Returning 0x4000 (resp. 0xC000) coincidences with default value (PAL_NONE)
1833  map = GB(callback, 0, 14);
1834  /* If bit 14 is set, then the company colours are applied to the
1835  * map else it's returned as-is. */
1836  if (!HasBit(callback, 14)) {
1837  /* Update cache */
1838  if (v != NULL) const_cast<Vehicle *>(v)->colourmap = map;
1839  return map;
1840  }
1841  }
1842  }
1843 
1844  bool twocc = HasBit(e->info.misc_flags, EF_USES_2CC);
1845 
1846  if (map == PAL_NONE) map = twocc ? (PaletteID)SPR_2CCMAP_BASE : (PaletteID)PALETTE_RECOLOUR_START;
1847 
1848  /* Spectator has news shown too, but has invalid company ID - as well as dedicated server */
1849  if (!Company::IsValidID(company)) return map;
1850 
1851  const Livery *livery = GetEngineLivery(engine_type, company, parent_engine_type, v, _settings_client.gui.liveries);
1852 
1853  map += livery->colour1;
1854  if (twocc) map += livery->colour2 * 16;
1855 
1856  /* Update cache */
1857  if (v != NULL) const_cast<Vehicle *>(v)->colourmap = map;
1858  return map;
1859 }
1860 
1868 {
1869  return GetEngineColourMap(engine_type, company, INVALID_ENGINE, NULL);
1870 }
1871 
1878 {
1879  if (v->IsGroundVehicle()) {
1880  return GetEngineColourMap(v->engine_type, v->owner, v->GetGroundVehicleCache()->first_engine, v);
1881  }
1882 
1883  return GetEngineColourMap(v->engine_type, v->owner, INVALID_ENGINE, v);
1884 }
1885 
1890 {
1891  if (this->IsGroundVehicle()) {
1892  uint16 &gv_flags = this->GetGroundVehicleFlags();
1893  if (HasBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS)) {
1894  /* Do not delete orders, only skip them */
1897  InvalidateVehicleOrder(this, 0);
1898  return;
1899  }
1900  }
1901 
1902  const Order *order = this->GetOrder(this->cur_implicit_order_index);
1903  while (order != NULL) {
1904  if (this->cur_implicit_order_index == this->cur_real_order_index) break;
1905 
1906  if (order->IsType(OT_IMPLICIT)) {
1908  /* DeleteOrder does various magic with order_indices, so resync 'order' with 'cur_implicit_order_index' */
1909  order = this->GetOrder(this->cur_implicit_order_index);
1910  } else {
1911  /* Skip non-implicit orders, e.g. service-orders */
1912  order = order->next;
1913  this->cur_implicit_order_index++;
1914  }
1915 
1916  /* Wrap around */
1917  if (order == NULL) {
1918  order = this->GetOrder(0);
1919  this->cur_implicit_order_index = 0;
1920  }
1921  }
1922 }
1923 
1929 {
1930  assert(IsTileType(this->tile, MP_STATION) || this->type == VEH_SHIP);
1931 
1932  if (this->current_order.IsType(OT_GOTO_STATION) &&
1935 
1936  /* Now both order indices point to the destination station, and we can start loading */
1937  this->current_order.MakeLoading(true);
1938  UpdateVehicleTimetable(this, true);
1939 
1940  /* Furthermore add the Non Stop flag to mark that this station
1941  * is the actual destination of the vehicle, which is (for example)
1942  * necessary to be known for HandleTrainLoading to determine
1943  * whether the train is lost or not; not marking a train lost
1944  * that arrives at random stations is bad. */
1946 
1947  } else {
1948  /* We weren't scheduled to stop here. Insert an implicit order
1949  * to show that we are stopping here.
1950  * While only groundvehicles have implicit orders, e.g. aircraft might still enter
1951  * the 'wrong' terminal when skipping orders etc. */
1952  Order *in_list = this->GetOrder(this->cur_implicit_order_index);
1953  if (this->IsGroundVehicle() &&
1954  (in_list == NULL || !in_list->IsType(OT_IMPLICIT) ||
1955  in_list->GetDestination() != this->last_station_visited)) {
1956  bool suppress_implicit_orders = HasBit(this->GetGroundVehicleFlags(), GVF_SUPPRESS_IMPLICIT_ORDERS);
1957  /* Do not create consecutive duplicates of implicit orders */
1958  Order *prev_order = this->cur_implicit_order_index > 0 ? this->GetOrder(this->cur_implicit_order_index - 1) : (this->GetNumOrders() > 1 ? this->GetLastOrder() : NULL);
1959  if (prev_order == NULL ||
1960  (!prev_order->IsType(OT_IMPLICIT) && !prev_order->IsType(OT_GOTO_STATION)) ||
1961  prev_order->GetDestination() != this->last_station_visited) {
1962 
1963  /* Prefer deleting implicit orders instead of inserting new ones,
1964  * so test whether the right order follows later. In case of only
1965  * implicit orders treat the last order in the list like an
1966  * explicit one, except if the overall number of orders surpasses
1967  * IMPLICIT_ORDER_ONLY_CAP. */
1968  int target_index = this->cur_implicit_order_index;
1969  bool found = false;
1970  while (target_index != this->cur_real_order_index || this->GetNumManualOrders() == 0) {
1971  const Order *order = this->GetOrder(target_index);
1972  if (order == NULL) break; // No orders.
1973  if (order->IsType(OT_IMPLICIT) && order->GetDestination() == this->last_station_visited) {
1974  found = true;
1975  break;
1976  }
1977  target_index++;
1978  if (target_index >= this->orders.list->GetNumOrders()) {
1979  if (this->GetNumManualOrders() == 0 &&
1981  break;
1982  }
1983  target_index = 0;
1984  }
1985  if (target_index == this->cur_implicit_order_index) break; // Avoid infinite loop.
1986  }
1987 
1988  if (found) {
1989  if (suppress_implicit_orders) {
1990  /* Skip to the found order */
1991  this->cur_implicit_order_index = target_index;
1992  InvalidateVehicleOrder(this, 0);
1993  } else {
1994  /* Delete all implicit orders up to the station we just reached */
1995  const Order *order = this->GetOrder(this->cur_implicit_order_index);
1996  while (!order->IsType(OT_IMPLICIT) || order->GetDestination() != this->last_station_visited) {
1997  if (order->IsType(OT_IMPLICIT)) {
1999  /* DeleteOrder does various magic with order_indices, so resync 'order' with 'cur_implicit_order_index' */
2000  order = this->GetOrder(this->cur_implicit_order_index);
2001  } else {
2002  /* Skip non-implicit orders, e.g. service-orders */
2003  order = order->next;
2004  this->cur_implicit_order_index++;
2005  }
2006 
2007  /* Wrap around */
2008  if (order == NULL) {
2009  order = this->GetOrder(0);
2010  this->cur_implicit_order_index = 0;
2011  }
2012  assert(order != NULL);
2013  }
2014  }
2015  } else if (!suppress_implicit_orders &&
2016  ((this->orders.list == NULL ? OrderList::CanAllocateItem() : this->orders.list->GetNumOrders() < MAX_VEH_ORDER_ID)) &&
2018  /* Insert new implicit order */
2019  Order *implicit_order = new Order();
2020  implicit_order->MakeImplicit(this->last_station_visited);
2021  InsertOrder(this, implicit_order, this->cur_implicit_order_index);
2022  if (this->cur_implicit_order_index > 0) --this->cur_implicit_order_index;
2023 
2024  /* InsertOrder disabled creation of implicit orders for all vehicles with the same implicit order.
2025  * Reenable it for this vehicle */
2026  uint16 &gv_flags = this->GetGroundVehicleFlags();
2028  }
2029  }
2030  }
2031  this->current_order.MakeLoading(false);
2032  }
2033 
2034  if (this->last_loading_station != INVALID_STATION &&
2035  this->last_loading_station != this->last_station_visited &&
2036  ((this->current_order.GetLoadType() & OLFB_NO_LOAD) == 0 ||
2037  (this->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0)) {
2039  }
2040 
2041  PrepareUnload(this);
2042 
2047 
2048  Station::Get(this->last_station_visited)->MarkTilesDirty(true);
2049  this->cur_speed = 0;
2050  this->MarkDirty();
2051 }
2052 
2058 void Vehicle::CancelReservation(StationID next, Station *st)
2059 {
2060  for (Vehicle *v = this; v != NULL; v = v->next) {
2062  if (cargo.ActionCount(VehicleCargoList::MTA_LOAD) > 0) {
2063  DEBUG(misc, 1, "cancelling cargo reservation");
2064  cargo.Return(UINT_MAX, &st->goods[v->cargo_type].cargo, next);
2065  cargo.SetTransferLoadPlace(st->xy);
2066  }
2067  cargo.KeepAll();
2068  }
2069 }
2070 
2076 {
2077  assert(this->current_order.IsType(OT_LOADING));
2078 
2079  delete this->cargo_payment;
2080 
2081  /* Only update the timetable if the vehicle was supposed to stop here. */
2083 
2084  if ((this->current_order.GetLoadType() & OLFB_NO_LOAD) == 0 ||
2085  (this->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
2086  if (this->current_order.CanLeaveWithCargo(this->last_loading_station != INVALID_STATION)) {
2087  /* Refresh next hop stats to make sure we've done that at least once
2088  * during the stop and that refit_cap == cargo_cap for each vehicle in
2089  * the consist. */
2090  this->ResetRefitCaps();
2091  LinkRefresher::Run(this);
2092 
2093  /* if the vehicle could load here or could stop with cargo loaded set the last loading station */
2095  } else {
2096  /* if the vehicle couldn't load and had to unload or transfer everything
2097  * set the last loading station to invalid as it will leave empty. */
2098  this->last_loading_station = INVALID_STATION;
2099  }
2100  }
2101 
2104  this->CancelReservation(INVALID_STATION, st);
2105  st->loading_vehicles.remove(this);
2106 
2108 
2109  if (this->type == VEH_TRAIN && !(this->vehstatus & VS_CRASHED)) {
2110  /* Trigger station animation (trains only) */
2111  if (IsTileType(this->tile, MP_STATION)) {
2113  TriggerStationAnimation(st, this->tile, SAT_TRAIN_DEPARTS);
2114  }
2115 
2116  SetBit(Train::From(this)->flags, VRF_LEAVING_STATION);
2117  }
2118 
2119  this->MarkDirty();
2120 }
2121 
2126 {
2127  for (Vehicle *v = this; v != NULL; v = v->Next()) v->refit_cap = v->cargo_cap;
2128 }
2129 
2135 void Vehicle::HandleLoading(bool mode)
2136 {
2137  switch (this->current_order.GetType()) {
2138  case OT_LOADING: {
2139  uint wait_time = max(this->current_order.GetTimetabledWait() - this->lateness_counter, 0);
2140 
2141  /* Not the first call for this tick, or still loading */
2142  if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) || this->current_order_time < wait_time) return;
2143 
2144  this->PlayLeaveStationSound();
2145 
2146  this->LeaveStation();
2147 
2148  /* Only advance to next order if we just loaded at the current one */
2149  const Order *order = this->GetOrder(this->cur_implicit_order_index);
2150  if (order == NULL ||
2151  (!order->IsType(OT_IMPLICIT) && !order->IsType(OT_GOTO_STATION)) ||
2152  order->GetDestination() != this->last_station_visited) {
2153  return;
2154  }
2155  break;
2156  }
2157 
2158  case OT_DUMMY: break;
2159 
2160  default: return;
2161  }
2162 
2164 }
2165 
2171 {
2172  for (const Vehicle *v = this; v != NULL; v = v->Next()) {
2173  if (v->cargo_cap == 0) continue;
2174  SmallPair<CargoID, uint> *pair = capacities.Find(v->cargo_type);
2175  if (pair == capacities.End()) {
2176  pair = capacities.Append();
2177  pair->first = v->cargo_type;
2178  pair->second = v->cargo_cap - v->cargo.StoredCount();
2179  } else {
2180  pair->second += v->cargo_cap - v->cargo.StoredCount();
2181  }
2182  }
2183 }
2184 
2185 uint Vehicle::GetConsistTotalCapacity() const
2186 {
2187  uint result = 0;
2188  for (const Vehicle *v = this; v != NULL; v = v->Next()) {
2189  result += v->cargo_cap;
2190  }
2191  return result;
2192 }
2193 
2201 {
2202  CommandCost ret = CheckOwnership(this->owner);
2203  if (ret.Failed()) return ret;
2204 
2205  if (this->vehstatus & VS_CRASHED) return CMD_ERROR;
2206  if (this->IsStoppedInDepot()) return CMD_ERROR;
2207 
2208  if (this->current_order.IsType(OT_GOTO_DEPOT)) {
2209  bool halt_in_depot = (this->current_order.GetDepotActionType() & ODATFB_HALT) != 0;
2210  if (!!(command & DEPOT_SERVICE) == halt_in_depot) {
2211  /* We called with a different DEPOT_SERVICE setting.
2212  * Now we change the setting to apply the new one and let the vehicle head for the same depot.
2213  * Note: the if is (true for requesting service == true for ordered to stop in depot) */
2214  if (flags & DC_EXEC) {
2218  }
2219  return CommandCost();
2220  }
2221 
2222  if (command & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders
2223  if (flags & DC_EXEC) {
2224  /* If the orders to 'goto depot' are in the orders list (forced servicing),
2225  * then skip to the next order; effectively cancelling this forced service */
2227 
2228  if (this->IsGroundVehicle()) {
2229  uint16 &gv_flags = this->GetGroundVehicleFlags();
2231  }
2232 
2233  this->current_order.MakeDummy();
2235  }
2236  return CommandCost();
2237  }
2238 
2239  TileIndex location;
2240  DestinationID destination;
2241  bool reverse;
2242  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};
2243  if (!this->FindClosestDepot(&location, &destination, &reverse)) return_cmd_error(no_depot[this->type]);
2244 
2245  if (flags & DC_EXEC) {
2246  if (this->current_order.IsType(OT_LOADING)) this->LeaveStation();
2247 
2248  if (this->IsGroundVehicle() && this->GetNumManualOrders() > 0) {
2249  uint16 &gv_flags = this->GetGroundVehicleFlags();
2251  }
2252 
2253  this->dest_tile = location;
2254  this->current_order.MakeGoToDepot(destination, ODTF_MANUAL);
2255  if (!(command & DEPOT_SERVICE)) this->current_order.SetDepotActionType(ODATFB_HALT);
2257 
2258  /* If there is no depot in front, reverse automatically (trains only) */
2259  if (this->type == VEH_TRAIN && reverse) DoCommand(this->tile, this->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
2260 
2261  if (this->type == VEH_AIRCRAFT) {
2262  Aircraft *a = Aircraft::From(this);
2263  if (a->state == FLYING && a->targetairport != destination) {
2264  /* The aircraft is now heading for a different hangar than the next in the orders */
2267  }
2268  }
2269  }
2270 
2271  return CommandCost();
2272 
2273 }
2274 
2279 void Vehicle::UpdateVisualEffect(bool allow_power_change)
2280 {
2281  bool powered_before = HasBit(this->vcache.cached_vis_effect, VE_DISABLE_WAGON_POWER);
2282  const Engine *e = this->GetEngine();
2283 
2284  /* Evaluate properties */
2285  byte visual_effect;
2286  switch (e->type) {
2287  case VEH_TRAIN: visual_effect = e->u.rail.visual_effect; break;
2288  case VEH_ROAD: visual_effect = e->u.road.visual_effect; break;
2289  case VEH_SHIP: visual_effect = e->u.ship.visual_effect; break;
2290  default: visual_effect = 1 << VE_DISABLE_EFFECT; break;
2291  }
2292 
2293  /* Check powered wagon / visual effect callback */
2295  uint16 callback = GetVehicleCallback(CBID_VEHICLE_VISUAL_EFFECT, 0, 0, this->engine_type, this);
2296 
2297  if (callback != CALLBACK_FAILED) {
2298  if (callback >= 0x100 && e->GetGRF()->grf_version >= 8) ErrorUnknownCallbackResult(e->GetGRFID(), CBID_VEHICLE_VISUAL_EFFECT, callback);
2299 
2300  callback = GB(callback, 0, 8);
2301  /* Avoid accidentally setting 'visual_effect' to the default value
2302  * Since bit 6 (disable effects) is set anyways, we can safely erase some bits. */
2303  if (callback == VE_DEFAULT) {
2304  assert(HasBit(callback, VE_DISABLE_EFFECT));
2305  SB(callback, VE_TYPE_START, VE_TYPE_COUNT, 0);
2306  }
2307  visual_effect = callback;
2308  }
2309  }
2310 
2311  /* Apply default values */
2312  if (visual_effect == VE_DEFAULT ||
2313  (!HasBit(visual_effect, VE_DISABLE_EFFECT) && GB(visual_effect, VE_TYPE_START, VE_TYPE_COUNT) == VE_TYPE_DEFAULT)) {
2314  /* Only train engines have default effects.
2315  * Note: This is independent of whether the engine is a front engine or articulated part or whatever. */
2316  if (e->type != VEH_TRAIN || e->u.rail.railveh_type == RAILVEH_WAGON || !IsInsideMM(e->u.rail.engclass, EC_STEAM, EC_MONORAIL)) {
2317  if (visual_effect == VE_DEFAULT) {
2318  visual_effect = 1 << VE_DISABLE_EFFECT;
2319  } else {
2320  SetBit(visual_effect, VE_DISABLE_EFFECT);
2321  }
2322  } else {
2323  if (visual_effect == VE_DEFAULT) {
2324  /* Also set the offset */
2325  visual_effect = (VE_OFFSET_CENTRE - (e->u.rail.engclass == EC_STEAM ? 4 : 0)) << VE_OFFSET_START;
2326  }
2327  SB(visual_effect, VE_TYPE_START, VE_TYPE_COUNT, e->u.rail.engclass - EC_STEAM + VE_TYPE_STEAM);
2328  }
2329  }
2330 
2331  this->vcache.cached_vis_effect = visual_effect;
2332 
2333  if (!allow_power_change && powered_before != HasBit(this->vcache.cached_vis_effect, VE_DISABLE_WAGON_POWER)) {
2335  ShowNewGrfVehicleError(this->engine_type, STR_NEWGRF_BROKEN, STR_NEWGRF_BROKEN_POWERED_WAGON, GBUG_VEH_POWERED_WAGON, false);
2336  }
2337 }
2338 
2339 static const int8 _vehicle_smoke_pos[8] = {
2340  1, 1, 1, 0, -1, -1, -1, 0
2341 };
2342 
2347 static void SpawnAdvancedVisualEffect(const Vehicle *v)
2348 {
2349  uint16 callback = GetVehicleCallback(CBID_VEHICLE_SPAWN_VISUAL_EFFECT, 0, Random(), v->engine_type, v);
2350  if (callback == CALLBACK_FAILED) return;
2351 
2352  uint count = GB(callback, 0, 2);
2353  bool auto_center = HasBit(callback, 13);
2354  bool auto_rotate = !HasBit(callback, 14);
2355 
2356  int8 l_center = 0;
2357  if (auto_center) {
2358  /* For road vehicles: Compute offset from vehicle position to vehicle center */
2359  if (v->type == VEH_ROAD) l_center = -(int)(VEHICLE_LENGTH - RoadVehicle::From(v)->gcache.cached_veh_length) / 2;
2360  } else {
2361  /* For trains: Compute offset from vehicle position to sprite position */
2362  if (v->type == VEH_TRAIN) l_center = (VEHICLE_LENGTH - Train::From(v)->gcache.cached_veh_length) / 2;
2363  }
2364 
2365  Direction l_dir = v->direction;
2366  if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_REVERSE_DIRECTION)) l_dir = ReverseDir(l_dir);
2367  Direction t_dir = ChangeDir(l_dir, DIRDIFF_90RIGHT);
2368 
2369  int8 x_center = _vehicle_smoke_pos[l_dir] * l_center;
2370  int8 y_center = _vehicle_smoke_pos[t_dir] * l_center;
2371 
2372  for (uint i = 0; i < count; i++) {
2373  uint32 reg = GetRegister(0x100 + i);
2374  uint type = GB(reg, 0, 8);
2375  int8 x = GB(reg, 8, 8);
2376  int8 y = GB(reg, 16, 8);
2377  int8 z = GB(reg, 24, 8);
2378 
2379  if (auto_rotate) {
2380  int8 l = x;
2381  int8 t = y;
2382  x = _vehicle_smoke_pos[l_dir] * l + _vehicle_smoke_pos[t_dir] * t;
2383  y = _vehicle_smoke_pos[t_dir] * l - _vehicle_smoke_pos[l_dir] * t;
2384  }
2385 
2386  if (type >= 0xF0) {
2387  switch (type) {
2388  case 0xF1: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_STEAM_SMOKE); break;
2389  case 0xF2: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_DIESEL_SMOKE); break;
2390  case 0xF3: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_ELECTRIC_SPARK); break;
2391  case 0xFA: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_BREAKDOWN_SMOKE_AIRCRAFT); break;
2392  default: break;
2393  }
2394  }
2395  }
2396 }
2397 
2403 {
2404  assert(this->IsPrimaryVehicle());
2405  bool sound = false;
2406 
2407  /* Do not show any smoke when:
2408  * - vehicle smoke is disabled by the player
2409  * - the vehicle is slowing down or stopped (by the player)
2410  * - the vehicle is moving very slowly
2411  */
2412  if (_settings_game.vehicle.smoke_amount == 0 ||
2413  this->vehstatus & (VS_TRAIN_SLOWING | VS_STOPPED) ||
2414  this->cur_speed < 2) {
2415  return;
2416  }
2417 
2418  uint max_speed = this->vcache.cached_max_speed;
2419  if (this->type == VEH_TRAIN) {
2420  const Train *t = Train::From(this);
2421  /* For trains, do not show any smoke when:
2422  * - the train is reversing
2423  * - is entering a station with an order to stop there and its speed is equal to maximum station entering speed
2424  */
2425  if (HasBit(t->flags, VRF_REVERSING) ||
2427  t->cur_speed >= t->Train::GetCurrentMaxSpeed())) {
2428  return;
2429  }
2430 
2431  max_speed = min(max_speed, t->gcache.cached_max_track_speed);
2432  max_speed = min(max_speed, this->current_order.GetMaxSpeed());
2433  }
2434  if (this->type == VEH_ROAD || this->type == VEH_SHIP) max_speed = min(max_speed, this->current_order.GetMaxSpeed() * 2);
2435 
2436  const Vehicle *v = this;
2437 
2438  do {
2439  bool advanced = HasBit(v->vcache.cached_vis_effect, VE_ADVANCED_EFFECT);
2440  int effect_offset = GB(v->vcache.cached_vis_effect, VE_OFFSET_START, VE_OFFSET_COUNT) - VE_OFFSET_CENTRE;
2441  VisualEffectSpawnModel effect_model = VESM_NONE;
2442  if (advanced) {
2443  effect_offset = VE_OFFSET_CENTRE;
2444  effect_model = (VisualEffectSpawnModel)GB(v->vcache.cached_vis_effect, 0, VE_ADVANCED_EFFECT);
2445  if (effect_model >= VESM_END) effect_model = VESM_NONE; // unknown spawning model
2446  } else {
2447  effect_model = (VisualEffectSpawnModel)GB(v->vcache.cached_vis_effect, VE_TYPE_START, VE_TYPE_COUNT);
2448  assert(effect_model != (VisualEffectSpawnModel)VE_TYPE_DEFAULT); // should have been resolved by UpdateVisualEffect
2449  assert_compile((uint)VESM_STEAM == (uint)VE_TYPE_STEAM);
2450  assert_compile((uint)VESM_DIESEL == (uint)VE_TYPE_DIESEL);
2451  assert_compile((uint)VESM_ELECTRIC == (uint)VE_TYPE_ELECTRIC);
2452  }
2453 
2454  /* Show no smoke when:
2455  * - Smoke has been disabled for this vehicle
2456  * - The vehicle is not visible
2457  * - The vehicle is under a bridge
2458  * - The vehicle is on a depot tile
2459  * - The vehicle is on a tunnel tile
2460  * - The vehicle is a train engine that is currently unpowered */
2461  if (effect_model == VESM_NONE ||
2462  v->vehstatus & VS_HIDDEN ||
2463  IsBridgeAbove(v->tile) ||
2464  IsDepotTile(v->tile) ||
2465  IsTunnelTile(v->tile) ||
2466  (v->type == VEH_TRAIN &&
2467  !HasPowerOnRail(Train::From(v)->railtype, GetTileRailType(v->tile)))) {
2468  continue;
2469  }
2470 
2471  EffectVehicleType evt = EV_END;
2472  switch (effect_model) {
2473  case VESM_STEAM:
2474  /* Steam smoke - amount is gradually falling until vehicle reaches its maximum speed, after that it's normal.
2475  * Details: while vehicle's current speed is gradually increasing, steam plumes' density decreases by one third each
2476  * third of its maximum speed spectrum. Steam emission finally normalises at very close to vehicle's maximum speed.
2477  * REGULATION:
2478  * - instead of 1, 4 / 2^smoke_amount (max. 2) is used to provide sufficient regulation to steam puffs' amount. */
2479  if (GB(v->tick_counter, 0, ((4 >> _settings_game.vehicle.smoke_amount) + ((this->cur_speed * 3) / max_speed))) == 0) {
2480  evt = EV_STEAM_SMOKE;
2481  }
2482  break;
2483 
2484  case VESM_DIESEL: {
2485  /* Diesel smoke - thicker when vehicle is starting, gradually subsiding till it reaches its maximum speed
2486  * when smoke emission stops.
2487  * Details: Vehicle's (max.) speed spectrum is divided into 32 parts. When max. speed is reached, chance for smoke
2488  * emission erodes by 32 (1/4). For trains, power and weight come in handy too to either increase smoke emission in
2489  * 6 steps (1000HP each) if the power is low or decrease smoke emission in 6 steps (512 tonnes each) if the train
2490  * isn't overweight. Power and weight contributions are expressed in a way that neither extreme power, nor
2491  * extreme weight can ruin the balance (e.g. FreightWagonMultiplier) in the formula. When the vehicle reaches
2492  * maximum speed no diesel_smoke is emitted.
2493  * REGULATION:
2494  * - up to which speed a diesel vehicle is emitting smoke (with reduced/small setting only until 1/2 of max_speed),
2495  * - in Chance16 - the last value is 512 / 2^smoke_amount (max. smoke when 128 = smoke_amount of 2). */
2496  int power_weight_effect = 0;
2497  if (v->type == VEH_TRAIN) {
2498  power_weight_effect = (32 >> (Train::From(this)->gcache.cached_power >> 10)) - (32 >> (Train::From(this)->gcache.cached_weight >> 9));
2499  }
2500  if (this->cur_speed < (max_speed >> (2 >> _settings_game.vehicle.smoke_amount)) &&
2501  Chance16((64 - ((this->cur_speed << 5) / max_speed) + power_weight_effect), (512 >> _settings_game.vehicle.smoke_amount))) {
2502  evt = EV_DIESEL_SMOKE;
2503  }
2504  break;
2505  }
2506 
2507  case VESM_ELECTRIC:
2508  /* Electric train's spark - more often occurs when train is departing (more load)
2509  * Details: Electric locomotives are usually at least twice as powerful as their diesel counterparts, so spark
2510  * emissions are kept simple. Only when starting, creating huge force are sparks more likely to happen, but when
2511  * reaching its max. speed, quarter by quarter of it, chance decreases until the usual 2,22% at train's top speed.
2512  * REGULATION:
2513  * - in Chance16 the last value is 360 / 2^smoke_amount (max. sparks when 90 = smoke_amount of 2). */
2514  if (GB(v->tick_counter, 0, 2) == 0 &&
2515  Chance16((6 - ((this->cur_speed << 2) / max_speed)), (360 >> _settings_game.vehicle.smoke_amount))) {
2516  evt = EV_ELECTRIC_SPARK;
2517  }
2518  break;
2519 
2520  default:
2521  NOT_REACHED();
2522  }
2523 
2524  if (evt != EV_END && advanced) {
2525  sound = true;
2527  } else if (evt != EV_END) {
2528  sound = true;
2529 
2530  /* The effect offset is relative to a point 4 units behind the vehicle's
2531  * front (which is the center of an 8/8 vehicle). Shorter vehicles need a
2532  * correction factor. */
2533  if (v->type == VEH_TRAIN) effect_offset += (VEHICLE_LENGTH - Train::From(v)->gcache.cached_veh_length) / 2;
2534 
2535  int x = _vehicle_smoke_pos[v->direction] * effect_offset;
2536  int y = _vehicle_smoke_pos[(v->direction + 2) % 8] * effect_offset;
2537 
2538  if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_REVERSE_DIRECTION)) {
2539  x = -x;
2540  y = -y;
2541  }
2542 
2543  CreateEffectVehicleRel(v, x, y, 10, evt);
2544  }
2545  } while ((v = v->Next()) != NULL);
2546 
2547  if (sound) PlayVehicleSound(this, VSE_VISUAL_EFFECT);
2548 }
2549 
2555 {
2556  assert(this != next);
2557 
2558  if (this->next != NULL) {
2559  /* We had an old next vehicle. Update the first and previous pointers */
2560  for (Vehicle *v = this->next; v != NULL; v = v->Next()) {
2561  v->first = this->next;
2562  }
2563  this->next->previous = NULL;
2564  }
2565 
2566  this->next = next;
2567 
2568  if (this->next != NULL) {
2569  /* A new next vehicle. Update the first and previous pointers */
2570  if (this->next->previous != NULL) this->next->previous->next = NULL;
2571  this->next->previous = this;
2572  for (Vehicle *v = this->next; v != NULL; v = v->Next()) {
2573  v->first = this->first;
2574  }
2575  }
2576 }
2577 
2583 void Vehicle::AddToShared(Vehicle *shared_chain)
2584 {
2585  assert(this->previous_shared == NULL && this->next_shared == NULL);
2586 
2587  if (shared_chain->orders.list == NULL) {
2588  assert(shared_chain->previous_shared == NULL);
2589  assert(shared_chain->next_shared == NULL);
2590  this->orders.list = shared_chain->orders.list = new OrderList(NULL, shared_chain);
2591  }
2592 
2593  this->next_shared = shared_chain->next_shared;
2594  this->previous_shared = shared_chain;
2595 
2596  shared_chain->next_shared = this;
2597 
2598  if (this->next_shared != NULL) this->next_shared->previous_shared = this;
2599 
2600  shared_chain->orders.list->AddVehicle(this);
2601 }
2602 
2607 {
2608  /* Remember if we were first and the old window number before RemoveVehicle()
2609  * as this changes first if needed. */
2610  bool were_first = (this->FirstShared() == this);
2611  VehicleListIdentifier vli(VL_SHARED_ORDERS, this->type, this->owner, this->FirstShared()->index);
2612 
2613  this->orders.list->RemoveVehicle(this);
2614 
2615  if (!were_first) {
2616  /* We are not the first shared one, so only relink our previous one. */
2617  this->previous_shared->next_shared = this->NextShared();
2618  }
2619 
2620  if (this->next_shared != NULL) this->next_shared->previous_shared = this->previous_shared;
2621 
2622 
2623  if (this->orders.list->GetNumVehicles() == 1) {
2624  /* When there is only one vehicle, remove the shared order list window. */
2626  InvalidateVehicleOrder(this->FirstShared(), 0);
2627  } else if (were_first) {
2628  /* If we were the first one, update to the new first one.
2629  * Note: FirstShared() is already the new first */
2630  InvalidateWindowData(GetWindowClassForVehicleType(this->type), vli.Pack(), this->FirstShared()->index | (1U << 31));
2631  }
2632 
2633  this->next_shared = NULL;
2634  this->previous_shared = NULL;
2635 }
2636 
2637 void VehiclesYearlyLoop()
2638 {
2639  Vehicle *v;
2640  FOR_ALL_VEHICLES(v) {
2641  if (v->IsPrimaryVehicle()) {
2642  /* show warning if vehicle is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */
2643  Money profit = v->GetDisplayProfitThisYear();
2644  if (v->age >= 730 && profit < 0) {
2646  SetDParam(0, v->index);
2647  SetDParam(1, profit);
2648  AddVehicleAdviceNewsItem(STR_NEWS_VEHICLE_IS_UNPROFITABLE, v->index);
2649  }
2650  AI::NewEvent(v->owner, new ScriptEventVehicleUnprofitable(v->index));
2651  }
2652 
2654  v->profit_this_year = 0;
2656  }
2657  }
2663 }
2664 
2665 
2675 bool CanVehicleUseStation(EngineID engine_type, const Station *st)
2676 {
2677  const Engine *e = Engine::GetIfValid(engine_type);
2678  assert(e != NULL);
2679 
2680  switch (e->type) {
2681  case VEH_TRAIN:
2682  return (st->facilities & FACIL_TRAIN) != 0;
2683 
2684  case VEH_ROAD:
2685  /* For road vehicles we need the vehicle to know whether it can actually
2686  * use the station, but if it doesn't have facilities for RVs it is
2687  * certainly not possible that the station can be used. */
2688  return (st->facilities & (FACIL_BUS_STOP | FACIL_TRUCK_STOP)) != 0;
2689 
2690  case VEH_SHIP:
2691  return (st->facilities & FACIL_DOCK) != 0;
2692 
2693  case VEH_AIRCRAFT:
2694  return (st->facilities & FACIL_AIRPORT) != 0 &&
2696 
2697  default:
2698  return false;
2699  }
2700 }
2701 
2708 bool CanVehicleUseStation(const Vehicle *v, const Station *st)
2709 {
2710  if (v->type == VEH_ROAD) return st->GetPrimaryRoadStop(RoadVehicle::From(v)) != NULL;
2711 
2712  return CanVehicleUseStation(v->engine_type, st);
2713 }
2714 
2721 {
2722  assert(this->IsGroundVehicle());
2723  if (this->type == VEH_TRAIN) {
2724  return &Train::From(this)->gcache;
2725  } else {
2726  return &RoadVehicle::From(this)->gcache;
2727  }
2728 }
2729 
2736 {
2737  assert(this->IsGroundVehicle());
2738  if (this->type == VEH_TRAIN) {
2739  return &Train::From(this)->gcache;
2740  } else {
2741  return &RoadVehicle::From(this)->gcache;
2742  }
2743 }
2744 
2751 {
2752  assert(this->IsGroundVehicle());
2753  if (this->type == VEH_TRAIN) {
2754  return Train::From(this)->gv_flags;
2755  } else {
2756  return RoadVehicle::From(this)->gv_flags;
2757  }
2758 }
2759 
2765 const uint16 &Vehicle::GetGroundVehicleFlags() const
2766 {
2767  assert(this->IsGroundVehicle());
2768  if (this->type == VEH_TRAIN) {
2769  return Train::From(this)->gv_flags;
2770  } else {
2771  return RoadVehicle::From(this)->gv_flags;
2772  }
2773 }
2774 
2783 void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8 num_vehicles)
2784 {
2785  if (v->type == VEH_TRAIN) {
2786  Train *u = Train::From(v);
2787  /* Only include whole vehicles, so start with the first articulated part */
2788  u = u->GetFirstEnginePart();
2789 
2790  /* Include num_vehicles vehicles, not counting articulated parts */
2791  for (; u != NULL && num_vehicles > 0; num_vehicles--) {
2792  do {
2793  /* Include current vehicle in the selection. */
2794  set.Include(u->index);
2795 
2796  /* If the vehicle is multiheaded, add the other part too. */
2797  if (u->IsMultiheaded()) set.Include(u->other_multiheaded_part->index);
2798 
2799  u = u->Next();
2800  } while (u != NULL && u->IsArticulatedPart());
2801  }
2802  }
2803 }