vehicle.cpp

Go to the documentation of this file.
00001 /* $Id: vehicle.cpp 14933 2009-01-09 14:59:02Z rubidium $ */
00002 
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "road_map.h"
00008 #include "roadveh.h"
00009 #include "ship.h"
00010 #include "spritecache.h"
00011 #include "tile_cmd.h"
00012 #include "landscape.h"
00013 #include "timetable.h"
00014 #include "viewport_func.h"
00015 #include "gfx_func.h"
00016 #include "news_func.h"
00017 #include "command_func.h"
00018 #include "saveload/saveload.h"
00019 #include "company_func.h"
00020 #include "debug.h"
00021 #include "vehicle_gui.h"
00022 #include "rail_type.h"
00023 #include "train.h"
00024 #include "aircraft.h"
00025 #include "industry_map.h"
00026 #include "station_map.h"
00027 #include "water_map.h"
00028 #include "yapf/yapf.h"
00029 #include "newgrf_callbacks.h"
00030 #include "newgrf_engine.h"
00031 #include "newgrf_sound.h"
00032 #include "newgrf_station.h"
00033 #include "newgrf_text.h"
00034 #include "group.h"
00035 #include "group_gui.h"
00036 #include "order_func.h"
00037 #include "strings_func.h"
00038 #include "zoom_func.h"
00039 #include "functions.h"
00040 #include "date_func.h"
00041 #include "window_func.h"
00042 #include "vehicle_func.h"
00043 #include "signal_func.h"
00044 #include "sound_func.h"
00045 #include "variables.h"
00046 #include "autoreplace_func.h"
00047 #include "autoreplace_gui.h"
00048 #include "string_func.h"
00049 #include "settings_type.h"
00050 #include "oldpool_func.h"
00051 #include "depot_map.h"
00052 #include "animated_tile_func.h"
00053 #include "effectvehicle_base.h"
00054 #include "core/alloc_func.hpp"
00055 #include "core/smallmap_type.hpp"
00056 #include "vehiclelist.h"
00057 #include "core/mem_func.hpp"
00058 #include "depot_func.h"
00059 
00060 #include "table/sprites.h"
00061 #include "table/strings.h"
00062 
00063 #define GEN_HASH(x, y) ((GB((y), 6, 6) << 6) + GB((x), 7, 6))
00064 
00065 VehicleID _vehicle_id_ctr_day;
00066 const Vehicle *_place_clicked_vehicle;
00067 VehicleID _new_vehicle_id;
00068 uint16 _returned_refit_capacity;
00069 
00070 
00071 /* Tables used in vehicle.h to find the right command for a certain vehicle type */
00072 const uint32 _veh_build_proc_table[] = {
00073   CMD_BUILD_RAIL_VEHICLE,
00074   CMD_BUILD_ROAD_VEH,
00075   CMD_BUILD_SHIP,
00076   CMD_BUILD_AIRCRAFT,
00077 };
00078 const uint32 _veh_sell_proc_table[] = {
00079   CMD_SELL_RAIL_WAGON,
00080   CMD_SELL_ROAD_VEH,
00081   CMD_SELL_SHIP,
00082   CMD_SELL_AIRCRAFT,
00083 };
00084 
00085 const uint32 _veh_refit_proc_table[] = {
00086   CMD_REFIT_RAIL_VEHICLE,
00087   CMD_REFIT_ROAD_VEH,
00088   CMD_REFIT_SHIP,
00089   CMD_REFIT_AIRCRAFT,
00090 };
00091 
00092 const uint32 _send_to_depot_proc_table[] = {
00093   CMD_SEND_TRAIN_TO_DEPOT,
00094   CMD_SEND_ROADVEH_TO_DEPOT,
00095   CMD_SEND_SHIP_TO_DEPOT,
00096   CMD_SEND_AIRCRAFT_TO_HANGAR,
00097 };
00098 
00099 
00100 /* Initialize the vehicle-pool */
00101 DEFINE_OLD_POOL_GENERIC(Vehicle, Vehicle)
00102 
00103 
00107 bool Vehicle::NeedsAutorenewing(const Company *c) const
00108 {
00109   /* We can always generate the Company pointer when we have the vehicle.
00110    * However this takes time and since the Company pointer is often present
00111    * when this function is called then it's faster to pass the pointer as an
00112    * argument rather than finding it again. */
00113   assert(c == GetCompany(this->owner));
00114 
00115   if (!c->engine_renew) return false;
00116   if (this->age - this->max_age < (c->engine_renew_months * 30)) return false;
00117   if (this->age == 0) return false; // rail cars don't age and lacks a max age
00118 
00119   return true;
00120 }
00121 
00122 void VehicleServiceInDepot(Vehicle *v)
00123 {
00124   v->date_of_last_service = _date;
00125   v->breakdowns_since_last_service = 0;
00126   v->reliability = GetEngine(v->engine_type)->reliability;
00127   InvalidateWindow(WC_VEHICLE_DETAILS, v->index); // ensure that last service date and reliability are updated
00128 }
00129 
00130 bool Vehicle::NeedsServicing() const
00131 {
00132   if (this->vehstatus & (VS_STOPPED | VS_CRASHED)) return false;
00133 
00134   if (_settings_game.order.no_servicing_if_no_breakdowns && _settings_game.difficulty.vehicle_breakdowns == 0) {
00135     /* Vehicles set for autoreplacing needs to go to a depot even if breakdowns are turned off.
00136      * Note: If servicing is enabled, we postpone replacement till next service. */
00137     return EngineHasReplacementForCompany(GetCompany(this->owner), this->engine_type, this->group_id);
00138   }
00139 
00140   return _settings_game.vehicle.servint_ispercent ?
00141     (this->reliability < GetEngine(this->engine_type)->reliability * (100 - this->service_interval) / 100) :
00142     (this->date_of_last_service + this->service_interval < _date);
00143 }
00144 
00145 bool Vehicle::NeedsAutomaticServicing() const
00146 {
00147   if (_settings_game.order.gotodepot && VehicleHasDepotOrders(this)) return false;
00148   if (this->current_order.IsType(OT_LOADING))            return false;
00149   if (this->current_order.IsType(OT_GOTO_DEPOT) && this->current_order.GetDepotOrderType() != ODTFB_SERVICE) return false;
00150   return NeedsServicing();
00151 }
00152 
00153 StringID VehicleInTheWayErrMsg(const Vehicle* v)
00154 {
00155   switch (v->type) {
00156     case VEH_TRAIN:    return STR_8803_TRAIN_IN_THE_WAY;
00157     case VEH_ROAD:     return STR_9000_ROAD_VEHICLE_IN_THE_WAY;
00158     case VEH_AIRCRAFT: return STR_A015_AIRCRAFT_IN_THE_WAY;
00159     default:           return STR_980E_SHIP_IN_THE_WAY;
00160   }
00161 }
00162 
00163 static Vehicle *EnsureNoVehicleProcZ(Vehicle *v, void *data)
00164 {
00165   byte z = *(byte*)data;
00166 
00167   if (v->type == VEH_DISASTER || (v->type == VEH_AIRCRAFT && v->subtype == AIR_SHADOW)) return NULL;
00168   if (v->z_pos > z) return NULL;
00169 
00170   _error_message = VehicleInTheWayErrMsg(v);
00171   return v;
00172 }
00173 
00174 bool EnsureNoVehicleOnGround(TileIndex tile)
00175 {
00176   byte z = GetTileMaxZ(tile);
00177   return !HasVehicleOnPos(tile, &z, &EnsureNoVehicleProcZ);
00178 }
00179 
00181 static Vehicle *GetVehicleTunnelBridgeProc(Vehicle *v, void *data)
00182 {
00183   if (v->type != VEH_TRAIN && v->type != VEH_ROAD && v->type != VEH_SHIP) return NULL;
00184   if (v == (const Vehicle *)data) return NULL;
00185 
00186   _error_message = VehicleInTheWayErrMsg(v);
00187   return v;
00188 }
00189 
00197 bool HasVehicleOnTunnelBridge(TileIndex tile, TileIndex endtile, const Vehicle *ignore)
00198 {
00199   return HasVehicleOnPos(tile, (void *)ignore, &GetVehicleTunnelBridgeProc) ||
00200       HasVehicleOnPos(endtile, (void *)ignore, &GetVehicleTunnelBridgeProc);
00201 }
00202 
00203 
00204 static void UpdateVehiclePosHash(Vehicle *v, int x, int y);
00205 
00206 void VehiclePositionChanged(Vehicle *v)
00207 {
00208   int img = v->cur_image;
00209   Point pt = RemapCoords(v->x_pos + v->x_offs, v->y_pos + v->y_offs, v->z_pos);
00210   const Sprite *spr = GetSprite(img, ST_NORMAL);
00211 
00212   pt.x += spr->x_offs;
00213   pt.y += spr->y_offs;
00214 
00215   UpdateVehiclePosHash(v, pt.x, pt.y);
00216 
00217   v->left_coord = pt.x;
00218   v->top_coord = pt.y;
00219   v->right_coord = pt.x + spr->width + 2;
00220   v->bottom_coord = pt.y + spr->height + 2;
00221 }
00222 
00223 Vehicle::Vehicle()
00224 {
00225   this->type               = VEH_INVALID;
00226   this->left_coord         = INVALID_COORD;
00227   this->group_id           = DEFAULT_GROUP;
00228   this->fill_percent_te_id = INVALID_TE_ID;
00229   this->first              = this;
00230   this->colormap           = PAL_NONE;
00231 }
00232 
00237 byte VehicleRandomBits()
00238 {
00239   return GB(Random(), 0, 8);
00240 }
00241 
00242 
00243 /* static */ bool Vehicle::AllocateList(Vehicle **vl, int num)
00244 {
00245   if (!Vehicle::CanAllocateItem(num)) return false;
00246   if (vl == NULL) return true;
00247 
00248   uint counter = _Vehicle_pool.first_free_index;
00249 
00250   for (int i = 0; i != num; i++) {
00251     vl[i] = new (AllocateRaw(counter)) InvalidVehicle();
00252     counter++;
00253   }
00254 
00255   return true;
00256 }
00257 
00258 /* Size of the hash, 6 = 64 x 64, 7 = 128 x 128. Larger sizes will (in theory) reduce hash
00259  * lookup times at the expense of memory usage. */
00260 const int HASH_BITS = 7;
00261 const int HASH_SIZE = 1 << HASH_BITS;
00262 const int HASH_MASK = HASH_SIZE - 1;
00263 const int TOTAL_HASH_SIZE = 1 << (HASH_BITS * 2);
00264 const int TOTAL_HASH_MASK = TOTAL_HASH_SIZE - 1;
00265 
00266 /* Resolution of the hash, 0 = 1*1 tile, 1 = 2*2 tiles, 2 = 4*4 tiles, etc.
00267  * Profiling results show that 0 is fastest. */
00268 const int HASH_RES = 0;
00269 
00270 static Vehicle *_new_vehicle_position_hash[TOTAL_HASH_SIZE];
00271 
00272 static Vehicle *VehicleFromHash(int xl, int yl, int xu, int yu, void *data, VehicleFromPosProc *proc, bool find_first)
00273 {
00274   for (int y = yl; ; y = (y + (1 << HASH_BITS)) & (HASH_MASK << HASH_BITS)) {
00275     for (int x = xl; ; x = (x + 1) & HASH_MASK) {
00276       Vehicle *v = _new_vehicle_position_hash[(x + y) & TOTAL_HASH_MASK];
00277       for (; v != NULL; v = v->next_new_hash) {
00278         Vehicle *a = proc(v, data);
00279         if (find_first && a != NULL) return a;
00280       }
00281       if (x == xu) break;
00282     }
00283     if (y == yu) break;
00284   }
00285 
00286   return NULL;
00287 }
00288 
00289 
00301 static Vehicle *VehicleFromPosXY(int x, int y, void *data, VehicleFromPosProc *proc, bool find_first)
00302 {
00303   const int COLL_DIST = 6;
00304 
00305   /* Hash area to scan is from xl,yl to xu,yu */
00306   int xl = GB((x - COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS);
00307   int xu = GB((x + COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS);
00308   int yl = GB((y - COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS) << HASH_BITS;
00309   int yu = GB((y + COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS) << HASH_BITS;
00310 
00311   return VehicleFromHash(xl, yl, xu, yu, data, proc, find_first);
00312 }
00313 
00328 void FindVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
00329 {
00330   VehicleFromPosXY(x, y, data, proc, false);
00331 }
00332 
00344 bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
00345 {
00346   return VehicleFromPosXY(x, y, data, proc, true) != NULL;
00347 }
00348 
00359 static Vehicle *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc, bool find_first)
00360 {
00361   int x = GB(TileX(tile), HASH_RES, HASH_BITS);
00362   int y = GB(TileY(tile), HASH_RES, HASH_BITS) << HASH_BITS;
00363 
00364   Vehicle *v = _new_vehicle_position_hash[(x + y) & TOTAL_HASH_MASK];
00365   for (; v != NULL; v = v->next_new_hash) {
00366     if (v->tile != tile) continue;
00367 
00368     Vehicle *a = proc(v, data);
00369     if (find_first && a != NULL) return a;
00370   }
00371 
00372   return NULL;
00373 }
00374 
00388 void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
00389 {
00390   VehicleFromPos(tile, data, proc, false);
00391 }
00392 
00403 bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
00404 {
00405   return VehicleFromPos(tile, data, proc, true) != NULL;
00406 }
00407 
00408 
00409 static void UpdateNewVehiclePosHash(Vehicle *v, bool remove)
00410 {
00411   Vehicle **old_hash = v->old_new_hash;
00412   Vehicle **new_hash;
00413 
00414   if (remove) {
00415     new_hash = NULL;
00416   } else {
00417     int x = GB(TileX(v->tile), HASH_RES, HASH_BITS);
00418     int y = GB(TileY(v->tile), HASH_RES, HASH_BITS) << HASH_BITS;
00419     new_hash = &_new_vehicle_position_hash[(x + y) & TOTAL_HASH_MASK];
00420   }
00421 
00422   if (old_hash == new_hash) return;
00423 
00424   /* Remove from the old position in the hash table */
00425   if (old_hash != NULL) {
00426     Vehicle *last = NULL;
00427     Vehicle *u = *old_hash;
00428     while (u != v) {
00429       last = u;
00430       u = u->next_new_hash;
00431       assert(u != NULL);
00432     }
00433 
00434     if (last == NULL) {
00435       *old_hash = v->next_new_hash;
00436     } else {
00437       last->next_new_hash = v->next_new_hash;
00438     }
00439   }
00440 
00441   /* Insert vehicle at beginning of the new position in the hash table */
00442   if (new_hash != NULL) {
00443     v->next_new_hash = *new_hash;
00444     *new_hash = v;
00445     assert(v != v->next_new_hash);
00446   }
00447 
00448   /* Remember current hash position */
00449   v->old_new_hash = new_hash;
00450 }
00451 
00452 static Vehicle *_vehicle_position_hash[0x1000];
00453 
00454 static void UpdateVehiclePosHash(Vehicle *v, int x, int y)
00455 {
00456   UpdateNewVehiclePosHash(v, x == INVALID_COORD);
00457 
00458   Vehicle **old_hash, **new_hash;
00459   int old_x = v->left_coord;
00460   int old_y = v->top_coord;
00461 
00462   new_hash = (x == INVALID_COORD) ? NULL : &_vehicle_position_hash[GEN_HASH(x, y)];
00463   old_hash = (old_x == INVALID_COORD) ? NULL : &_vehicle_position_hash[GEN_HASH(old_x, old_y)];
00464 
00465   if (old_hash == new_hash) return;
00466 
00467   /* remove from hash table? */
00468   if (old_hash != NULL) {
00469     Vehicle *last = NULL;
00470     Vehicle *u = *old_hash;
00471     while (u != v) {
00472       last = u;
00473       u = u->next_hash;
00474       assert(u != NULL);
00475     }
00476 
00477     if (last == NULL) {
00478       *old_hash = v->next_hash;
00479     } else {
00480       last->next_hash = v->next_hash;
00481     }
00482   }
00483 
00484   /* insert into hash table? */
00485   if (new_hash != NULL) {
00486     v->next_hash = *new_hash;
00487     *new_hash = v;
00488   }
00489 }
00490 
00491 void ResetVehiclePosHash()
00492 {
00493   Vehicle *v;
00494   FOR_ALL_VEHICLES(v) { v->old_new_hash = NULL; }
00495   memset(_vehicle_position_hash, 0, sizeof(_vehicle_position_hash));
00496   memset(_new_vehicle_position_hash, 0, sizeof(_new_vehicle_position_hash));
00497 }
00498 
00499 void ResetVehicleColorMap()
00500 {
00501   Vehicle *v;
00502   FOR_ALL_VEHICLES(v) { v->colormap = PAL_NONE; }
00503 }
00504 
00509 typedef SmallMap<Vehicle *, bool, 4> AutoreplaceMap;
00510 static AutoreplaceMap _vehicles_to_autoreplace;
00511 
00512 void InitializeVehicles()
00513 {
00514   _Vehicle_pool.CleanPool();
00515   _Vehicle_pool.AddBlockToPool();
00516 
00517   _vehicles_to_autoreplace.Reset();
00518   ResetVehiclePosHash();
00519 }
00520 
00521 Vehicle *GetLastVehicleInChain(Vehicle *v)
00522 {
00523   while (v->Next() != NULL) v = v->Next();
00524   return v;
00525 }
00526 
00527 const Vehicle *GetLastVehicleInChain(const Vehicle *v)
00528 {
00529   while (v->Next() != NULL) v = v->Next();
00530   return v;
00531 }
00532 
00533 uint CountVehiclesInChain(const Vehicle* v)
00534 {
00535   uint count = 0;
00536   do count++; while ((v = v->Next()) != NULL);
00537   return count;
00538 }
00539 
00544 bool IsEngineCountable(const Vehicle *v)
00545 {
00546   switch (v->type) {
00547     case VEH_AIRCRAFT: return IsNormalAircraft(v); // don't count plane shadows and helicopter rotors
00548     case VEH_TRAIN:
00549       return !IsArticulatedPart(v) && // tenders and other articulated parts
00550       !IsRearDualheaded(v); // rear parts of multiheaded engines
00551     case VEH_ROAD: return IsRoadVehFront(v);
00552     case VEH_SHIP: return true;
00553     default: return false; // Only count company buildable vehicles
00554   }
00555 }
00556 
00557 void Vehicle::PreDestructor()
00558 {
00559   if (CleaningPool()) return;
00560 
00561   if (IsValidStationID(this->last_station_visited)) {
00562     GetStation(this->last_station_visited)->loading_vehicles.remove(this);
00563 
00564     HideFillingPercent(&this->fill_percent_te_id);
00565   }
00566 
00567   if (IsEngineCountable(this)) {
00568     GetCompany(this->owner)->num_engines[this->engine_type]--;
00569     if (this->owner == _local_company) InvalidateAutoreplaceWindow(this->engine_type, this->group_id);
00570 
00571     DeleteGroupHighlightOfVehicle(this);
00572     if (IsValidGroupID(this->group_id)) GetGroup(this->group_id)->num_engines[this->engine_type]--;
00573     if (this->IsPrimaryVehicle()) DecreaseGroupNumVehicle(this->group_id);
00574   }
00575 
00576   if (this->type == VEH_ROAD) ClearSlot(this);
00577   if (this->type == VEH_AIRCRAFT && this->IsPrimaryVehicle()) {
00578     Station *st = GetTargetAirportIfValid(this);
00579     if (st != NULL) {
00580       const AirportFTA *layout = st->Airport()->layout;
00581       CLRBITS(st->airport_flags, layout[this->u.air.previous_pos].block | layout[this->u.air.pos].block);
00582     }
00583   }
00584 
00585   if (this->type != VEH_TRAIN || (this->type == VEH_TRAIN && (IsFrontEngine(this) || IsFreeWagon(this)))) {
00586     InvalidateWindowData(WC_VEHICLE_DEPOT, this->tile);
00587   }
00588 
00589   if (this->IsPrimaryVehicle()) {
00590     DeleteWindowById(WC_VEHICLE_VIEW, this->index);
00591     DeleteWindowById(WC_VEHICLE_ORDERS, this->index);
00592     DeleteWindowById(WC_VEHICLE_REFIT, this->index);
00593     DeleteWindowById(WC_VEHICLE_DETAILS, this->index);
00594     DeleteWindowById(WC_VEHICLE_TIMETABLE, this->index);
00595     InvalidateWindow(WC_COMPANY, this->owner);
00596   }
00597   InvalidateWindowClassesData(GetWindowClassForVehicleType(this->type), 0);
00598 
00599   this->cargo.Truncate(0);
00600   DeleteVehicleOrders(this);
00601   DeleteDepotHighlightOfVehicle(this);
00602 
00603   extern void StopGlobalFollowVehicle(const Vehicle *v);
00604   StopGlobalFollowVehicle(this);
00605 }
00606 
00607 Vehicle::~Vehicle()
00608 {
00609   free(this->name);
00610 
00611   if (CleaningPool()) return;
00612 
00613   /* sometimes, eg. for disaster vehicles, when company bankrupts, when removing crashed/flooded vehicles,
00614    * it may happen that vehicle chain is deleted when visible */
00615   if (!(this->vehstatus & VS_HIDDEN)) MarkSingleVehicleDirty(this);
00616 
00617   Vehicle *v = this->Next();
00618   this->SetNext(NULL);
00619 
00620   delete v;
00621 
00622   UpdateVehiclePosHash(this, INVALID_COORD, 0);
00623   this->next_hash = NULL;
00624   this->next_new_hash = NULL;
00625 
00626   DeleteVehicleNews(this->index, INVALID_STRING_ID);
00627 
00628   new (this) InvalidVehicle();
00629 }
00630 
00634 void VehicleEnteredDepotThisTick(Vehicle *v)
00635 {
00636   /* Vehicle should stop in the depot if it was in 'stopping' state or
00637    * when the vehicle is ordered to halt in the depot. */
00638   _vehicles_to_autoreplace[v] = !(v->vehstatus & VS_STOPPED) &&
00639       (!v->current_order.IsType(OT_GOTO_DEPOT) ||
00640        !(v->current_order.GetDepotActionType() & ODATFB_HALT));
00641 
00642   /* We ALWAYS set the stopped state. Even when the vehicle does not plan on
00643    * stopping in the depot, so we stop it to ensure that it will not reserve
00644    * the path out of the depot before we might autoreplace it to a different
00645    * engine. The new engine would not own the reserved path we store that we
00646    * stopped the vehicle, so autoreplace can start it again */
00647   v->vehstatus |= VS_STOPPED;
00648 }
00649 
00650 void CallVehicleTicks()
00651 {
00652   _vehicles_to_autoreplace.Clear();
00653 
00654   Station *st;
00655   FOR_ALL_STATIONS(st) LoadUnloadStation(st);
00656 
00657   Vehicle *v;
00658   FOR_ALL_VEHICLES(v) {
00659     v->Tick();
00660 
00661     switch (v->type) {
00662       default: break;
00663 
00664       case VEH_TRAIN:
00665       case VEH_ROAD:
00666       case VEH_AIRCRAFT:
00667       case VEH_SHIP:
00668         if (v->type == VEH_TRAIN && IsTrainWagon(v)) continue;
00669         if (v->type == VEH_AIRCRAFT && v->subtype != AIR_HELICOPTER) continue;
00670         if (v->type == VEH_ROAD && !IsRoadVehFront(v)) continue;
00671 
00672         v->motion_counter += (v->direction & 1) ? (v->cur_speed * 3) / 4 : v->cur_speed;
00673         /* Play a running sound if the motion counter passes 256 (Do we not skip sounds?) */
00674         if (GB(v->motion_counter, 0, 8) < v->cur_speed) PlayVehicleSound(v, VSE_RUNNING);
00675 
00676         /* Play an alterate running sound every 16 ticks */
00677         if (GB(v->tick_counter, 0, 4) == 0) PlayVehicleSound(v, v->cur_speed > 0 ? VSE_RUNNING_16 : VSE_STOPPED_16);
00678     }
00679   }
00680 
00681   for (AutoreplaceMap::iterator it = _vehicles_to_autoreplace.Begin(); it != _vehicles_to_autoreplace.End(); it++) {
00682     v = it->first;
00683     /* Autoreplace needs the current company set as the vehicle owner */
00684     _current_company = v->owner;
00685 
00686     /* Start vehicle if we stopped them in VehicleEnteredDepotThisTick()
00687      * We need to stop them between VehicleEnteredDepotThisTick() and here or we risk that
00688      * they are already leaving the depot again before being replaced. */
00689     if (it->second) v->vehstatus &= ~VS_STOPPED;
00690 
00691     /* Store the position of the effect as the vehicle pointer will become invalid later */
00692     int x = v->x_pos;
00693     int y = v->y_pos;
00694     int z = v->z_pos;
00695 
00696     const Company *c = GetCompany(_current_company);
00697     SubtractMoneyFromCompany(CommandCost(EXPENSES_NEW_VEHICLES, (Money)c->engine_renew_money));
00698     CommandCost res = DoCommand(0, v->index, 0, DC_EXEC, CMD_AUTOREPLACE_VEHICLE);
00699     SubtractMoneyFromCompany(CommandCost(EXPENSES_NEW_VEHICLES, -(Money)c->engine_renew_money));
00700 
00701     if (!IsLocalCompany()) continue;
00702 
00703     if (res.Succeeded()) {
00704       ShowCostOrIncomeAnimation(x, y, z, res.GetCost());
00705       continue;
00706     }
00707 
00708     StringID error_message = res.GetErrorMessage();
00709     if (error_message == STR_AUTOREPLACE_NOTHING_TO_DO || error_message == INVALID_STRING_ID) continue;
00710 
00711     if (error_message == STR_0003_NOT_ENOUGH_CASH_REQUIRES) error_message = STR_AUTOREPLACE_MONEY_LIMIT;
00712 
00713     StringID message;
00714     if (error_message == STR_TRAIN_TOO_LONG_AFTER_REPLACEMENT) {
00715       message = error_message;
00716     } else {
00717       message = STR_VEHICLE_AUTORENEW_FAILED;
00718     }
00719 
00720     SetDParam(0, v->index);
00721     SetDParam(1, error_message);
00722     AddNewsItem(message, NS_ADVICE, v->index, 0);
00723   }
00724 
00725   _current_company = OWNER_NONE;
00726 }
00727 
00733 bool CanRefitTo(EngineID engine_type, CargoID cid_to)
00734 {
00735   return HasBit(EngInfo(engine_type)->refit_mask, cid_to);
00736 }
00737 
00742 CargoID FindFirstRefittableCargo(EngineID engine_type)
00743 {
00744   uint32 refit_mask = EngInfo(engine_type)->refit_mask;
00745 
00746   if (refit_mask != 0) {
00747     for (CargoID cid = 0; cid < NUM_CARGO; cid++) {
00748       if (HasBit(refit_mask, cid)) return cid;
00749     }
00750   }
00751 
00752   return CT_INVALID;
00753 }
00754 
00759 CommandCost GetRefitCost(EngineID engine_type)
00760 {
00761   Money base_cost;
00762   ExpensesType expense_type;
00763   switch (GetEngine(engine_type)->type) {
00764     case VEH_SHIP:
00765       base_cost = _price.ship_base;
00766       expense_type = EXPENSES_SHIP_RUN;
00767       break;
00768 
00769     case VEH_ROAD:
00770       base_cost = _price.roadveh_base;
00771       expense_type = EXPENSES_ROADVEH_RUN;
00772       break;
00773 
00774     case VEH_AIRCRAFT:
00775       base_cost = _price.aircraft_base;
00776       expense_type = EXPENSES_AIRCRAFT_RUN;
00777       break;
00778 
00779     case VEH_TRAIN:
00780       base_cost = 2 * ((RailVehInfo(engine_type)->railveh_type == RAILVEH_WAGON) ?
00781                _price.build_railwagon : _price.build_railvehicle);
00782       expense_type = EXPENSES_TRAIN_RUN;
00783       break;
00784 
00785     default: NOT_REACHED();
00786   }
00787   return CommandCost(expense_type, (EngInfo(engine_type)->refit_cost * base_cost) >> 10);
00788 }
00789 
00790 static void DoDrawVehicle(const Vehicle *v)
00791 {
00792   SpriteID image = v->cur_image;
00793   SpriteID pal = PAL_NONE;
00794 
00795   if (v->vehstatus & VS_DEFPAL) pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
00796 
00797   AddSortableSpriteToDraw(image, pal, v->x_pos + v->x_offs, v->y_pos + v->y_offs,
00798     v->x_extent, v->y_extent, v->z_extent, v->z_pos, (v->vehstatus & VS_SHADOW) != 0);
00799 }
00800 
00801 void ViewportAddVehicles(DrawPixelInfo *dpi)
00802 {
00803   /* The bounding rectangle */
00804   const int l = dpi->left;
00805   const int r = dpi->left + dpi->width;
00806   const int t = dpi->top;
00807   const int b = dpi->top + dpi->height;
00808 
00809   /* The hash area to scan */
00810   int xl, xu, yl, yu;
00811 
00812   if (dpi->width + 70 < (1 << (7 + 6))) {
00813     xl = GB(l - 70, 7, 6);
00814     xu = GB(r,      7, 6);
00815   } else {
00816     /* scan whole hash row */
00817     xl = 0;
00818     xu = 0x3F;
00819   }
00820 
00821   if (dpi->height + 70 < (1 << (6 + 6))) {
00822     yl = GB(t - 70, 6, 6) << 6;
00823     yu = GB(b,      6, 6) << 6;
00824   } else {
00825     /* scan whole column */
00826     yl = 0;
00827     yu = 0x3F << 6;
00828   }
00829 
00830   for (int y = yl;; y = (y + (1 << 6)) & (0x3F << 6)) {
00831     for (int x = xl;; x = (x + 1) & 0x3F) {
00832       const Vehicle *v = _vehicle_position_hash[x + y]; // already masked & 0xFFF
00833 
00834       while (v != NULL) {
00835         if (!(v->vehstatus & VS_HIDDEN) &&
00836             l <= v->right_coord &&
00837             t <= v->bottom_coord &&
00838             r >= v->left_coord &&
00839             b >= v->top_coord) {
00840           DoDrawVehicle(v);
00841         }
00842         v = v->next_hash;
00843       }
00844 
00845       if (x == xu) break;
00846     }
00847 
00848     if (y == yu) break;
00849   }
00850 }
00851 
00852 Vehicle *CheckClickOnVehicle(const ViewPort *vp, int x, int y)
00853 {
00854   Vehicle *found = NULL, *v;
00855   uint dist, best_dist = UINT_MAX;
00856 
00857   if ((uint)(x -= vp->left) >= (uint)vp->width || (uint)(y -= vp->top) >= (uint)vp->height) return NULL;
00858 
00859   x = ScaleByZoom(x, vp->zoom) + vp->virtual_left;
00860   y = ScaleByZoom(y, vp->zoom) + vp->virtual_top;
00861 
00862   FOR_ALL_VEHICLES(v) {
00863     if ((v->vehstatus & (VS_HIDDEN|VS_UNCLICKABLE)) == 0 &&
00864         x >= v->left_coord && x <= v->right_coord &&
00865         y >= v->top_coord && y <= v->bottom_coord) {
00866 
00867       dist = max(
00868         abs(((v->left_coord + v->right_coord) >> 1) - x),
00869         abs(((v->top_coord + v->bottom_coord) >> 1) - y)
00870       );
00871 
00872       if (dist < best_dist) {
00873         found = v;
00874         best_dist = dist;
00875       }
00876     }
00877   }
00878 
00879   return found;
00880 }
00881 
00882 void CheckVehicle32Day(Vehicle *v)
00883 {
00884   if ((v->day_counter & 0x1F) != 0) return;
00885 
00886   uint16 callback = GetVehicleCallback(CBID_VEHICLE_32DAY_CALLBACK, 0, 0, v->engine_type, v);
00887   if (callback == CALLBACK_FAILED) return;
00888   if (HasBit(callback, 0)) TriggerVehicle(v, VEHICLE_TRIGGER_CALLBACK_32); // Trigger vehicle trigger 10
00889   if (HasBit(callback, 1)) v->colormap = PAL_NONE;                         // Update colormap via callback 2D
00890 }
00891 
00892 void DecreaseVehicleValue(Vehicle *v)
00893 {
00894   v->value -= v->value >> 8;
00895   InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
00896 }
00897 
00898 static const byte _breakdown_chance[64] = {
00899     3,   3,   3,   3,   3,   3,   3,   3,
00900     4,   4,   5,   5,   6,   6,   7,   7,
00901     8,   8,   9,   9,  10,  10,  11,  11,
00902    12,  13,  13,  13,  13,  14,  15,  16,
00903    17,  19,  21,  25,  28,  31,  34,  37,
00904    40,  44,  48,  52,  56,  60,  64,  68,
00905    72,  80,  90, 100, 110, 120, 130, 140,
00906   150, 170, 190, 210, 230, 250, 250, 250,
00907 };
00908 
00909 void CheckVehicleBreakdown(Vehicle *v)
00910 {
00911   int rel, rel_old;
00912 
00913   /* decrease reliability */
00914   v->reliability = rel = max((rel_old = v->reliability) - v->reliability_spd_dec, 0);
00915   if ((rel_old >> 8) != (rel >> 8)) InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
00916 
00917   if (v->breakdown_ctr != 0 || v->vehstatus & VS_STOPPED ||
00918       _settings_game.difficulty.vehicle_breakdowns < 1 ||
00919       v->cur_speed < 5 || _game_mode == GM_MENU) {
00920     return;
00921   }
00922 
00923   uint32 r = Random();
00924 
00925   /* increase chance of failure */
00926   int chance = v->breakdown_chance + 1;
00927   if (Chance16I(1, 25, r)) chance += 25;
00928   v->breakdown_chance = min(255, chance);
00929 
00930   /* calculate reliability value to use in comparison */
00931   rel = v->reliability;
00932   if (v->type == VEH_SHIP) rel += 0x6666;
00933 
00934   /* reduced breakdowns? */
00935   if (_settings_game.difficulty.vehicle_breakdowns == 1) rel += 0x6666;
00936 
00937   /* check if to break down */
00938   if (_breakdown_chance[(uint)min(rel, 0xffff) >> 10] <= v->breakdown_chance) {
00939     v->breakdown_ctr    = GB(r, 16, 6) + 0x3F;
00940     v->breakdown_delay  = GB(r, 24, 7) + 0x80;
00941     v->breakdown_chance = 0;
00942   }
00943 }
00944 
00945 static void ShowVehicleGettingOld(Vehicle *v, StringID msg)
00946 {
00947   if (v->owner != _local_company) return;
00948 
00949   /* Do not show getting-old message if autorenew is active (and it can replace the vehicle) */
00950   if (GetCompany(v->owner)->engine_renew && GetEngine(v->engine_type)->company_avail != 0) return;
00951 
00952   SetDParam(0, v->index);
00953   AddNewsItem(msg, NS_ADVICE, v->index, 0);
00954 }
00955 
00956 void AgeVehicle(Vehicle *v)
00957 {
00958   if (v->age < 65535) v->age++;
00959 
00960   int age = v->age - v->max_age;
00961   if (age == 366*0 || age == 366*1 || age == 366*2 || age == 366*3 || age == 366*4) v->reliability_spd_dec <<= 1;
00962 
00963   InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
00964 
00965   if (age == -366) {
00966     ShowVehicleGettingOld(v, STR_01A0_IS_GETTING_OLD);
00967   } else if (age == 0) {
00968     ShowVehicleGettingOld(v, STR_01A1_IS_GETTING_VERY_OLD);
00969   } else if (age > 0 && (age % 366) == 0) {
00970     ShowVehicleGettingOld(v, STR_01A2_IS_GETTING_VERY_OLD_AND);
00971   }
00972 }
00973 
00981 CommandCost CmdStartStopVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2, const char *text)
00982 {
00983   /* Disable the effect of p2 bit 0, when DC_AUTOREPLACE is not set */
00984   if ((flags & DC_AUTOREPLACE) == 0) SetBit(p2, 0);
00985 
00986   if (!IsValidVehicleID(p1)) return CMD_ERROR;
00987 
00988   Vehicle *v = GetVehicle(p1);
00989 
00990   if (!CheckOwnership(v->owner)) return CMD_ERROR;
00991   if (!v->IsPrimaryVehicle()) return CMD_ERROR;
00992 
00993   switch (v->type) {
00994     case VEH_TRAIN:
00995       if (v->vehstatus & VS_STOPPED && v->u.rail.cached_power == 0) return_cmd_error(STR_TRAIN_START_NO_CATENARY);
00996       break;
00997 
00998     case VEH_SHIP:
00999     case VEH_ROAD:
01000       break;
01001 
01002     case VEH_AIRCRAFT:
01003       /* cannot stop airplane when in flight, or when taking off / landing */
01004       if (v->u.air.state >= STARTTAKEOFF && v->u.air.state < TERM7) return_cmd_error(STR_A017_AIRCRAFT_IS_IN_FLIGHT);
01005       break;
01006 
01007     default: return CMD_ERROR;
01008   }
01009 
01010   /* Check if this vehicle can be started/stopped. The callback will fail or
01011    * return 0xFF if it can. */
01012   uint16 callback = GetVehicleCallback(CBID_VEHICLE_START_STOP_CHECK, 0, 0, v->engine_type, v);
01013   if (callback != CALLBACK_FAILED && GB(callback, 0, 8) != 0xFF && HasBit(p2, 0)) {
01014     StringID error = GetGRFStringID(GetEngineGRFID(v->engine_type), 0xD000 + callback);
01015     return_cmd_error(error);
01016   }
01017 
01018   if (flags & DC_EXEC) {
01019     static const StringID vehicle_waiting_in_depot[] = {
01020       STR_8814_TRAIN_IS_WAITING_IN_DEPOT,
01021       STR_9016_ROAD_VEHICLE_IS_WAITING,
01022       STR_981C_SHIP_IS_WAITING_IN_DEPOT,
01023       STR_A014_AIRCRAFT_IS_WAITING_IN,
01024     };
01025 
01026     static const WindowClass vehicle_list[] = {
01027       WC_TRAINS_LIST,
01028       WC_ROADVEH_LIST,
01029       WC_SHIPS_LIST,
01030       WC_AIRCRAFT_LIST,
01031     };
01032 
01033     if (v->IsStoppedInDepot() && (flags & DC_AUTOREPLACE) == 0) DeleteVehicleNews(p1, vehicle_waiting_in_depot[v->type]);
01034 
01035     v->vehstatus ^= VS_STOPPED;
01036     if (v->type != VEH_TRAIN) v->cur_speed = 0; // trains can stop 'slowly'
01037     InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
01038     InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
01039     InvalidateWindowClasses(vehicle_list[v->type]);
01040   }
01041   return CommandCost();
01042 }
01043 
01054 CommandCost CmdMassStartStopVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2, const char *text)
01055 {
01056   VehicleList list;
01057   CommandCost return_value = CMD_ERROR;
01058   VehicleType vehicle_type = (VehicleType)GB(p2, 0, 5);
01059   bool start_stop = HasBit(p2, 5);
01060   bool vehicle_list_window = HasBit(p2, 6);
01061 
01062   if (vehicle_list_window) {
01063     uint32 id = p1;
01064     uint16 window_type = p2 & VLW_MASK;
01065 
01066     GenerateVehicleSortList(&list, vehicle_type, _current_company, id, window_type);
01067   } else {
01068     /* Get the list of vehicles in the depot */
01069     BuildDepotVehicleList(vehicle_type, tile, &list, NULL);
01070   }
01071 
01072   for (uint i = 0; i < list.Length(); i++) {
01073     const Vehicle *v = list[i];
01074 
01075     if (!!(v->vehstatus & VS_STOPPED) != start_stop) continue;
01076 
01077     if (!vehicle_list_window) {
01078       if (vehicle_type == VEH_TRAIN) {
01079         if (CheckTrainInDepot(v, false) == -1) continue;
01080       } else {
01081         if (!(v->vehstatus & VS_HIDDEN)) continue;
01082       }
01083     }
01084 
01085     CommandCost ret = DoCommand(tile, v->index, 0, flags, CMD_START_STOP_VEHICLE);
01086 
01087     if (CmdSucceeded(ret)) {
01088       return_value = CommandCost();
01089       /* We know that the command is valid for at least one vehicle.
01090        * If we haven't set DC_EXEC, then there is no point in continueing because it will be valid */
01091       if (!(flags & DC_EXEC)) break;
01092     }
01093   }
01094 
01095   return return_value;
01096 }
01097 
01104 CommandCost CmdDepotSellAllVehicles(TileIndex tile, uint32 flags, uint32 p1, uint32 p2, const char *text)
01105 {
01106   VehicleList list;
01107 
01108   CommandCost cost(EXPENSES_NEW_VEHICLES);
01109   uint sell_command;
01110   VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8);
01111 
01112   switch (vehicle_type) {
01113     case VEH_TRAIN:    sell_command = CMD_SELL_RAIL_WAGON; break;
01114     case VEH_ROAD:     sell_command = CMD_SELL_ROAD_VEH;   break;
01115     case VEH_SHIP:     sell_command = CMD_SELL_SHIP;       break;
01116     case VEH_AIRCRAFT: sell_command = CMD_SELL_AIRCRAFT;   break;
01117     default: return CMD_ERROR;
01118   }
01119 
01120   /* Get the list of vehicles in the depot */
01121   BuildDepotVehicleList(vehicle_type, tile, &list, &list);
01122 
01123   for (uint i = 0; i < list.Length(); i++) {
01124     CommandCost ret = DoCommand(tile, list[i]->index, 1, flags, sell_command);
01125     if (CmdSucceeded(ret)) cost.AddCost(ret);
01126   }
01127 
01128   if (cost.GetCost() == 0) return CMD_ERROR; // no vehicles to sell
01129   return cost;
01130 }
01131 
01141 CommandCost CmdDepotMassAutoReplace(TileIndex tile, uint32 flags, uint32 p1, uint32 p2, const char *text)
01142 {
01143   VehicleList list;
01144   CommandCost cost = CommandCost(EXPENSES_NEW_VEHICLES);
01145   VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8);
01146   bool all_or_nothing = HasBit(p2, 0);
01147 
01148   if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR;
01149 
01150   /* Get the list of vehicles in the depot */
01151   BuildDepotVehicleList(vehicle_type, tile, &list, &list, true);
01152 
01153   bool did_something = false;
01154 
01155   for (uint i = 0; i < list.Length(); i++) {
01156     Vehicle *v = (Vehicle*)list[i];
01157 
01158     /* Ensure that the vehicle completely in the depot */
01159     if (!v->IsInDepot()) continue;
01160 
01161     CommandCost ret = DoCommand(0, v->index, 0, flags, CMD_AUTOREPLACE_VEHICLE);
01162 
01163     if (CmdSucceeded(ret)) {
01164       did_something = true;
01165       cost.AddCost(ret);
01166     } else {
01167       if (ret.GetErrorMessage() != STR_AUTOREPLACE_NOTHING_TO_DO && all_or_nothing) {
01168         /* We failed to replace a vehicle even though we set all or nothing.
01169          * We should never reach this if DC_EXEC is set since then it should
01170          * have failed the estimation guess. */
01171         assert(!(flags & DC_EXEC));
01172         /* Now we will have to return an error. */
01173         return CMD_ERROR;
01174       }
01175     }
01176   }
01177 
01178   if (!did_something) {
01179     /* Either we didn't replace anything or something went wrong.
01180      * Either way we want to return an error and not execute this command. */
01181     cost = CMD_ERROR;
01182   }
01183 
01184   return cost;
01185 }
01186 
01193 CommandCost CmdCloneVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2, const char *text)
01194 {
01195   CommandCost total_cost(EXPENSES_NEW_VEHICLES);
01196   uint32 build_argument = 2;
01197 
01198   if (!IsValidVehicleID(p1)) return CMD_ERROR;
01199 
01200   Vehicle *v = GetVehicle(p1);
01201   Vehicle *v_front = v;
01202   Vehicle *w = NULL;
01203   Vehicle *w_front = NULL;
01204   Vehicle *w_rear = NULL;
01205 
01206   /*
01207    * v_front is the front engine in the original vehicle
01208    * v is the car/vehicle of the original vehicle, that is currently being copied
01209    * w_front is the front engine of the cloned vehicle
01210    * w is the car/vehicle currently being cloned
01211    * w_rear is the rear end of the cloned train. It's used to add more cars and is only used by trains
01212    */
01213 
01214   if (!CheckOwnership(v->owner)) return CMD_ERROR;
01215 
01216   if (v->type == VEH_TRAIN && (!IsFrontEngine(v) || v->u.rail.crash_anim_pos >= 4400)) return CMD_ERROR;
01217 
01218   /* check that we can allocate enough vehicles */
01219   if (!(flags &