# vehicle.cpp

Go to the documentation of this file.

    00001 /* $Id: vehicle.cpp 15434 2009-02-09 21:20:05Z rubidium $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "openttd.h"
    00007 #include "roadveh.h"
    00008 #include "ship.h"
    00009 #include "spritecache.h"
    00010 #include "landscape.h"
    00011 #include "timetable.h"
    00012 #include "viewport_func.h"
    00013 #include "gfx_func.h"
    00014 #include "news_func.h"
    00015 #include "command_func.h"
    00016 #include "company_func.h"
    00017 #include "vehicle_gui.h"
    00018 #include "train.h"
    00019 #include "aircraft.h"
    00020 #include "newgrf_engine.h"
    00021 #include "newgrf_sound.h"
    00022 #include "newgrf_station.h"
    00023 #include "newgrf_text.h"
    00024 #include "group.h"
    00025 #include "group_gui.h"
    00026 #include "strings_func.h"
    00027 #include "zoom_func.h"
    00028 #include "functions.h"
    00029 #include "date_func.h"
    00030 #include "window_func.h"
    00031 #include "vehicle_func.h"
    00032 #include "autoreplace_func.h"
    00033 #include "autoreplace_gui.h"
    00034 #include "string_func.h"
    00035 #include "oldpool_func.h"
    00036 #include "depot_map.h"
    00037 #include "ai/ai.hpp"
    00038 #include "core/smallmap_type.hpp"
    00039 #include "vehiclelist.h"
    00040 #include "core/mem_func.hpp"
    00041 #include "depot_func.h"
    00042 #include "settings_type.h"
    00043
    00044 #include "table/sprites.h"
    00045 #include "table/strings.h"
    00046
    00047 #define GEN_HASH(x, y) ((GB((y), 6, 6) << 6) + GB((x), 7, 6))
    00048
    00049 VehicleID _vehicle_id_ctr_day;
    00050 const Vehicle *_place_clicked_vehicle;
    00051 VehicleID _new_vehicle_id;
    00052 uint16 _returned_refit_capacity;
    00053
    00054
    00055 /* Tables used in vehicle.h to find the right command for a certain vehicle type */
    00056 const uint32 _veh_build_proc_table[] = {
    00057   CMD_BUILD_RAIL_VEHICLE,
    00058   CMD_BUILD_ROAD_VEH,
    00059   CMD_BUILD_SHIP,
    00060   CMD_BUILD_AIRCRAFT,
    00061 };
    00062 const uint32 _veh_sell_proc_table[] = {
    00063   CMD_SELL_RAIL_WAGON,
    00064   CMD_SELL_ROAD_VEH,
    00065   CMD_SELL_SHIP,
    00066   CMD_SELL_AIRCRAFT,
    00067 };
    00068
    00069 const uint32 _veh_refit_proc_table[] = {
    00070   CMD_REFIT_RAIL_VEHICLE,
    00071   CMD_REFIT_ROAD_VEH,
    00072   CMD_REFIT_SHIP,
    00073   CMD_REFIT_AIRCRAFT,
    00074 };
    00075
    00076 const uint32 _send_to_depot_proc_table[] = {
    00077   CMD_SEND_TRAIN_TO_DEPOT,
    00078   CMD_SEND_ROADVEH_TO_DEPOT,
    00079   CMD_SEND_SHIP_TO_DEPOT,
    00080   CMD_SEND_AIRCRAFT_TO_HANGAR,
    00081 };
    00082
    00083
    00084 /* Initialize the vehicle-pool */
    00085 DEFINE_OLD_POOL_GENERIC(Vehicle, Vehicle)
    00086
    00087
    00091 bool Vehicle::NeedsAutorenewing(const Company *c) const
    00092 {
    00093   /* We can always generate the Company pointer when we have the vehicle.
    00094    * However this takes time and since the Company pointer is often present
    00095    * when this function is called then it's faster to pass the pointer as an
    00096    * argument rather than finding it again. */
    00097   assert(c == GetCompany(this->owner));
    00098
    00099   if (!c->engine_renew) return false;
    00100   if (this->age - this->max_age < (c->engine_renew_months * 30)) return false;
    00101   if (this->age == 0) return false; // rail cars don't age and lacks a max age
    00102
    00103   return true;
    00104 }
    00105
    00106 void VehicleServiceInDepot(Vehicle *v)
    00107 {
    00108   v->date_of_last_service = _date;
    00109   v->breakdowns_since_last_service = 0;
    00110   v->reliability = GetEngine(v->engine_type)->reliability;
    00111   InvalidateWindow(WC_VEHICLE_DETAILS, v->index); // ensure that last service date and reliability are updated
    00112 }
    00113
    00114 bool Vehicle::NeedsServicing() const
    00115 {
    00116   if (this->vehstatus & (VS_STOPPED | VS_CRASHED)) return false;
    00117
    00118   if (_settings_game.order.no_servicing_if_no_breakdowns && _settings_game.difficulty.vehicle_breakdowns == 0) {
    00119     /* Vehicles set for autoreplacing needs to go to a depot even if breakdowns are turned off.
    00120      * Note: If servicing is enabled, we postpone replacement till next service. */
    00121     return EngineHasReplacementForCompany(GetCompany(this->owner), this->engine_type, this->group_id);
    00122   }
    00123
    00124   return _settings_game.vehicle.servint_ispercent ?
    00125     (this->reliability < GetEngine(this->engine_type)->reliability * (100 - this->service_interval) / 100) :
    00126     (this->date_of_last_service + this->service_interval < _date);
    00127 }
    00128
    00129 bool Vehicle::NeedsAutomaticServicing() const
    00130 {
    00131   if (_settings_game.order.gotodepot && VehicleHasDepotOrders(this)) return false;
    00132   if (this->current_order.IsType(OT_LOADING))            return false;
    00133   if (this->current_order.IsType(OT_GOTO_DEPOT) && this->current_order.GetDepotOrderType() != ODTFB_SERVICE) return false;
    00134   return NeedsServicing();
    00135 }
    00136
    00137 StringID VehicleInTheWayErrMsg(const Vehicle *v)
    00138 {
    00139   switch (v->type) {
    00140     case VEH_TRAIN:    return STR_8803_TRAIN_IN_THE_WAY;
    00141     case VEH_ROAD:     return STR_9000_ROAD_VEHICLE_IN_THE_WAY;
    00142     case VEH_AIRCRAFT: return STR_A015_AIRCRAFT_IN_THE_WAY;
    00143     default:           return STR_980E_SHIP_IN_THE_WAY;
    00144   }
    00145 }
    00146
    00147 static Vehicle *EnsureNoVehicleProcZ(Vehicle *v, void *data)
    00148 {
    00149   byte z = *(byte*)data;
    00150
    00151   if (v->type == VEH_DISASTER || (v->type == VEH_AIRCRAFT && v->subtype == AIR_SHADOW)) return NULL;
    00152   if (v->z_pos > z) return NULL;
    00153
    00154   _error_message = VehicleInTheWayErrMsg(v);
    00155   return v;
    00156 }
    00157
    00158 bool EnsureNoVehicleOnGround(TileIndex tile)
    00159 {
    00160   byte z = GetTileMaxZ(tile);
    00161   return !HasVehicleOnPos(tile, &z, &EnsureNoVehicleProcZ);
    00162 }
    00163
    00165 static Vehicle *GetVehicleTunnelBridgeProc(Vehicle *v, void *data)
    00166 {
    00167   if (v->type != VEH_TRAIN && v->type != VEH_ROAD && v->type != VEH_SHIP) return NULL;
    00168   if (v == (const Vehicle *)data) return NULL;
    00169
    00170   _error_message = VehicleInTheWayErrMsg(v);
    00171   return v;
    00172 }
    00173
    00181 bool HasVehicleOnTunnelBridge(TileIndex tile, TileIndex endtile, const Vehicle *ignore)
    00182 {
    00183   return HasVehicleOnPos(tile, (void *)ignore, &GetVehicleTunnelBridgeProc) ||
    00184       HasVehicleOnPos(endtile, (void *)ignore, &GetVehicleTunnelBridgeProc);
    00185 }
    00186
    00187
    00188 static void UpdateVehiclePosHash(Vehicle *v, int x, int y);
    00189
    00190 void VehiclePositionChanged(Vehicle *v)
    00191 {
    00192   int img = v->cur_image;
    00193   Point pt = RemapCoords(v->x_pos + v->x_offs, v->y_pos + v->y_offs, v->z_pos);
    00194   const Sprite *spr = GetSprite(img, ST_NORMAL);
    00195
    00196   pt.x += spr->x_offs;
    00197   pt.y += spr->y_offs;
    00198
    00199   UpdateVehiclePosHash(v, pt.x, pt.y);
    00200
    00201   v->left_coord = pt.x;
    00202   v->top_coord = pt.y;
    00203   v->right_coord = pt.x + spr->width + 2;
    00204   v->bottom_coord = pt.y + spr->height + 2;
    00205 }
    00206
    00207 Vehicle::Vehicle()
    00208 {
    00209   this->type               = VEH_INVALID;
    00210   this->left_coord         = INVALID_COORD;
    00211   this->group_id           = DEFAULT_GROUP;
    00212   this->fill_percent_te_id = INVALID_TE_ID;
    00213   this->first              = this;
    00214   this->colourmap           = PAL_NONE;
    00215 }
    00216
    00221 byte VehicleRandomBits()
    00222 {
    00223   return GB(Random(), 0, 8);
    00224 }
    00225
    00226
    00227 /* static */ bool Vehicle::AllocateList(Vehicle **vl, int num)
    00228 {
    00229   if (!Vehicle::CanAllocateItem(num)) return false;
    00230   if (vl == NULL) return true;
    00231
    00232   uint counter = _Vehicle_pool.first_free_index;
    00233
    00234   for (int i = 0; i != num; i++) {
    00235     vl[i] = new (AllocateRaw(counter)) InvalidVehicle();
    00236     counter++;
    00237   }
    00238
    00239   return true;
    00240 }
    00241
    00242 /* Size of the hash, 6 = 64 x 64, 7 = 128 x 128. Larger sizes will (in theory) reduce hash
    00243  * lookup times at the expense of memory usage. */
    00244 const int HASH_BITS = 7;
    00245 const int HASH_SIZE = 1 << HASH_BITS;
    00246 const int HASH_MASK = HASH_SIZE - 1;
    00247 const int TOTAL_HASH_SIZE = 1 << (HASH_BITS * 2);
    00248 const int TOTAL_HASH_MASK = TOTAL_HASH_SIZE - 1;
    00249
    00250 /* Resolution of the hash, 0 = 1*1 tile, 1 = 2*2 tiles, 2 = 4*4 tiles, etc.
    00251  * Profiling results show that 0 is fastest. */
    00252 const int HASH_RES = 0;
    00253
    00254 static Vehicle *_new_vehicle_position_hash[TOTAL_HASH_SIZE];
    00255
    00256 static Vehicle *VehicleFromHash(int xl, int yl, int xu, int yu, void *data, VehicleFromPosProc *proc, bool find_first)
    00257 {
    00258   for (int y = yl; ; y = (y + (1 << HASH_BITS)) & (HASH_MASK << HASH_BITS)) {
    00259     for (int x = xl; ; x = (x + 1) & HASH_MASK) {
    00260       Vehicle *v = _new_vehicle_position_hash[(x + y) & TOTAL_HASH_MASK];
    00261       for (; v != NULL; v = v->next_new_hash) {
    00262         Vehicle *a = proc(v, data);
    00263         if (find_first && a != NULL) return a;
    00264       }
    00265       if (x == xu) break;
    00266     }
    00267     if (y == yu) break;
    00268   }
    00269
    00270   return NULL;
    00271 }
    00272
    00273
    00285 static Vehicle *VehicleFromPosXY(int x, int y, void *data, VehicleFromPosProc *proc, bool find_first)
    00286 {
    00287   const int COLL_DIST = 6;
    00288
    00289   /* Hash area to scan is from xl,yl to xu,yu */
    00290   int xl = GB((x - COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS);
    00291   int xu = GB((x + COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS);
    00292   int yl = GB((y - COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS) << HASH_BITS;
    00293   int yu = GB((y + COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS) << HASH_BITS;
    00294
    00295   return VehicleFromHash(xl, yl, xu, yu, data, proc, find_first);
    00296 }
    00297
    00312 void FindVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
    00313 {
    00314   VehicleFromPosXY(x, y, data, proc, false);
    00315 }
    00316
    00328 bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
    00329 {
    00330   return VehicleFromPosXY(x, y, data, proc, true) != NULL;
    00331 }
    00332
    00343 static Vehicle *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc, bool find_first)
    00344 {
    00345   int x = GB(TileX(tile), HASH_RES, HASH_BITS);
    00346   int y = GB(TileY(tile), HASH_RES, HASH_BITS) << HASH_BITS;
    00347
    00348   Vehicle *v = _new_vehicle_position_hash[(x + y) & TOTAL_HASH_MASK];
    00349   for (; v != NULL; v = v->next_new_hash) {
    00350     if (v->tile != tile) continue;
    00351
    00352     Vehicle *a = proc(v, data);
    00353     if (find_first && a != NULL) return a;
    00354   }
    00355
    00356   return NULL;
    00357 }
    00358
    00372 void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
    00373 {
    00374   VehicleFromPos(tile, data, proc, false);
    00375 }
    00376
    00387 bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
    00388 {
    00389   return VehicleFromPos(tile, data, proc, true) != NULL;
    00390 }
    00391
    00392
    00393 static void UpdateNewVehiclePosHash(Vehicle *v, bool remove)
    00394 {
    00395   Vehicle **old_hash = v->old_new_hash;
    00396   Vehicle **new_hash;
    00397
    00398   if (remove) {
    00399     new_hash = NULL;
    00400   } else {
    00401     int x = GB(TileX(v->tile), HASH_RES, HASH_BITS);
    00402     int y = GB(TileY(v->tile), HASH_RES, HASH_BITS) << HASH_BITS;
    00403     new_hash = &_new_vehicle_position_hash[(x + y) & TOTAL_HASH_MASK];
    00404   }
    00405
    00406   if (old_hash == new_hash) return;
    00407
    00408   /* Remove from the old position in the hash table */
    00409   if (old_hash != NULL) {
    00410     Vehicle *last = NULL;
    00411     Vehicle *u = *old_hash;
    00412     while (u != v) {
    00413       last = u;
    00414       u = u->next_new_hash;
    00415       assert(u != NULL);
    00416     }
    00417
    00418     if (last == NULL) {
    00419       *old_hash = v->next_new_hash;
    00420     } else {
    00421       last->next_new_hash = v->next_new_hash;
    00422     }
    00423   }
    00424
    00425   /* Insert vehicle at beginning of the new position in the hash table */
    00426   if (new_hash != NULL) {
    00427     v->next_new_hash = *new_hash;
    00428     *new_hash = v;
    00429     assert(v != v->next_new_hash);
    00430   }
    00431
    00432   /* Remember current hash position */
    00433   v->old_new_hash = new_hash;
    00434 }
    00435
    00436 static Vehicle *_vehicle_position_hash[0x1000];
    00437
    00438 static void UpdateVehiclePosHash(Vehicle *v, int x, int y)
    00439 {
    00440   UpdateNewVehiclePosHash(v, x == INVALID_COORD);
    00441
    00442   Vehicle **old_hash, **new_hash;
    00443   int old_x = v->left_coord;
    00444   int old_y = v->top_coord;
    00445
    00446   new_hash = (x == INVALID_COORD) ? NULL : &_vehicle_position_hash[GEN_HASH(x, y)];
    00447   old_hash = (old_x == INVALID_COORD) ? NULL : &_vehicle_position_hash[GEN_HASH(old_x, old_y)];
    00448
    00449   if (old_hash == new_hash) return;
    00450
    00451   /* remove from hash table? */
    00452   if (old_hash != NULL) {
    00453     Vehicle *last = NULL;
    00454     Vehicle *u = *old_hash;
    00455     while (u != v) {
    00456       last = u;
    00457       u = u->next_hash;
    00458       assert(u != NULL);
    00459     }
    00460
    00461     if (last == NULL) {
    00462       *old_hash = v->next_hash;
    00463     } else {
    00464       last->next_hash = v->next_hash;
    00465     }
    00466   }
    00467
    00468   /* insert into hash table? */
    00469   if (new_hash != NULL) {
    00470     v->next_hash = *new_hash;
    00471     *new_hash = v;
    00472   }
    00473 }
    00474
    00475 void ResetVehiclePosHash()
    00476 {
    00477   Vehicle *v;
    00478   FOR_ALL_VEHICLES(v) { v->old_new_hash = NULL; }
    00479   memset(_vehicle_position_hash, 0, sizeof(_vehicle_position_hash));
    00480   memset(_new_vehicle_position_hash, 0, sizeof(_new_vehicle_position_hash));
    00481 }
    00482
    00483 void ResetVehicleColourMap()
    00484 {
    00485   Vehicle *v;
    00486   FOR_ALL_VEHICLES(v) { v->colourmap = PAL_NONE; }
    00487 }
    00488
    00493 typedef SmallMap<Vehicle *, bool, 4> AutoreplaceMap;
    00494 static AutoreplaceMap _vehicles_to_autoreplace;
    00495
    00496 void InitializeVehicles()
    00497 {
    00498   _Vehicle_pool.CleanPool();
    00499   _Vehicle_pool.AddBlockToPool();
    00500
    00501   _vehicles_to_autoreplace.Reset();
    00502   ResetVehiclePosHash();
    00503 }
    00504
    00505 Vehicle *GetLastVehicleInChain(Vehicle *v)
    00506 {
    00507   while (v->Next() != NULL) v = v->Next();
    00508   return v;
    00509 }
    00510
    00511 const Vehicle *GetLastVehicleInChain(const Vehicle *v)
    00512 {
    00513   while (v->Next() != NULL) v = v->Next();
    00514   return v;
    00515 }
    00516
    00517 uint CountVehiclesInChain(const Vehicle *v)
    00518 {
    00519   uint count = 0;
    00520   do count++; while ((v = v->Next()) != NULL);
    00521   return count;
    00522 }
    00523
    00528 bool IsEngineCountable(const Vehicle *v)
    00529 {
    00530   switch (v->type) {
    00531     case VEH_AIRCRAFT: return IsNormalAircraft(v); // don't count plane shadows and helicopter rotors
    00532     case VEH_TRAIN:
    00533       return !IsArticulatedPart(v) && // tenders and other articulated parts
    00534       !IsRearDualheaded(v); // rear parts of multiheaded engines
    00535     case VEH_ROAD: return IsRoadVehFront(v);
    00536     case VEH_SHIP: return true;
    00537     default: return false; // Only count company buildable vehicles
    00538   }
    00539 }
    00540
    00541 void Vehicle::PreDestructor()
    00542 {
    00543   if (CleaningPool()) return;
    00544
    00545   if (IsValidStationID(this->last_station_visited)) {
    00546     GetStation(this->last_station_visited)->loading_vehicles.remove(this);
    00547
    00548     HideFillingPercent(&this->fill_percent_te_id);
    00549   }
    00550
    00551   if (IsEngineCountable(this)) {
    00552     GetCompany(this->owner)->num_engines[this->engine_type]--;
    00553     if (this->owner == _local_company) InvalidateAutoreplaceWindow(this->engine_type, this->group_id);
    00554
    00555     DeleteGroupHighlightOfVehicle(this);
    00556     if (IsValidGroupID(this->group_id)) GetGroup(this->group_id)->num_engines[this->engine_type]--;
    00557     if (this->IsPrimaryVehicle()) DecreaseGroupNumVehicle(this->group_id);
    00558   }
    00559
    00560   if (this->type == VEH_ROAD) ClearSlot(this);
    00561   if (this->type == VEH_AIRCRAFT && this->IsPrimaryVehicle()) {
    00562     Station *st = GetTargetAirportIfValid(this);
    00563     if (st != NULL) {
    00564       const AirportFTA *layout = st->Airport()->layout;
    00565       CLRBITS(st->airport_flags, layout[this->u.air.previous_pos].block | layout[this->u.air.pos].block);
    00566     }
    00567   }
    00568
    00569   if (this->type != VEH_TRAIN || (this->type == VEH_TRAIN && (IsFrontEngine(this) || IsFreeWagon(this)))) {
    00570     InvalidateWindowData(WC_VEHICLE_DEPOT, this->tile);
    00571   }
    00572
    00573   if (this->IsPrimaryVehicle()) {
    00574     DeleteWindowById(WC_VEHICLE_VIEW, this->index);
    00575     DeleteWindowById(WC_VEHICLE_ORDERS, this->index);
    00576     DeleteWindowById(WC_VEHICLE_REFIT, this->index);
    00577     DeleteWindowById(WC_VEHICLE_DETAILS, this->index);
    00578     DeleteWindowById(WC_VEHICLE_TIMETABLE, this->index);
    00579     InvalidateWindow(WC_COMPANY, this->owner);
    00580   }
    00581   InvalidateWindowClassesData(GetWindowClassForVehicleType(this->type), 0);
    00582
    00583   this->cargo.Truncate(0);
    00584   DeleteVehicleOrders(this);
    00585   DeleteDepotHighlightOfVehicle(this);
    00586
    00587   extern void StopGlobalFollowVehicle(const Vehicle *v);
    00588   StopGlobalFollowVehicle(this);
    00589 }
    00590
    00591 Vehicle::~Vehicle()
    00592 {
    00593   free(this->name);
    00594
    00595   if (CleaningPool()) return;
    00596
    00597   /* sometimes, eg. for disaster vehicles, when company bankrupts, when removing crashed/flooded vehicles,
    00598    * it may happen that vehicle chain is deleted when visible */
    00599   if (!(this->vehstatus & VS_HIDDEN)) MarkSingleVehicleDirty(this);
    00600
    00601   Vehicle *v = this->Next();
    00602   this->SetNext(NULL);
    00603
    00604   delete v;
    00605
    00606   UpdateVehiclePosHash(this, INVALID_COORD, 0);
    00607   this->next_hash = NULL;
    00608   this->next_new_hash = NULL;
    00609
    00610   DeleteVehicleNews(this->index, INVALID_STRING_ID);
    00611
    00612   new (this) InvalidVehicle();
    00613 }
    00614
    00618 void VehicleEnteredDepotThisTick(Vehicle *v)
    00619 {
    00620   /* Vehicle should stop in the depot if it was in 'stopping' state or
    00621    * when the vehicle is ordered to halt in the depot. */
    00622   _vehicles_to_autoreplace[v] = !(v->vehstatus & VS_STOPPED) &&
    00623       (!v->current_order.IsType(OT_GOTO_DEPOT) ||
    00624        !(v->current_order.GetDepotActionType() & ODATFB_HALT));
    00625
    00626   /* We ALWAYS set the stopped state. Even when the vehicle does not plan on
    00627    * stopping in the depot, so we stop it to ensure that it will not reserve
    00628    * the path out of the depot before we might autoreplace it to a different
    00629    * engine. The new engine would not own the reserved path we store that we
    00630    * stopped the vehicle, so autoreplace can start it again */
    00631   v->vehstatus |= VS_STOPPED;
    00632 }
    00633
    00634 void CallVehicleTicks()
    00635 {
    00636   _vehicles_to_autoreplace.Clear();
    00637
    00638   Station *st;
    00639   FOR_ALL_STATIONS(st) LoadUnloadStation(st);
    00640
    00641   Vehicle *v;
    00642   FOR_ALL_VEHICLES(v) {
    00643     v->Tick();
    00644
    00645     switch (v->type) {
    00646       default: break;
    00647
    00648       case VEH_TRAIN:
    00649       case VEH_ROAD:
    00650       case VEH_AIRCRAFT:
    00651       case VEH_SHIP:
    00652         if (v->type == VEH_TRAIN && IsTrainWagon(v)) continue;
    00653         if (v->type == VEH_AIRCRAFT && v->subtype != AIR_HELICOPTER) continue;
    00654         if (v->type == VEH_ROAD && !IsRoadVehFront(v)) continue;
    00655
    00656         v->motion_counter += (v->direction & 1) ? (v->cur_speed * 3) / 4 : v->cur_speed;
    00657         /* Play a running sound if the motion counter passes 256 (Do we not skip sounds?) */
    00658         if (GB(v->motion_counter, 0, 8) < v->cur_speed) PlayVehicleSound(v, VSE_RUNNING);
    00659
    00660         /* Play an alterate running sound every 16 ticks */
    00661         if (GB(v->tick_counter, 0, 4) == 0) PlayVehicleSound(v, v->cur_speed > 0 ? VSE_RUNNING_16 : VSE_STOPPED_16);
    00662     }
    00663   }
    00664
    00665   for (AutoreplaceMap::iterator it = _vehicles_to_autoreplace.Begin(); it != _vehicles_to_autoreplace.End(); it++) {
    00666     v = it->first;
    00667     /* Autoreplace needs the current company set as the vehicle owner */
    00668     _current_company = v->owner;
    00669
    00670     /* Start vehicle if we stopped them in VehicleEnteredDepotThisTick()
    00671      * We need to stop them between VehicleEnteredDepotThisTick() and here or we risk that
    00672      * they are already leaving the depot again before being replaced. */
    00673     if (it->second) v->vehstatus &= ~VS_STOPPED;
    00674
    00675     /* Store the position of the effect as the vehicle pointer will become invalid later */
    00676     int x = v->x_pos;
    00677     int y = v->y_pos;
    00678     int z = v->z_pos;
    00679
    00680     const Company *c = GetCompany(_current_company);
    00681     SubtractMoneyFromCompany(CommandCost(EXPENSES_NEW_VEHICLES, (Money)c->engine_renew_money));
    00682     CommandCost res = DoCommand(0, v->index, 0, DC_EXEC, CMD_AUTOREPLACE_VEHICLE);
    00683     SubtractMoneyFromCompany(CommandCost(EXPENSES_NEW_VEHICLES, -(Money)c->engine_renew_money));
    00684
    00685     if (!IsLocalCompany()) continue;
    00686
    00687     if (res.Succeeded()) {
    00688       ShowCostOrIncomeAnimation(x, y, z, res.GetCost());
    00689       continue;
    00690     }
    00691
    00692     StringID error_message = res.GetErrorMessage();
    00693     if (error_message == STR_AUTOREPLACE_NOTHING_TO_DO || error_message == INVALID_STRING_ID) continue;
    00694
    00695     if (error_message == STR_0003_NOT_ENOUGH_CASH_REQUIRES) error_message = STR_AUTOREPLACE_MONEY_LIMIT;
    00696
    00697     StringID message;
    00698     if (error_message == STR_TRAIN_TOO_LONG_AFTER_REPLACEMENT) {
    00699       message = error_message;
    00700     } else {
    00701       message = STR_VEHICLE_AUTORENEW_FAILED;
    00702     }
    00703
    00704     SetDParam(0, v->index);
    00705     SetDParam(1, error_message);
    00706     AddNewsItem(message, NS_ADVICE, v->index, 0);
    00707   }
    00708
    00709   _current_company = OWNER_NONE;
    00710 }
    00711
    00717 bool CanRefitTo(EngineID engine_type, CargoID cid_to)
    00718 {
    00719   return HasBit(EngInfo(engine_type)->refit_mask, cid_to);
    00720 }
    00721
    00726 CargoID FindFirstRefittableCargo(EngineID engine_type)
    00727 {
    00728   uint32 refit_mask = EngInfo(engine_type)->refit_mask;
    00729
    00730   if (refit_mask != 0) {
    00731     for (CargoID cid = 0; cid < NUM_CARGO; cid++) {
    00732       if (HasBit(refit_mask, cid)) return cid;
    00733     }
    00734   }
    00735
    00736   return CT_INVALID;
    00737 }
    00738
    00743 CommandCost GetRefitCost(EngineID engine_type)
    00744 {
    00745   Money base_cost;
    00746   ExpensesType expense_type;
    00747   switch (GetEngine(engine_type)->type) {
    00748     case VEH_SHIP:
    00749       base_cost = _price.ship_base;
    00750       expense_type = EXPENSES_SHIP_RUN;
    00751       break;
    00752
    00753     case VEH_ROAD:
    00754       base_cost = _price.roadveh_base;
    00755       expense_type = EXPENSES_ROADVEH_RUN;
    00756       break;
    00757
    00758     case VEH_AIRCRAFT:
    00759       base_cost = _price.aircraft_base;
    00760       expense_type = EXPENSES_AIRCRAFT_RUN;
    00761       break;
    00762
    00763     case VEH_TRAIN:
    00764       base_cost = 2 * ((RailVehInfo(engine_type)->railveh_type == RAILVEH_WAGON) ?
    00765                _price.build_railwagon : _price.build_railvehicle);
    00766       expense_type = EXPENSES_TRAIN_RUN;
    00767       break;
    00768
    00769     default: NOT_REACHED();
    00770   }
    00771   return CommandCost(expense_type, (EngInfo(engine_type)->refit_cost * base_cost) >> 10);
    00772 }
    00773
    00774 static void DoDrawVehicle(const Vehicle *v)
    00775 {
    00776   SpriteID image = v->cur_image;
    00777   SpriteID pal = PAL_NONE;
    00778
    00779   if (v->vehstatus & VS_DEFPAL) pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
    00780
    00781   AddSortableSpriteToDraw(image, pal, v->x_pos + v->x_offs, v->y_pos + v->y_offs,
    00782     v->x_extent, v->y_extent, v->z_extent, v->z_pos, (v->vehstatus & VS_SHADOW) != 0);
    00783 }
    00784
    00785 void ViewportAddVehicles(DrawPixelInfo *dpi)
    00786 {
    00787   /* The bounding rectangle */
    00788   const int l = dpi->left;
    00789   const int r = dpi->left + dpi->width;
    00790   const int t = dpi->top;
    00791   const int b = dpi->top + dpi->height;
    00792
    00793   /* The hash area to scan */
    00794   int xl, xu, yl, yu;
    00795
    00796   if (dpi->width + 70 < (1 << (7 + 6))) {
    00797     xl = GB(l - 70, 7, 6);
    00798     xu = GB(r,      7, 6);
    00799   } else {
    00800     /* scan whole hash row */
    00801     xl = 0;
    00802     xu = 0x3F;
    00803   }
    00804
    00805   if (dpi->height + 70 < (1 << (6 + 6))) {
    00806     yl = GB(t - 70, 6, 6) << 6;
    00807     yu = GB(b,      6, 6) << 6;
    00808   } else {
    00809     /* scan whole column */
    00810     yl = 0;
    00811     yu = 0x3F << 6;
    00812   }
    00813
    00814   for (int y = yl;; y = (y + (1 << 6)) & (0x3F << 6)) {
    00815     for (int x = xl;; x = (x + 1) & 0x3F) {
    00816       const Vehicle *v = _vehicle_position_hash[x + y]; // already masked & 0xFFF
    00817
    00818       while (v != NULL) {
    00819         if (!(v->vehstatus & VS_HIDDEN) &&
    00820             l <= v->right_coord &&
    00821             t <= v->bottom_coord &&
    00822             r >= v->left_coord &&
    00823             b >= v->top_coord) {
    00824           DoDrawVehicle(v);
    00825         }
    00826         v = v->next_hash;
    00827       }
    00828
    00829       if (x == xu) break;
    00830     }
    00831
    00832     if (y == yu) break;
    00833   }
    00834 }
    00835
    00836 Vehicle *CheckClickOnVehicle(const ViewPort *vp, int x, int y)
    00837 {
    00838   Vehicle *found = NULL, *v;
    00839   uint dist, best_dist = UINT_MAX;
    00840
    00841   if ((uint)(x -= vp->left) >= (uint)vp->width || (uint)(y -= vp->top) >= (uint)vp->height) return NULL;
    00842
    00843   x = ScaleByZoom(x, vp->zoom) + vp->virtual_left;
    00844   y = ScaleByZoom(y, vp->zoom) + vp->virtual_top;
    00845
    00846   FOR_ALL_VEHICLES(v) {
    00847     if ((v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0 &&
    00848         x >= v->left_coord && x <= v->right_coord &&
    00849         y >= v->top_coord && y <= v->bottom_coord) {
    00850
    00851       dist = max(
    00852         abs(((v->left_coord + v->right_coord) >> 1) - x),
    00853         abs(((v->top_coord + v->bottom_coord) >> 1) - y)
    00854       );
    00855
    00856       if (dist < best_dist) {
    00857         found = v;
    00858         best_dist = dist;
    00859       }
    00860     }
    00861   }
    00862
    00863   return found;
    00864 }
    00865
    00866 void CheckVehicle32Day(Vehicle *v)
    00867 {
    00868   if ((v->day_counter & 0x1F) != 0) return;
    00869
    00870   uint16 callback = GetVehicleCallback(CBID_VEHICLE_32DAY_CALLBACK, 0, 0, v->engine_type, v);
    00871   if (callback == CALLBACK_FAILED) return;
    00872   if (HasBit(callback, 0)) TriggerVehicle(v, VEHICLE_TRIGGER_CALLBACK_32); // Trigger vehicle trigger 10
    00873   if (HasBit(callback, 1)) v->colourmap = PAL_NONE;                         // Update colourmap via callback 2D
    00874 }
    00875
    00876 void DecreaseVehicleValue(Vehicle *v)
    00877 {
    00878   v->value -= v->value >> 8;
    00879   InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
    00880 }
    00881
    00882 static const byte _breakdown_chance[64] = {
    00883     3,   3,   3,   3,   3,   3,   3,   3,
    00884     4,   4,   5,   5,   6,   6,   7,   7,
    00885     8,   8,   9,   9,  10,  10,  11,  11,
    00886    12,  13,  13,  13,  13,  14,  15,  16,
    00887    17,  19,  21,  25,  28,  31,  34,  37,
    00888    40,  44,  48,  52,  56,  60,  64,  68,
    00889    72,  80,  90, 100, 110, 120, 130, 140,
    00890   150, 170, 190, 210, 230, 250, 250, 250,
    00891 };
    00892
    00893 void CheckVehicleBreakdown(Vehicle *v)
    00894 {
    00895   int rel, rel_old;
    00896
    00897   /* decrease reliability */
    00898   v->reliability = rel = max((rel_old = v->reliability) - v->reliability_spd_dec, 0);
    00899   if ((rel_old >> 8) != (rel >> 8)) InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
    00900
    00901   if (v->breakdown_ctr != 0 || v->vehstatus & VS_STOPPED ||
    00902       _settings_game.difficulty.vehicle_breakdowns < 1 ||
    00903       v->cur_speed < 5 || _game_mode == GM_MENU) {
    00904     return;
    00905   }
    00906
    00907   uint32 r = Random();
    00908
    00909   /* increase chance of failure */
    00910   int chance = v->breakdown_chance + 1;
    00911   if (Chance16I(1, 25, r)) chance += 25;
    00912   v->breakdown_chance = min(255, chance);
    00913
    00914   /* calculate reliability value to use in comparison */
    00915   rel = v->reliability;
    00916   if (v->type == VEH_SHIP) rel += 0x6666;
    00917
    00918   /* reduced breakdowns? */
    00919   if (_settings_game.difficulty.vehicle_breakdowns == 1) rel += 0x6666;
    00920
    00921   /* check if to break down */
    00922   if (_breakdown_chance[(uint)min(rel, 0xffff) >> 10] <= v->breakdown_chance) {
    00923     v->breakdown_ctr    = GB(r, 16, 6) + 0x3F;
    00924     v->breakdown_delay  = GB(r, 24, 7) + 0x80;
    00925     v->breakdown_chance = 0;
    00926   }
    00927 }
    00928
    00929 void AgeVehicle(Vehicle *v)
    00930 {
    00931   if (v->age < 65535) v->age++;
    00932
    00933   int age = v->age - v->max_age;
    00934   if (age == DAYS_IN_LEAP_YEAR * 0 || age == DAYS_IN_LEAP_YEAR * 1 ||
    00935       age == DAYS_IN_LEAP_YEAR * 2 || age == DAYS_IN_LEAP_YEAR * 3 || age == DAYS_IN_LEAP_YEAR * 4) {
    00936     v->reliability_spd_dec <<= 1;
    00937   }
    00938
    00939   InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
    00940
    00941   /* Don't warn about non-primary or not ours vehicles */
    00942   if (v->Previous() != NULL || v->owner != _local_company) return;
    00943
    00944   /* Don't warn if a renew is active */
    00945   if (GetCompany(v->owner)->engine_renew && GetEngine(v->engine_type)->company_avail != 0) return;
    00946
    00947   StringID str;
    00948   if (age == -DAYS_IN_LEAP_YEAR) {
    00949     str = STR_01A0_IS_GETTING_OLD;
    00950   } else if (age == 0) {
    00951     str = STR_01A1_IS_GETTING_VERY_OLD;
    00952   } else if (age > 0 && (age % DAYS_IN_LEAP_YEAR) == 0) {
    00953     str = STR_01A2_IS_GETTING_VERY_OLD_AND;
    00954   } else {
    00955     return;
    00956   }
    00957
    00958   SetDParam(0, v->index);
    00959   AddNewsItem(str, NS_ADVICE, v->index, 0);
    00960 }
    00961
    00969 CommandCost CmdStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    00970 {
    00971   /* Disable the effect of p2 bit 0, when DC_AUTOREPLACE is not set */
    00972   if ((flags & DC_AUTOREPLACE) == 0) SetBit(p2, 0);
    00973
    00974   if (!IsValidVehicleID(p1)) return CMD_ERROR;
    00975
    00976   Vehicle *v = GetVehicle(p1);
    00977
    00978   if (!CheckOwnership(v->owner)) return CMD_ERROR;
    00979   if (!v->IsPrimaryVehicle()) return CMD_ERROR;
    00980
    00981   switch (v->type) {
    00982     case VEH_TRAIN:
    00983       if (v->vehstatus & VS_STOPPED && v->u.rail.cached_power == 0) return_cmd_error(STR_TRAIN_START_NO_CATENARY);
    00984       break;
    00985
    00986     case VEH_SHIP:
    00987     case VEH_ROAD:
    00988       break;
    00989
    00990     case VEH_AIRCRAFT:
    00991       /* cannot stop airplane when in flight, or when taking off / landing */
    00992       if (v->u.air.state >= STARTTAKEOFF && v->u.air.state < TERM7) return_cmd_error(STR_A017_AIRCRAFT_IS_IN_FLIGHT);
    00993       break;
    00994
    00995     default: return CMD_ERROR;
    00996   }
    00997
    00998   /* Check if this vehicle can be started/stopped. The callback will fail or
    00999    * return 0xFF if it can. */
    01000   uint16 callback = GetVehicleCallback(CBID_VEHICLE_START_STOP_CHECK, 0, 0, v->engine_type, v);
    01001   if (callback != CALLBACK_FAILED && GB(callback, 0, 8) != 0xFF && HasBit(p2, 0)) {
    01002     StringID error = GetGRFStringID(GetEngineGRFID(v->engine_type), 0xD000 + callback);
    01003     return_cmd_error(error);
    01004   }
    01005
    01006   if (flags & DC_EXEC) {
    01007     static const StringID vehicle_waiting_in_depot[] = {
    01008       STR_8814_TRAIN_IS_WAITING_IN_DEPOT,
    01009       STR_9016_ROAD_VEHICLE_IS_WAITING,
    01010       STR_981C_SHIP_IS_WAITING_IN_DEPOT,
    01011       STR_A014_AIRCRAFT_IS_WAITING_IN,
    01012     };
    01013
    01014     static const WindowClass vehicle_list[] = {
    01015       WC_TRAINS_LIST,
    01016       WC_ROADVEH_LIST,
    01017       WC_SHIPS_LIST,
    01018       WC_AIRCRAFT_LIST,
    01019     };
    01020
    01021     if (v->IsStoppedInDepot() && (flags & DC_AUTOREPLACE) == 0) DeleteVehicleNews(p1, vehicle_waiting_in_depot[v->type]);
    01022
    01023     v->vehstatus ^= VS_STOPPED;
    01024     if (v->type != VEH_TRAIN) v->cur_speed = 0; // trains can stop 'slowly'
    01025     InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
    01026     InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
    01027     InvalidateWindowClasses(vehicle_list[v->type]);
    01028   }
    01029   return CommandCost();
    01030 }
    01031
    01042 CommandCost CmdMassStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    01043 {
    01044   VehicleList list;
    01045   CommandCost return_value = CMD_ERROR;
    01046   VehicleType vehicle_type = (VehicleType)GB(p2, 0, 5);
    01047   bool start_stop = HasBit(p2, 5);
    01048   bool vehicle_list_window = HasBit(p2, 6);
    01049
    01050   if (vehicle_list_window) {
    01051     uint32 id = p1;
    01052     uint16 window_type = p2 & VLW_MASK;
    01053
    01054     GenerateVehicleSortList(&list, vehicle_type, _current_company, id, window_type);
    01055   } else {
    01056     /* Get the list of vehicles in the depot */
    01057     BuildDepotVehicleList(vehicle_type, tile, &list, NULL);
    01058   }
    01059
    01060   for (uint i = 0; i < list.Length(); i++) {
    01061     const Vehicle *v = list[i];
    01062
    01063     if (!!(v->vehstatus & VS_STOPPED) != start_stop) continue;
    01064
    01065     if (!vehicle_list_window) {
    01066       if (vehicle_type == VEH_TRAIN) {
    01067         if (CheckTrainInDepot(v, false) == -1) continue;
    01068       } else {
    01069         if (!(v->vehstatus & VS_HIDDEN)) continue;
    01070       }
    01071     }
    01072
    01073     CommandCost ret = DoCommand(tile, v->index, 0, flags, CMD_START_STOP_VEHICLE);
    01074
    01075     if (CmdSucceeded(ret)) {
    01076       return_value = CommandCost();
    01077       /* We know that the command is valid for at least one vehicle.
    01078        * If we haven't set DC_EXEC, then there is no point in continueing because it will be valid */
    01079       if (!(flags & DC_EXEC)) break;
    01080     }
    01081   }
    01082
    01083   return return_value;
    01084 }
    01085
    01092 CommandCost CmdDepotSellAllVehicles(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    01093 {
    01094   VehicleList list;
    01095
    01096   CommandCost cost(EXPENSES_NEW_VEHICLES);
    01097   uint sell_command;
    01098   VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8);
    01099
    01100   switch (vehicle_type) {
    01101     case VEH_TRAIN:    sell_command = CMD_SELL_RAIL_WAGON; break;
    01102     case VEH_ROAD:     sell_command = CMD_SELL_ROAD_VEH;   break;
    01103     case VEH_SHIP:     sell_command = CMD_SELL_SHIP;       break;
    01104     case VEH_AIRCRAFT: sell_command = CMD_SELL_AIRCRAFT;   break;
    01105     default: return CMD_ERROR;
    01106   }
    01107
    01108   /* Get the list of vehicles in the depot */
    01109   BuildDepotVehicleList(vehicle_type, tile, &list, &list);
    01110
    01111   for (uint i = 0; i < list.Length(); i++) {
    01112     CommandCost ret = DoCommand(tile, list[i]->index, 1, flags, sell_command);
    01113     if (CmdSucceeded(ret)) cost.AddCost(ret);
    01114   }
    01115
    01116   if (cost.GetCost() == 0) return CMD_ERROR; // no vehicles to sell
    01117   return cost;
    01118 }
    01119
    01129 CommandCost CmdDepotMassAutoReplace(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    01130 {
    01131   VehicleList list;
    01132   CommandCost cost = CommandCost(EXPENSES_NEW_VEHICLES);
    01133   VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8);
    01134   bool all_or_nothing = HasBit(p2, 0);
    01135
    01136   if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR;
    01137
    01138   /* Get the list of vehicles in the depot */
    01139   BuildDepotVehicleList(vehicle_type, tile, &list, &list, true);
    01140
    01141   bool did_something = false;
    01142
    01143   for (uint i = 0; i < list.Length(); i++) {
    01144     Vehicle *v = (Vehicle*)list[i];
    01145
    01146     /* Ensure that the vehicle completely in the depot */
    01147     if (!v->IsInDepot()) continue;
    01148
    01149     CommandCost ret = DoCommand(0, v->index, 0, flags, CMD_AUTOREPLACE_VEHICLE);
    01150
    01151     if (CmdSucceeded(ret)) {
    01152       did_something = true;
    01153       cost.AddCost(ret);
    01154     } else {
    01155       if (ret.GetErrorMessage() != STR_AUTOREPLACE_NOTHING_TO_DO && all_or_nothing) {
    01156         /* We failed to replace a vehicle even though we set all or nothing.
    01157          * We should never reach this if DC_EXEC is set since then it should
    01158          * have failed the estimation guess. */
    01159         assert(!(flags & DC_EXEC));
    01160         /* Now we will have to return an error. */
    01161         return CMD_ERROR;
    01162       }
    01163     }
    01164   }
    01165
    01166   if (!did_something) {
    01167     /* Either we didn't replace anything or something went wrong.
    01168      * Either way we want to return an error and not execute this command. */
    01169     cost = CMD_ERROR;
    01170   }
    01171
    01172   return cost;
    01173 }
    01174
    01181 CommandCost CmdCloneVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    01182 {
    01183   CommandCost total_cost(EXPENSES_NEW_VEHICLES);
    01184   uint32 build_argument = 2;
    01185
    01186   if (!IsValidVehicleID(p1)) return CMD_ERROR;
    01187
    01188   Vehicle *v = GetVehicle(p1);
    01189   Vehicle *v_front = v;
    01190   Vehicle *w = NULL;
    01191   Vehicle *w_front = NULL;
    01192   Vehicle *w_rear = NULL;
    01193
    01194   /*
    01195    * v_front is the front engine in the original vehicle
    01196    * v is the car/vehicle of the original vehicle, that is currently being copied
    01197    * w_front is the front engine of the cloned vehicle
    01198    * w is the car/vehicle currently being cloned
    01199    * w_rear is the rear end of the cloned train. It's used to add more cars and is only used by trains
    01200    */
    01201
    01202   if (!CheckOwnership(v->owner)) return CMD_ERROR;
    01203
    01204   if (v->type == VEH_TRAIN && (!IsFrontEngine(v) || v->u.rail.crash_anim_pos >= 4400)) return CMD_ERROR;
    01205
    01206   /* check that we can allocate enough vehicles */
    01207   if (!(flags & DC_EXEC)) {
    01208     int veh_counter = 0;
    01209     do {
    01210       veh_counter++;
    01211     } while ((v = v->Next()) != NULL);
    01212
    01213     if (!Vehicle::AllocateList(NULL, veh_counter)) {
    01214       return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
    01215     }
    01216   }
    01217
    01218   v = v_front;
    01219
    01220   do {
    01221     if (v->type == VEH_TRAIN && IsRearDualheaded(v)) {
    01222       /* we build the rear ends of multiheaded trains with the front ones */
    01223       continue;
    01224     }
    01225
    01226     CommandCost cost = DoCommand(tile, v->engine_type, build_argument, flags, GetCmdBuildVeh(v));
    01227     build_argument = 3; // ensure that we only assign a number to the first engine
    01228
    01229     if (CmdFailed(cost)) return cost;
    01230
    01231     total_cost.AddCost(cost);
    01232
    01233     if (flags & DC_EXEC) {
    01234       w = GetVehicle(_new_vehicle_id);
    01235
    01236       if (v->type == VEH_TRAIN && HasBit(v->u.rail.flags, VRF_REVERSE_DIRECTION)) {
    01237         SetBit(w->u.rail.flags, VRF_REVERSE_DIRECTION);
    01238       }
    01239
    01240       if (v->type == VEH_TRAIN && !IsFrontEngine(v)) {
    01241         /* this s a train car
    01242          * add this unit to the end of the train */
    01243         CommandCost result = DoCommand(0, (w_rear->index << 16) | w->index, 1, flags, CMD_MOVE_RAIL_VEHICLE);
    01244         if (CmdFailed(result)) {
    01245           /* The train can't be joined to make the same consist as the original.
    01246            * Sell what we already made (clean up) and return an error.           */
    01247           DoCommand(w_front->tile, w_front->index, 1, flags, GetCmdSellVeh(w_front));
    01248           DoCommand(w_front->tile, w->index,       1, flags, GetCmdSellVeh(w));
    01249           return result; // return error and the message returned from CMD_MOVE_RAIL_VEHICLE
    01250         }
    01251       } else {
    01252         /* this is a front engine or not a train. */
    01253         w_front = w;
    01254         w->service_interval = v->service_interval;
    01255       }
    01256       w_rear = w; // trains needs to know the last car in the train, so they can add more in next loop
    01257     }
    01258   } while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL);
    01259
    01260   if (flags & DC_EXEC && v_front->type == VEH_TRAIN) {
    01261     /* for trains this needs to be the front engine due to the callback function */
    01262     _new_vehicle_id = w_front->index;
    01263   }
    01264
    01265   if (flags & DC_EXEC) {
    01266     /* Cloned vehicles belong to the same group */
    01267     DoCommand(0, v_front->group_id, w_front->index, flags, CMD_ADD_VEHICLE_GROUP);
    01268   }
    01269
    01270
    01271   /* Take care of refitting. */
    01272   w = w_front;
    01273   v = v_front;
    01274
    01275   /* Both building and refitting are influenced by newgrf callbacks, which
    01276    * makes it impossible to accurately estimate the cloning costs. In
    01277    * particular, it is possible for engines of the same type to be built with
    01278    * different numbers of articulated parts, so when refitting we have to
    01279    * loop over real vehicles first, and then the articulated parts of those
    01280    * vehicles in a different loop. */
    01281   do {
    01282     do {
    01283       if (flags & DC_EXEC) {
    01284         assert(w != NULL);
    01285
    01286         if (w->cargo_type != v->cargo_type || w->cargo_subtype != v->cargo_subtype) {
    01287           CommandCost cost = DoCommand(0, w->index, v->cargo_type | (v->cargo_subtype << 8) | 1U << 16 , flags, GetCmdRefitVeh(v));
    01288           if (CmdSucceeded(cost)) total_cost.AddCost(cost);
    01289         }
    01290
    01291         if (w->type == VEH_TRAIN && EngineHasArticPart(w)) {
    01292           w = GetNextArticPart(w);
    01293         } else if (w->type == VEH_ROAD && RoadVehHasArticPart(w)) {
    01294           w = w->Next();
    01295         } else {
    01296           break;
    01297         }
    01298       } else {
    01299         CargoID initial_cargo = GetEngineCargoType(v->engine_type);
    01300
    01301         if (v->cargo_type != initial_cargo && initial_cargo != CT_INVALID) {
    01302           total_cost.AddCost(GetRefitCost(v->engine_type));
    01303         }
    01304       }
    01305
    01306       if (v->type == VEH_TRAIN && EngineHasArticPart(v)) {
    01307         v = GetNextArticPart(v);
    01308       } else if (v->type == VEH_ROAD && RoadVehHasArticPart(v)) {
    01309         v = v->Next();
    01310       } else {
    01311         break;
    01312       }
    01313     } while (v != NULL);
    01314
    01315     if ((flags & DC_EXEC) && v->type == VEH_TRAIN) w = GetNextVehicle(w);
    01316   } while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL);
    01317
    01318   if (flags & DC_EXEC) {
    01319     /*
    01320      * Set the orders of the vehicle. Cannot do it earlier as we need
    01321      * the vehicle refitted before doing this, otherwise the moved
    01322      * cargo types might not match (passenger vs non-passenger)
    01323      */
    01324     DoCommand(0, (v_front->index << 16) | w_front->index, p2 & 1 ? CO_SHARE : CO_COPY, flags, CMD_CLONE_ORDER);
    01325   }
    01326
    01327   /* Since we can't estimate the cost of cloning a vehicle accurately we must
    01328    * check whether the company has enough money manually. */
    01329   if (!CheckCompanyHasMoney(total_cost)) {
    01330     if (flags & DC_EXEC) {
    01331       /* The vehicle has already been bought, so now it must be sold again. */
    01332       DoCommand(w_front->tile, w_front->index, 1, flags, GetCmdSellVeh(w_front));
    01333     }
    01334     return CMD_ERROR;
    01335   }
    01336
    01337   return total_cost;
    01338 }
    01339
    01349 CommandCost SendAllVehiclesToDepot(VehicleType type, DoCommandFlag flags, bool service, Owner owner, uint16 vlw_flag, uint32 id)
    01350 {
    01351   VehicleList list;
    01352
    01353   GenerateVehicleSortList(&list, type, owner, id, vlw_flag);
    01354
    01355   /* Send all the vehicles to a depot */
    01356   for (uint i = 0; i < list.Length(); i++) {
    01357     const Vehicle *v = list[i];
    01358     CommandCost ret = DoCommand(v->tile, v->index, (service ? 1 : 0) | DEPOT_DONT_CANCEL, flags, GetCmdSendToDepot(type));
    01359
    01360     /* Return 0 if DC_EXEC is not set this is a valid goto depot command)
    01361       * In this case we know that at least one vehicle can be sent to a depot
    01362       * and we will issue the command. We can now safely quit the loop, knowing
    01363       * it will succeed at least once. With DC_EXEC we really need to send them to the depot */
    01364     if (CmdSucceeded(ret) && !(flags & DC_EXEC)) {
    01365       return CommandCost();
    01366     }
    01367   }
    01368
    01369   return (flags & DC_EXEC) ? CommandCost() : CMD_ERROR;
    01370 }
    01371
    01378 uint8 CalcPercentVehicleFilled(const Vehicle *v, StringID *colour)
    01379 {
    01380   int count = 0;
    01381   int max = 0;
    01382   int cars = 0;
    01383   int unloading = 0;
    01384   bool loading = false;
    01385
    01386   const Vehicle *u = v;
    01387   const Station *st = v->last_station_visited != INVALID_STATION ? GetStation(v->last_station_visited) : NULL;
    01388
    01389   /* Count up max and used */
    01390   for (; v != NULL; v = v->Next()) {
    01391     count += v->cargo.Count();
    01392     max += v->cargo_cap;
    01393     if (v->cargo_cap != 0 && colour != NULL) {
    01394       unloading += HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) ? 1 : 0;
    01395       loading |= !(u->current_order.GetUnloadType() & OUFB_UNLOAD) && st->goods[v->cargo_type].days_since_pickup != 255;
    01396       cars++;
    01397     }
    01398   }
    01399
    01400   if (colour != NULL) {
    01401     if (unloading == 0 && loading) {
    01402       *colour = STR_PERCENT_UP;
    01403     } else if (cars == unloading || !loading) {
    01404       *colour = STR_PERCENT_DOWN;
    01405     } else {
    01406       *colour = STR_PERCENT_UP_DOWN;
    01407     }
    01408   }
    01409
    01410   /* Train without capacity */
    01411   if (max == 0) return 100;
    01412
    01413   /* Return the percentage */
    01414   return (count * 100) / max;
    01415 }
    01416
    01417 void VehicleEnterDepot(Vehicle *v)
    01418 {
    01419   switch (v->type) {
    01420     case VEH_TRAIN:
    01421       InvalidateWindowClasses(WC_TRAINS_LIST);
    01422       /* Clear path reservation */
    01423       SetDepotWaypointReservation(v->tile, false);
    01424       if (_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(v->tile);
    01425
    01426       if (!IsFrontEngine(v)) v = v->First();
    01427       UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR, v->owner);
    01428       v->load_unload_time_rem = 0;
    01429       ClrBit(v->u.rail.flags, VRF_TOGGLE_REVERSE);
    01430       TrainConsistChanged(v, true);
    01431       break;
    01432
    01433     case VEH_ROAD:
    01434       InvalidateWindowClasses(WC_ROADVEH_LIST);
    01435       if (!IsRoadVehFront(v)) v = v->First();
    01436       break;
    01437
    01438     case VEH_SHIP:
    01439       InvalidateWindowClasses(WC_SHIPS_LIST);
    01440       v->u.ship.state = TRACK_BIT_DEPOT;
    01441       RecalcShipStuff(v);
    01442       break;
    01443
    01444     case VEH_AIRCRAFT:
    01445       InvalidateWindowClasses(WC_AIRCRAFT_LIST);
    01446       HandleAircraftEnterHangar(v);
    01447       break;
    01448     default: NOT_REACHED();
    01449   }
    01450
    01451   if (v->type != VEH_TRAIN) {
    01452     /* Trains update the vehicle list when the first unit enters the depot and calls VehicleEnterDepot() when the last unit enters.
    01453      * 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 */
    01454     InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
    01455   }
    01456   InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
    01457
    01458   v->vehstatus |= VS_HIDDEN;
    01459   v->cur_speed = 0;
    01460
    01461   VehicleServiceInDepot(v);
    01462
    01463   TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
    01464
    01465   if (v->current_order.IsType(OT_GOTO_DEPOT)) {
    01466     InvalidateWindow(WC_VEHICLE_VIEW, v->index);
    01467
    01468     Order t = v->current_order;
    01469     v->current_order.MakeDummy();
    01470
    01471     if (t.IsRefit()) {
    01472       _current_company = v->owner;
    01473       CommandCost cost = DoCommand(v->tile, v->index, t.GetRefitCargo() | t.GetRefitSubtype() << 8, DC_EXEC, GetCmdRefitVeh(v));
    01474
    01475       if (CmdFailed(cost)) {
    01476         _vehicles_to_autoreplace[v] = false;
    01477         if (v->owner == _local_company) {
    01478           /* Notify the user that we stopped the vehicle */
    01479           SetDParam(0, v->index);
    01480           AddNewsItem(STR_ORDER_REFIT_FAILED, NS_ADVICE, v->index, 0);
    01481         }
    01482       } else if (v->owner == _local_company && cost.GetCost() != 0) {
    01483         ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
    01484       }
    01485     }
    01486
    01487     if (t.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) {
    01488       /* Part of orders */
    01489       UpdateVehicleTimetable(v, true);
    01490       v->cur_order_index++;
    01491     }
    01492     if (t.GetDepotActionType() & ODATFB_HALT) {
    01493       /* Force depot visit */
    01494       v->vehstatus |= VS_STOPPED;
    01495       if (v->owner == _local_company) {
    01496         StringID string;
    01497
    01498         switch (v->type) {
    01499           case VEH_TRAIN:    string = STR_8814_TRAIN_IS_WAITING_IN_DEPOT; break;
    01500           case VEH_ROAD:     string = STR_9016_ROAD_VEHICLE_IS_WAITING;   break;
    01501           case VEH_SHIP:     string = STR_981C_SHIP_IS_WAITING_IN_DEPOT;  break;
    01502           case VEH_AIRCRAFT: string = STR_A014_AIRCRAFT_IS_WAITING_IN;    break;
    01503           default: NOT_REACHED(); string = STR_EMPTY; // Set the string to something to avoid a compiler warning
    01504         }
    01505
    01506         SetDParam(0, v->index);
    01507         AddNewsItem(string, NS_ADVICE, v->index, 0);
    01508       }
    01509       AI::NewEvent(v->owner, new AIEventVehicleWaitingInDepot(v->index));
    01510     }
    01511   }
    01512 }
    01513
    01514 static bool IsUniqueVehicleName(const char *name)
    01515 {
    01516   const Vehicle *v;
    01517
    01518   FOR_ALL_VEHICLES(v) {
    01519     if (v->name != NULL && strcmp(v->name, name) == 0) return false;
    01520   }
    01521
    01522   return true;
    01523 }
    01524
    01531 CommandCost CmdRenameVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    01532 {
    01533   if (!IsValidVehicleID(p1)) return CMD_ERROR;
    01534
    01535   Vehicle *v = GetVehicle(p1);
    01536   if (!CheckOwnership(v->owner)) return CMD_ERROR;
    01537
    01538   bool reset = StrEmpty(text);
    01539
    01540   if (!reset) {
    01541     if (strlen(text) >= MAX_LENGTH_VEHICLE_NAME_BYTES) return CMD_ERROR;
    01542     if (!(flags & DC_AUTOREPLACE) && !IsUniqueVehicleName(text)) return_cmd_error(STR_NAME_MUST_BE_UNIQUE);
    01543   }
    01544
    01545   if (flags & DC_EXEC) {
    01546     free(v->name);
    01547     v->name = reset ? NULL : strdup(text);
    01548     InvalidateWindowClassesData(WC_TRAINS_LIST, 1);
    01549     MarkWholeScreenDirty();
    01550   }
    01551
    01552   return CommandCost();
    01553 }
    01554
    01555
    01562 CommandCost CmdChangeServiceInt(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    01563 {
    01564   uint16 serv_int = GetServiceIntervalClamped(p2); /* Double check the service interval from the user-input */
    01565
    01566   if (serv_int != p2 || !IsValidVehicleID(p1)) return CMD_ERROR;
    01567
    01568   Vehicle *v = GetVehicle(p1);
    01569
    01570   if (!CheckOwnership(v->owner)) return CMD_ERROR;
    01571
    01572   if (flags & DC_EXEC) {
    01573     v->service_interval = serv_int;
    01574     InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
    01575   }
    01576
    01577   return CommandCost();
    01578 }
    01579
    01580
    01581 static Rect _old_vehicle_coords;
    01582
    01589 void BeginVehicleMove(const Vehicle *v)
    01590 {
    01591   _old_vehicle_coords.left   = v->left_coord;
    01592   _old_vehicle_coords.top    = v->top_coord;
    01593   _old_vehicle_coords.right  = v->right_coord;
    01594   _old_vehicle_coords.bottom = v->bottom_coord;
    01595 }
    01596
    01603 void EndVehicleMove(const Vehicle *v)
    01604 {
    01605   MarkAllViewportsDirty(
    01606     min(_old_vehicle_coords.left,   v->left_coord),
    01607     min(_old_vehicle_coords.top,    v->top_coord),
    01608     max(_old_vehicle_coords.right,  v->right_coord) + 1,
    01609     max(_old_vehicle_coords.bottom, v->bottom_coord) + 1
    01610   );
    01611 }
    01612
    01621 void MarkSingleVehicleDirty(const Vehicle *v)
    01622 {
    01623   MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1);
    01624 }
    01625
    01630 GetNewVehiclePosResult GetNewVehiclePos(const Vehicle *v)
    01631 {
    01632   static const int8 _delta_coord[16] = {
    01633     -1,-1,-1, 0, 1, 1, 1, 0, /* x */
    01634     -1, 0, 1, 1, 1, 0,-1,-1, /* y */
    01635   };
    01636
    01637   int x = v->x_pos + _delta_coord[v->direction];
    01638   int y = v->y_pos + _delta_coord[v->direction + 8];
    01639
    01640   GetNewVehiclePosResult gp;
    01641   gp.x = x;
    01642   gp.y = y;
    01643   gp.old_tile = v->tile;
    01644   gp.new_tile = TileVirtXY(x, y);
    01645   return gp;
    01646 }
    01647
    01648 static const Direction _new_direction_table[] = {
    01649   DIR_N , DIR_NW, DIR_W ,
    01650   DIR_NE, DIR_SE, DIR_SW,
    01651   DIR_E , DIR_SE, DIR_S
    01652 };
    01653
    01654 Direction GetDirectionTowards(const Vehicle *v, int x, int y)
    01655 {
    01656   int i = 0;
    01657
    01658   if (y >= v->y_pos) {
    01659     if (y != v->y_pos) i += 3;
    01660     i += 3;
    01661   }
    01662
    01663   if (x >= v->x_pos) {
    01664     if (x != v->x_pos) i++;
    01665     i++;
    01666   }
    01667
    01668   Direction dir = v->direction;
    01669
    01670   DirDiff dirdiff = DirDifference(_new_direction_table[i], dir);
    01671   if (dirdiff == DIRDIFF_SAME) return dir;
    01672   return ChangeDir(dir, dirdiff > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT);
    01673 }
    01674
    01675 Trackdir GetVehicleTrackdir(const Vehicle *v)
    01676 {
    01677   if (v->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
    01678
    01679   switch (v->type) {
    01680     case VEH_TRAIN:
    01681       if (v->u.rail.track == TRACK_BIT_DEPOT) // We'll assume the train is facing outwards
    01682         return DiagDirToDiagTrackdir(GetRailDepotDirection(v->tile)); // Train in depot
    01683
    01684       if (v->u.rail.track == TRACK_BIT_WORMHOLE) // train in tunnel or on bridge, so just use his direction and assume a diagonal track
    01685         return DiagDirToDiagTrackdir(DirToDiagDir(v->direction));
    01686
    01687       return TrackDirectionToTrackdir(FindFirstTrack(v->u.rail.track), v->direction);
    01688
    01689     case VEH_SHIP:
    01690       if (v->IsInDepot())
    01691         // We'll assume the ship is facing outwards
    01692         return DiagDirToDiagTrackdir(GetShipDepotDirection(v->tile));
    01693
    01694       if (v->u.ship.state == TRACK_BIT_WORMHOLE) // ship on aqueduct, so just use his direction and assume a diagonal track
    01695         return DiagDirToDiagTrackdir(DirToDiagDir(v->direction));
    01696
    01697       return TrackDirectionToTrackdir(FindFirstTrack(v->u.ship.state), v->direction);
    01698
    01699     case VEH_ROAD:
    01700       if (v->IsInDepot()) // We'll assume the road vehicle is facing outwards
    01701         return DiagDirToDiagTrackdir(GetRoadDepotDirection(v->tile));
    01702
    01703       if (IsStandardRoadStopTile(v->tile)) // We'll assume the road vehicle is facing outwards
    01704         return DiagDirToDiagTrackdir(GetRoadStopDir(v->tile)); // Road vehicle in a station
    01705
    01706       if (IsDriveThroughStopTile(v->tile)) return DiagDirToDiagTrackdir(DirToDiagDir(v->direction));
    01707
    01708       /* If vehicle's state is a valid track direction (vehicle is not turning around) return it */
    01709       if (!IsReversingRoadTrackdir((Trackdir)v->u.road.state)) return (Trackdir)v->u.road.state;
    01710
    01711       /* Vehicle is turning around, get the direction from vehicle's direction */
    01712       return DiagDirToDiagTrackdir(DirToDiagDir(v->direction));
    01713
    01714     /* case VEH_AIRCRAFT: case VEH_EFFECT: case VEH_DISASTER: */
    01715     default: return INVALID_TRACKDIR;
    01716   }
    01717 }
    01718
    01728 VehicleEnterTileStatus VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y)
    01729 {
    01730   return _tile_type_procs[GetTileType(tile)]->vehicle_enter_tile_proc(v, tile, x, y);
    01731 }
    01732
    01733 FreeUnitIDGenerator::FreeUnitIDGenerator(VehicleType type, CompanyID owner) : cache(NULL), maxid(0), curid(0)
    01734 {
    01735   /* Find maximum */
    01736   const Vehicle *v;
    01737   FOR_ALL_VEHICLES(v) {
    01738     if (v->type == type && v->owner == owner) {
    01739       this->maxid = max<UnitID>(this->maxid, v->unitnumber);
    01740     }
    01741   }
    01742
    01743   if (this->maxid == 0) return;
    01744
    01745   this->maxid++; // so there is space for last item (with v->unitnumber == maxid)
    01746   this->maxid++; // this one will always be free (well, it will fail when there are 65535 units, so this overflows)
    01747
    01748   this->cache = MallocT<bool>(this->maxid);
    01749
    01750   MemSetT(this->cache, 0, this->maxid);
    01751
    01752   /* Fill the cache */
    01753   FOR_ALL_VEHICLES(v) {
    01754     if (v->type == type && v->owner == owner) {
    01755       this->cache[v->unitnumber] = true;
    01756     }
    01757   }
    01758 }
    01759
    01760 UnitID FreeUnitIDGenerator::NextID()
    01761 {
    01762   if (this->maxid <= this->curid) return ++this->curid;
    01763
    01764   while (this->cache[++this->curid]) { } // it will stop, we reserved more space than needed
    01765
    01766   return this->curid;
    01767 }
    01768
    01769 UnitID GetFreeUnitNumber(VehicleType type)
    01770 {
    01771   FreeUnitIDGenerator gen(type, _current_company);
    01772
    01773   return gen.NextID();
    01774 }
    01775
    01776
    01785 bool CanBuildVehicleInfrastructure(VehicleType type)
    01786 {
    01787   assert(IsCompanyBuildableVehicleType(type));
    01788
    01789   if (!IsValidCompanyID(_local_company)) return false;
    01790   if (_settings_client.gui.always_build_infrastructure) return true;
    01791
    01792   UnitID max;
    01793   switch (type) {
    01794     case VEH_TRAIN:    max = _settings_game.vehicle.max_trains; break;
    01795     case VEH_ROAD:     max = _settings_game.vehicle.max_roadveh; break;
    01796     case VEH_SHIP:     max = _settings_game.vehicle.max_ships; break;
    01797     case VEH_AIRCRAFT: max = _settings_game.vehicle.max_aircraft; break;
    01798     default: NOT_REACHED();
    01799   }
    01800
    01801   /* We can build vehicle infrastructure when we may build the vehicle type */
    01802   if (max > 0) {
    01803     /* Can we actually build the vehicle type? */
    01804     const Engine *e;
    01805     FOR_ALL_ENGINES_OF_TYPE(e, type) {
    01806       if (HasBit(e->company_avail, _local_company)) return true;
    01807     }
    01808     return false;
    01809   }
    01810
    01811   /* We should be able to build infrastructure when we have the actual vehicle type */
    01812   const Vehicle *v;
    01813   FOR_ALL_VEHICLES(v) {
    01814     if (v->owner == _local_company && v->type == type) return true;
    01815   }
    01816
    01817   return false;
    01818 }
    01819
    01820
    01821 const Livery *GetEngineLivery(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v)
    01822 {
    01823   const Company *c = GetCompany(company);
    01824   LiveryScheme scheme = LS_DEFAULT;
    01825   CargoID cargo_type = v == NULL ? (CargoID)CT_INVALID : v->cargo_type;
    01826
    01827   /* The default livery is always available for use, but its in_use flag determines
    01828    * whether any _other_ liveries are in use. */
    01829   if (c->livery[LS_DEFAULT].in_use && (_settings_client.gui.liveries == 2 || (_settings_client.gui.liveries == 1 && company == _local_company))) {
    01830     /* Determine the livery scheme to use */
    01831     switch (GetEngine(engine_type)->type) {
    01832       default: NOT_REACHED();
    01833       case VEH_TRAIN: {
    01834         const RailVehicleInfo *rvi = RailVehInfo(engine_type);
    01835
    01836         if (cargo_type == CT_INVALID) cargo_type = rvi->cargo_type;
    01837         if (rvi->railveh_type == RAILVEH_WAGON) {
    01838           if (!GetCargo(cargo_type)->is_freight) {
    01839             if (parent_engine_type == INVALID_ENGINE) {
    01840               scheme = LS_PASSENGER_WAGON_STEAM;
    01841             } else {
    01842               switch (RailVehInfo(parent_engine_type)->engclass) {
    01843                 default: NOT_REACHED();
    01844                 case EC_STEAM:    scheme = LS_PASSENGER_WAGON_STEAM;    break;
    01845                 case EC_DIESEL:   scheme = LS_PASSENGER_WAGON_DIESEL;   break;
    01846                 case EC_ELECTRIC: scheme = LS_PASSENGER_WAGON_ELECTRIC; break;
    01847                 case EC_MONORAIL: scheme = LS_PASSENGER_WAGON_MONORAIL; break;
    01848                 case EC_MAGLEV:   scheme = LS_PASSENGER_WAGON_MAGLEV;   break;
    01849               }
    01850             }
    01851           } else {
    01852             scheme = LS_FREIGHT_WAGON;
    01853           }
    01854         } else {
    01855           bool is_mu = HasBit(EngInfo(engine_type)->misc_flags, EF_RAIL_IS_MU);
    01856
    01857           switch (rvi->engclass) {
    01858             default: NOT_REACHED();
    01859             case EC_STEAM:    scheme = LS_STEAM; break;
    01860             case EC_DIESEL:   scheme = is_mu ? LS_DMU : LS_DIESEL;   break;
    01861             case EC_ELECTRIC: scheme = is_mu ? LS_EMU : LS_ELECTRIC; break;
    01862             case EC_MONORAIL: scheme = LS_MONORAIL; break;
    01863             case EC_MAGLEV:   scheme = LS_MAGLEV; break;
    01864           }
    01865         }
    01866         break;
    01867       }
    01868
    01869       case VEH_ROAD: {
    01870         const RoadVehicleInfo *rvi = RoadVehInfo(engine_type);
    01871         if (cargo_type == CT_INVALID) cargo_type = rvi->cargo_type;
    01872         if (HasBit(EngInfo(engine_type)->misc_flags, EF_ROAD_TRAM)) {
    01873           /* Tram */
    01874           scheme = IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_TRAM : LS_FREIGHT_TRAM;
    01875         } else {
    01876           /* Bus or truck */
    01877           scheme = IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_BUS : LS_TRUCK;
    01878         }
    01879         break;
    01880       }
    01881
    01882       case VEH_SHIP: {
    01883         const ShipVehicleInfo *svi = ShipVehInfo(engine_type);
    01884         if (cargo_type == CT_INVALID) cargo_type = svi->cargo_type;
    01885         scheme = IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_SHIP : LS_FREIGHT_SHIP;
    01886         break;
    01887       }
    01888
    01889       case VEH_AIRCRAFT: {
    01890         const AircraftVehicleInfo *avi = AircraftVehInfo(engine_type);
    01891         if (cargo_type == CT_INVALID) cargo_type = CT_PASSENGERS;
    01892         switch (avi->subtype) {
    01893           case AIR_HELI: scheme = LS_HELICOPTER; break;
    01894           case AIR_CTOL: scheme = LS_SMALL_PLANE; break;
    01895           case AIR_CTOL | AIR_FAST: scheme = LS_LARGE_PLANE; break;
    01896         }
    01897         break;
    01898       }
    01899     }
    01900
    01901     /* Switch back to the default scheme if the resolved scheme is not in use */
    01902     if (!c->livery[scheme].in_use) scheme = LS_DEFAULT;
    01903   }
    01904
    01905   return &c->livery[scheme];
    01906 }
    01907
    01908
    01909 static SpriteID GetEngineColourMap(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v)
    01910 {
    01911   SpriteID map = (v != NULL) ? v->colourmap : PAL_NONE;
    01912
    01913   /* Return cached value if any */
    01914   if (map != PAL_NONE) return map;
    01915
    01916   /* Check if we should use the colour map callback */
    01917   if (HasBit(EngInfo(engine_type)->callbackmask, CBM_VEHICLE_COLOUR_REMAP)) {
    01918     uint16 callback = GetVehicleCallback(CBID_VEHICLE_COLOUR_MAPPING, 0, 0, engine_type, v);
    01919     /* A return value of 0xC000 is stated to "use the default two-colour
    01920      * maps" which happens to be the failure action too... */
    01921     if (callback != CALLBACK_FAILED && callback != 0xC000) {
    01922       map = GB(callback, 0, 14);
    01923       /* If bit 14 is set, then the company colours are applied to the
    01924        * map else it's returned as-is. */
    01925       if (!HasBit(callback, 14)) {
    01926         /* Update cache */
    01927         if (v != NULL) ((Vehicle*)v)->colourmap = map;
    01928         return map;
    01929       }
    01930     }
    01931   }
    01932
    01933   bool twocc = HasBit(EngInfo(engine_type)->misc_flags, EF_USES_2CC);
    01934
    01935   if (map == PAL_NONE) map = twocc ? (SpriteID)SPR_2CCMAP_BASE : (SpriteID)PALETTE_RECOLOUR_START;
    01936
    01937   const Livery *livery = GetEngineLivery(engine_type, company, parent_engine_type, v);
    01938
    01939   map += livery->colour1;
    01940   if (twocc) map += livery->colour2 * 16;
    01941
    01942   /* Update cache */
    01943   if (v != NULL) ((Vehicle*)v)->colourmap = map;
    01944   return map;
    01945 }
    01946
    01947 SpriteID GetEnginePalette(EngineID engine_type, CompanyID company)
    01948 {
    01949   return GetEngineColourMap(engine_type, company, INVALID_ENGINE, NULL);
    01950 }
    01951
    01952 SpriteID GetVehiclePalette(const Vehicle *v)
    01953 {
    01954   if (v->type == VEH_TRAIN) {
    01955     return GetEngineColourMap(
    01956       (v->u.rail.first_engine != INVALID_ENGINE && (UsesWagonOverride(v) || (IsArticulatedPart(v) && RailVehInfo(v->engine_type)->railveh_type != RAILVEH_WAGON))) ?
    01957         v->u.rail.first_engine : v->engine_type,
    01958       v->owner, v->u.rail.first_engine, v);
    01959   }
    01960
    01961   return GetEngineColourMap(v->engine_type, v->owner, INVALID_ENGINE, v);
    01962 }
    01963
    01964
    01965 void Vehicle::BeginLoading()
    01966 {
    01967   assert(IsTileType(tile, MP_STATION) || type == VEH_SHIP);
    01968
    01969   if (this->current_order.IsType(OT_GOTO_STATION) &&
    01970       this->current_order.GetDestination() == this->last_station_visited) {
    01971     current_order.MakeLoading(true);
    01972     UpdateVehicleTimetable(this, true);
    01973
    01974     /* Furthermore add the Non Stop flag to mark that this station
    01975      * is the actual destination of the vehicle, which is (for example)
    01976      * necessary to be known for HandleTrainLoading to determine
    01977      * whether the train is lost or not; not marking a train lost
    01978      * that arrives at random stations is bad. */
    01979     this->current_order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION);
    01980
    01981   } else {
    01982     current_order.MakeLoading(false);
    01983   }
    01984
    01985   GetStation(this->last_station_visited)->loading_vehicles.push_back(this);
    01986
    01987   VehiclePayment(this);
    01988
    01989   InvalidateWindow(GetWindowClassForVehicleType(this->type), this->owner);
    01990   InvalidateWindowWidget(WC_VEHICLE_VIEW, this->index, VVW_WIDGET_START_STOP_VEH);
    01991   InvalidateWindow(WC_VEHICLE_DETAILS, this->index);
    01992   InvalidateWindow(WC_STATION_VIEW, this->last_station_visited);
    01993
    01994   GetStation(this->last_station_visited)->MarkTilesDirty(true);
    01995   this->MarkDirty();
    01996 }
    01997
    01998 void Vehicle::LeaveStation()
    01999 {
    02000   assert(current_order.IsType(OT_LOADING));
    02001
    02002   /* Only update the timetable if the vehicle was supposed to stop here. */
    02003   if (current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE) UpdateVehicleTimetable(this, false);
    02004
    02005   current_order.MakeLeaveStation();
    02006   Station *st = GetStation(this->last_station_visited);
    02007   st->loading_vehicles.remove(this);
    02008
    02009   HideFillingPercent(&this->fill_percent_te_id);
    02010
    02011   if (this->type == VEH_TRAIN) {
    02012     /* Trigger station animation (trains only) */
    02013     if (IsTileType(this->tile, MP_STATION)) StationAnimationTrigger(st, this->tile, STAT_ANIM_TRAIN_DEPARTS);
    02014
    02015     /* Try to reserve a path when leaving the station as we
    02016      * might not be marked as wanting a reservation, e.g.
    02017      * when an overlength train gets turned around in a station. */
    02018     if (UpdateSignalsOnSegment(this->tile, TrackdirToExitdir(GetVehicleTrackdir(this)), this->owner) == SIGSEG_PBS || _settings_game.pf.reserve_paths) {
    02019       TryPathReserve(this, true, true);
    02020     }
    02021   }
    02022 }
    02023
    02024
    02025 void Vehicle::HandleLoading(bool mode)
    02026 {
    02027   switch (this->current_order.GetType()) {
    02028     case OT_LOADING: {
    02029       uint wait_time = max(this->current_order.wait_time - this->lateness_counter, 0);
    02030
    02031       /* Not the first call for this tick, or still loading */
    02032       if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) ||
    02033           (_settings_game.order.timetabling && this->current_order_time < wait_time)) return;
    02034
    02035       this->PlayLeaveStationSound();
    02036
    02037       bool at_destination_station = this->current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE;
    02038       this->LeaveStation();
    02039
    02040       /* If this was not the final order, don't remove it from the list. */
    02041       if (!at_destination_station) return;
    02042       break;
    02043     }
    02044
    02045     case OT_DUMMY: break;
    02046
    02047     default: return;
    02048   }
    02049
    02050   this->cur_order_index++;
    02051   InvalidateVehicleOrder(this, 0);
    02052 }
    02053
    02054 CommandCost Vehicle::SendToDepot(DoCommandFlag flags, DepotCommand command)
    02055 {
    02056   if (!CheckOwnership(this->owner)) return CMD_ERROR;
    02057   if (this->vehstatus & VS_CRASHED) return CMD_ERROR;
    02058   if (this->IsStoppedInDepot()) return CMD_ERROR;
    02059
    02060   if (this->current_order.IsType(OT_GOTO_DEPOT)) {
    02061     bool halt_in_depot = this->current_order.GetDepotActionType() & ODATFB_HALT;
    02062     if (!!(command & DEPOT_SERVICE) == halt_in_depot) {
    02063       /* We called with a different DEPOT_SERVICE setting.
    02064        * Now we change the setting to apply the new one and let the vehicle head for the same depot.
    02065        * Note: the if is (true for requesting service == true for ordered to stop in depot)          */
    02066       if (flags & DC_EXEC) {
    02067         this->current_order.SetDepotOrderType(ODTF_MANUAL);
    02068         this->current_order.SetDepotActionType(halt_in_depot ? ODATF_SERVICE_ONLY : ODATFB_HALT);
    02069         InvalidateWindowWidget(WC_VEHICLE_VIEW, this->index, VVW_WIDGET_START_STOP_VEH);
    02070       }
    02071       return CommandCost();
    02072     }
    02073
    02074     if (command & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders
    02075     if (flags & DC_EXEC) {
    02076       /* If the orders to 'goto depot' are in the orders list (forced servicing),
    02077        * then skip to the next order; effectively cancelling this forced service */
    02078       if (this->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) this->cur_order_index++;
    02079
    02080       this->current_order.MakeDummy();
    02081       InvalidateWindowWidget(WC_VEHICLE_VIEW, this->index, VVW_WIDGET_START_STOP_VEH);
    02082     }
    02083     return CommandCost();
    02084   }
    02085
    02086   TileIndex location;
    02087   DestinationID destination;
    02088   bool reverse;
    02089   static const StringID no_depot[] = {STR_883A_UNABLE_TO_FIND_ROUTE_TO, STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT, STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT, STR_A012_CAN_T_SEND_AIRCRAFT_TO};
    02090   if (!this->FindClosestDepot(&location, &destination, &reverse)) return_cmd_error(no_depot[this->type]);
    02091
    02092   if (flags & DC_EXEC) {
    02093     if (this->current_order.IsType(OT_LOADING)) this->LeaveStation();
    02094
    02095     this->dest_tile = location;
    02096     this->current_order.MakeGoToDepot(destination, ODTF_MANUAL);
    02097     if (!(command & DEPOT_SERVICE)) this->current_order.SetDepotActionType(ODATFB_HALT);
    02098     InvalidateWindowWidget(WC_VEHICLE_VIEW, this->index, VVW_WIDGET_START_STOP_VEH);
    02099
    02100     /* If there is no depot in front, reverse automatically (trains only) */
    02101     if (this->type == VEH_TRAIN && reverse) DoCommand(this->tile, this->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
    02102
    02103     if (this->type == VEH_AIRCRAFT && this->u.air.state == FLYING && this->u.air.targetairport != destination) {
    02104       /* The aircraft is now heading for a different hangar than the next in the orders */
    02105       extern void AircraftNextAirportPos_and_Order(Vehicle *v);
    02106       AircraftNextAirportPos_and_Order(this);
    02107     }
    02108   }
    02109
    02110   return CommandCost();
    02111
    02112 }
    02113
    02114 void Vehicle::SetNext(Vehicle *next)
    02115 {
    02116   if (this->next != NULL) {
    02117     /* We had an old next vehicle. Update the first and previous pointers */
    02118     for (Vehicle *v = this->next; v != NULL; v = v->Next()) {
    02119       v->first = this->next;
    02120     }
    02121     this->next->previous = NULL;
    02122   }
    02123
    02124   this->next = next;
    02125
    02126   if (this->next != NULL) {
    02127     /* A new next vehicle. Update the first and previous pointers */
    02128     if (this->next->previous != NULL) this->next->previous->next = NULL;
    02129     this->next->previous = this;
    02130     for (Vehicle *v = this->next; v != NULL; v = v->Next()) {
    02131       v->first = this->first;
    02132     }
    02133   }
    02134 }
    02135
    02136 void Vehicle::AddToShared(Vehicle *shared_chain)
    02137 {
    02138   assert(this->previous_shared == NULL && this->next_shared == NULL);
    02139
    02140   if (!shared_chain->orders.list) {
    02141     assert(shared_chain->previous_shared == NULL);
    02142     assert(shared_chain->next_shared == NULL);
    02143     this->orders.list = shared_chain->orders.list = new OrderList(NULL, shared_chain);
    02144   }
    02145
    02146   this->next_shared     = shared_chain->next_shared;
    02147   this->previous_shared = shared_chain;
    02148
    02149   shared_chain->next_shared = this;
    02150
    02151   if (this->next_shared != NULL) this->next_shared->previous_shared = this;
    02152
    02153   shared_chain->orders.list->AddVehicle(this);
    02154 }
    02155
    02156 void Vehicle::RemoveFromShared()
    02157 {
    02158   /* Remember if we were first and the old window number before RemoveVehicle()
    02159    * as this changes first if needed. */
    02160   bool were_first = (this->FirstShared() == this);
    02161   uint32 old_window_number = (this->FirstShared()->index << 16) | (this->type << 11) | VLW_SHARED_ORDERS | this->owner;
    02162
    02163   this->orders.list->RemoveVehicle(this);
    02164
    02165   if (!were_first) {
    02166     /* We are not the first shared one, so only relink our previous one. */
    02167     this->previous_shared->next_shared = this->NextShared();
    02168   }
    02169
    02170   if (this->next_shared != NULL) this->next_shared->previous_shared = this->previous_shared;
    02171
    02172
    02173   if (this->orders.list->GetNumVehicles() == 1) {
    02174     /* When there is only one vehicle, remove the shared order list window. */
    02175     DeleteWindowById(GetWindowClassForVehicleType(this->type), old_window_number);
    02176     InvalidateVehicleOrder(this->FirstShared(), 0);
    02177   } else if (were_first) {
    02178     /* If we were the first one, update to the new first one.
    02179      * Note: FirstShared() is already the new first */
    02180     InvalidateWindowData(GetWindowClassForVehicleType(this->type), old_window_number, (this->FirstShared()->index << 16) | (1 << 15));
    02181   }
    02182
    02183   this->next_shared     = NULL;
    02184   this->previous_shared = NULL;
    02185 }
    02186
    02187 void StopAllVehicles()
    02188 {
    02189   Vehicle *v;
    02190   FOR_ALL_VEHICLES(v) {
    02191     /* Code ripped from CmdStartStopTrain. Can't call it, because of
    02192      * ownership problems, so we'll duplicate some code, for now */
    02193     v->vehstatus |= VS_STOPPED;
    02194     InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
    02195     InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
    02196   }
    02197 }
    02198
    02199 void VehiclesYearlyLoop()
    02200 {
    02201   Vehicle *v;
    02202   FOR_ALL_VEHICLES(v) {
    02203     if (v->IsPrimaryVehicle()) {
    02204       /* show warning if vehicle is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */
    02205       Money profit = v->GetDisplayProfitThisYear();
    02206       if (v->age >= 730 && profit < 0) {
    02207         if (_settings_client.gui.vehicle_income_warn && v->owner == _local_company) {
    02208           SetDParam(0, v->index);
    02209           SetDParam(1, profit);
    02210           AddNewsItem(
    02211             STR_VEHICLE_IS_UNPROFITABLE,
    02212             NS_ADVICE,
    02213             v->index,
    02214             0);
    02215         }
    02216         AI::NewEvent(v->owner, new AIEventVehicleUnprofitable(v->index));
    02217       }
    02218
    02219       v->profit_last_year = v->profit_this_year;
    02220       v->profit_this_year = 0;
    02221       InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
    02222     }
    02223   }
    02224 }
    02225
    02226
    02236 bool CanVehicleUseStation(EngineID engine_type, const Station *st)
    02237 {
    02238   assert(IsEngineIndex(engine_type));
    02239   const Engine *e = GetEngine(engine_type);
    02240
    02241   switch (e->type) {
    02242     case VEH_TRAIN:
    02243       return (st->facilities & FACIL_TRAIN) != 0;
    02244
    02245     case VEH_ROAD:
    02246       /* For road vehicles we need the vehicle to know whether it can actually
    02247        * use the station, but if it doesn't have facilities for RVs it is
    02248        * certainly not possible that the station can be used. */
    02249       return (st->facilities & (FACIL_BUS_STOP | FACIL_TRUCK_STOP)) != 0;
    02250
    02251     case VEH_SHIP:
    02252       return (st->facilities & FACIL_DOCK) != 0;
    02253
    02254     case VEH_AIRCRAFT:
    02255       return (st->facilities & FACIL_AIRPORT) != 0 &&
    02256           (st->Airport()->flags & (e->u.air.subtype & AIR_CTOL ? AirportFTAClass::AIRPLANES : AirportFTAClass::HELICOPTERS)) != 0;
    02257
    02258     default:
    02259       return false;
    02260   }
    02261 }
    02262
    02269 bool CanVehicleUseStation(const Vehicle *v, const Station *st)
    02270 {
    02271   if (v->type == VEH_ROAD) return st->GetPrimaryRoadStop(v) != NULL;
    02272
    02273   return CanVehicleUseStation(v->engine_type, st);
    02274 }