roadveh_cmd.cpp

Go to the documentation of this file.
00001 /* $Id: roadveh_cmd.cpp 26180 2013-12-25 11:37:10Z frosch $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "stdafx.h"
00013 #include "roadveh.h"
00014 #include "command_func.h"
00015 #include "news_func.h"
00016 #include "pathfinder/npf/npf_func.h"
00017 #include "station_base.h"
00018 #include "company_func.h"
00019 #include "articulated_vehicles.h"
00020 #include "newgrf_sound.h"
00021 #include "pathfinder/yapf/yapf.h"
00022 #include "strings_func.h"
00023 #include "tunnelbridge_map.h"
00024 #include "date_func.h"
00025 #include "vehicle_func.h"
00026 #include "sound_func.h"
00027 #include "ai/ai.hpp"
00028 #include "game/game.hpp"
00029 #include "depot_map.h"
00030 #include "effectvehicle_func.h"
00031 #include "roadstop_base.h"
00032 #include "spritecache.h"
00033 #include "core/random_func.hpp"
00034 #include "company_base.h"
00035 #include "core/backup_type.hpp"
00036 #include "newgrf.h"
00037 #include "zoom_func.h"
00038 
00039 #include "table/strings.h"
00040 
00041 static const uint16 _roadveh_images[] = {
00042   0xCD4, 0xCDC, 0xCE4, 0xCEC, 0xCF4, 0xCFC, 0xD0C, 0xD14,
00043   0xD24, 0xD1C, 0xD2C, 0xD04, 0xD1C, 0xD24, 0xD6C, 0xD74,
00044   0xD7C, 0xC14, 0xC1C, 0xC24, 0xC2C, 0xC34, 0xC3C, 0xC4C,
00045   0xC54, 0xC64, 0xC5C, 0xC6C, 0xC44, 0xC5C, 0xC64, 0xCAC,
00046   0xCB4, 0xCBC, 0xD94, 0xD9C, 0xDA4, 0xDAC, 0xDB4, 0xDBC,
00047   0xDCC, 0xDD4, 0xDE4, 0xDDC, 0xDEC, 0xDC4, 0xDDC, 0xDE4,
00048   0xE2C, 0xE34, 0xE3C, 0xC14, 0xC1C, 0xC2C, 0xC3C, 0xC4C,
00049   0xC5C, 0xC64, 0xC6C, 0xC74, 0xC84, 0xC94, 0xCA4
00050 };
00051 
00052 static const uint16 _roadveh_full_adder[] = {
00053    0,  88,   0,   0,   0,   0,  48,  48,
00054   48,  48,   0,   0,  64,  64,   0,  16,
00055   16,   0,  88,   0,   0,   0,   0,  48,
00056   48,  48,  48,   0,   0,  64,  64,   0,
00057   16,  16,   0,  88,   0,   0,   0,   0,
00058   48,  48,  48,  48,   0,   0,  64,  64,
00059    0,  16,  16,   0,   8,   8,   8,   8,
00060    0,   0,   0,   8,   8,   8,   8
00061 };
00062 assert_compile(lengthof(_roadveh_images) == lengthof(_roadveh_full_adder));
00063 
00064 template <>
00065 bool IsValidImageIndex<VEH_ROAD>(uint8 image_index)
00066 {
00067   return image_index < lengthof(_roadveh_images);
00068 }
00069 
00071 static const TrackdirBits _road_enter_dir_to_reachable_trackdirs[DIAGDIR_END] = {
00072   TRACKDIR_BIT_LEFT_N  | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_X_NE,    // Enter from north east
00073   TRACKDIR_BIT_LEFT_S  | TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_Y_SE,    // Enter from south east
00074   TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_X_SW    | TRACKDIR_BIT_RIGHT_S, // Enter from south west
00075   TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_Y_NW     // Enter from north west
00076 };
00077 
00078 static const Trackdir _road_reverse_table[DIAGDIR_END] = {
00079   TRACKDIR_RVREV_NE, TRACKDIR_RVREV_SE, TRACKDIR_RVREV_SW, TRACKDIR_RVREV_NW
00080 };
00081 
00083 static const Trackdir _roadveh_depot_exit_trackdir[DIAGDIR_END] = {
00084   TRACKDIR_X_NE, TRACKDIR_Y_SE, TRACKDIR_X_SW, TRACKDIR_Y_NW
00085 };
00086 
00087 
00092 bool RoadVehicle::IsBus() const
00093 {
00094   assert(this->IsFrontEngine());
00095   return IsCargoInClass(this->cargo_type, CC_PASSENGERS);
00096 }
00097 
00103 int RoadVehicle::GetDisplayImageWidth(Point *offset) const
00104 {
00105   int reference_width = ROADVEHINFO_DEFAULT_VEHICLE_WIDTH;
00106 
00107   if (offset != NULL) {
00108     offset->x = reference_width / 2;
00109     offset->y = 0;
00110   }
00111   return this->gcache.cached_veh_length * reference_width / VEHICLE_LENGTH;
00112 }
00113 
00114 static SpriteID GetRoadVehIcon(EngineID engine, EngineImageType image_type)
00115 {
00116   const Engine *e = Engine::Get(engine);
00117   uint8 spritenum = e->u.road.image_index;
00118 
00119   if (is_custom_sprite(spritenum)) {
00120     SpriteID sprite = GetCustomVehicleIcon(engine, DIR_W, image_type);
00121     if (sprite != 0) return sprite;
00122 
00123     spritenum = e->original_image_index;
00124   }
00125 
00126   assert(IsValidImageIndex<VEH_ROAD>(spritenum));
00127   return DIR_W + _roadveh_images[spritenum];
00128 }
00129 
00130 SpriteID RoadVehicle::GetImage(Direction direction, EngineImageType image_type) const
00131 {
00132   uint8 spritenum = this->spritenum;
00133   SpriteID sprite;
00134 
00135   if (is_custom_sprite(spritenum)) {
00136     sprite = GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)), image_type);
00137     if (sprite != 0) return sprite;
00138 
00139     spritenum = this->GetEngine()->original_image_index;
00140   }
00141 
00142   assert(IsValidImageIndex<VEH_ROAD>(spritenum));
00143   sprite = direction + _roadveh_images[spritenum];
00144 
00145   if (this->cargo.StoredCount() >= this->cargo_cap / 2U) sprite += _roadveh_full_adder[spritenum];
00146 
00147   return sprite;
00148 }
00149 
00159 void DrawRoadVehEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
00160 {
00161   SpriteID sprite = GetRoadVehIcon(engine, image_type);
00162   const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
00163   preferred_x = Clamp(preferred_x, left - UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI), right - UnScaleByZoom(real_sprite->width, ZOOM_LVL_GUI) - UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI));
00164   DrawSprite(sprite, pal, preferred_x, y);
00165 }
00166 
00176 void GetRoadVehSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
00177 {
00178   const Sprite *spr = GetSprite(GetRoadVehIcon(engine, image_type), ST_NORMAL);
00179 
00180   width  = UnScaleByZoom(spr->width, ZOOM_LVL_GUI);
00181   height = UnScaleByZoom(spr->height, ZOOM_LVL_GUI);
00182   xoffs  = UnScaleByZoom(spr->x_offs, ZOOM_LVL_GUI);
00183   yoffs  = UnScaleByZoom(spr->y_offs, ZOOM_LVL_GUI);
00184 }
00185 
00191 static uint GetRoadVehLength(const RoadVehicle *v)
00192 {
00193   const Engine *e = v->GetEngine();
00194   uint length = VEHICLE_LENGTH;
00195 
00196   uint16 veh_len = CALLBACK_FAILED;
00197   if (e->GetGRF() != NULL && e->GetGRF()->grf_version >= 8) {
00198     /* Use callback 36 */
00199     veh_len = GetVehicleProperty(v, PROP_ROADVEH_SHORTEN_FACTOR, CALLBACK_FAILED);
00200     if (veh_len != CALLBACK_FAILED && veh_len >= VEHICLE_LENGTH) ErrorUnknownCallbackResult(e->GetGRFID(), CBID_VEHICLE_LENGTH, veh_len);
00201   } else {
00202     /* Use callback 11 */
00203     veh_len = GetVehicleCallback(CBID_VEHICLE_LENGTH, 0, 0, v->engine_type, v);
00204   }
00205   if (veh_len == CALLBACK_FAILED) veh_len = e->u.road.shorten_factor;
00206   if (veh_len != 0) {
00207     length -= Clamp(veh_len, 0, VEHICLE_LENGTH - 1);
00208   }
00209 
00210   return length;
00211 }
00212 
00219 void RoadVehUpdateCache(RoadVehicle *v, bool same_length)
00220 {
00221   assert(v->type == VEH_ROAD);
00222   assert(v->IsFrontEngine());
00223 
00224   v->InvalidateNewGRFCacheOfChain();
00225 
00226   v->gcache.cached_total_length = 0;
00227 
00228   for (RoadVehicle *u = v; u != NULL; u = u->Next()) {
00229     /* Check the v->first cache. */
00230     assert(u->First() == v);
00231 
00232     /* Update the 'first engine' */
00233     u->gcache.first_engine = (v == u) ? INVALID_ENGINE : v->engine_type;
00234 
00235     /* Update the length of the vehicle. */
00236     uint veh_len = GetRoadVehLength(u);
00237     /* Verify length hasn't changed. */
00238     if (same_length && veh_len != u->gcache.cached_veh_length) VehicleLengthChanged(u);
00239 
00240     u->gcache.cached_veh_length = veh_len;
00241     v->gcache.cached_total_length += u->gcache.cached_veh_length;
00242 
00243     /* Update visual effect */
00244     u->UpdateVisualEffect();
00245 
00246     /* Update cargo aging period. */
00247     u->vcache.cached_cargo_age_period = GetVehicleProperty(u, PROP_ROADVEH_CARGO_AGE_PERIOD, EngInfo(u->engine_type)->cargo_age_period);
00248   }
00249 
00250   uint max_speed = GetVehicleProperty(v, PROP_ROADVEH_SPEED, 0);
00251   v->vcache.cached_max_speed = (max_speed != 0) ? max_speed * 4 : RoadVehInfo(v->engine_type)->max_speed;
00252 }
00253 
00263 CommandCost CmdBuildRoadVehicle(TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **ret)
00264 {
00265   if (HasTileRoadType(tile, ROADTYPE_TRAM) != HasBit(e->info.misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_ERROR_DEPOT_WRONG_DEPOT_TYPE);
00266 
00267   if (flags & DC_EXEC) {
00268     const RoadVehicleInfo *rvi = &e->u.road;
00269 
00270     RoadVehicle *v = new RoadVehicle();
00271     *ret = v;
00272     v->direction = DiagDirToDir(GetRoadDepotDirection(tile));
00273     v->owner = _current_company;
00274 
00275     v->tile = tile;
00276     int x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2;
00277     int y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2;
00278     v->x_pos = x;
00279     v->y_pos = y;
00280     v->z_pos = GetSlopePixelZ(x, y);
00281 
00282     v->state = RVSB_IN_DEPOT;
00283     v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
00284 
00285     v->spritenum = rvi->image_index;
00286     v->cargo_type = e->GetDefaultCargoType();
00287     v->cargo_cap = rvi->capacity;
00288     v->refit_cap = 0;
00289 
00290     v->last_station_visited = INVALID_STATION;
00291     v->last_loading_station = INVALID_STATION;
00292     v->engine_type = e->index;
00293     v->gcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
00294 
00295     v->reliability = e->reliability;
00296     v->reliability_spd_dec = e->reliability_spd_dec;
00297     v->max_age = e->GetLifeLengthInDays();
00298     _new_vehicle_id = v->index;
00299 
00300     v->SetServiceInterval(Company::Get(v->owner)->settings.vehicle.servint_roadveh);
00301 
00302     v->date_of_last_service = _date;
00303     v->build_year = _cur_year;
00304 
00305     v->cur_image = SPR_IMG_QUERY;
00306     v->random_bits = VehicleRandomBits();
00307     v->SetFrontEngine();
00308 
00309     v->roadtype = HasBit(e->info.misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
00310     v->compatible_roadtypes = RoadTypeToRoadTypes(v->roadtype);
00311     v->gcache.cached_veh_length = VEHICLE_LENGTH;
00312 
00313     if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
00314     v->SetServiceIntervalIsPercent(Company::Get(_current_company)->settings.vehicle.servint_ispercent);
00315 
00316     AddArticulatedParts(v);
00317     v->InvalidateNewGRFCacheOfChain();
00318 
00319     /* Call various callbacks after the whole consist has been constructed */
00320     for (RoadVehicle *u = v; u != NULL; u = u->Next()) {
00321       u->cargo_cap = u->GetEngine()->DetermineCapacity(u);
00322       u->refit_cap = 0;
00323       v->InvalidateNewGRFCache();
00324       u->InvalidateNewGRFCache();
00325     }
00326     RoadVehUpdateCache(v);
00327     /* Initialize cached values for realistic acceleration. */
00328     if (_settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL) v->CargoChanged();
00329 
00330     VehicleUpdatePosition(v);
00331 
00332     CheckConsistencyOfArticulatedVehicle(v);
00333   }
00334 
00335   return CommandCost();
00336 }
00337 
00338 static FindDepotData FindClosestRoadDepot(const RoadVehicle *v, int max_distance)
00339 {
00340   if (IsRoadDepotTile(v->tile)) return FindDepotData(v->tile, 0);
00341 
00342   switch (_settings_game.pf.pathfinder_for_roadvehs) {
00343     case VPF_NPF: return NPFRoadVehicleFindNearestDepot(v, max_distance);
00344     case VPF_YAPF: return YapfRoadVehicleFindNearestDepot(v, max_distance);
00345 
00346     default: NOT_REACHED();
00347   }
00348 }
00349 
00350 bool RoadVehicle::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
00351 {
00352   FindDepotData rfdd = FindClosestRoadDepot(this, 0);
00353   if (rfdd.best_length == UINT_MAX) return false;
00354 
00355   if (location    != NULL) *location    = rfdd.tile;
00356   if (destination != NULL) *destination = GetDepotIndex(rfdd.tile);
00357 
00358   return true;
00359 }
00360 
00370 CommandCost CmdTurnRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00371 {
00372   RoadVehicle *v = RoadVehicle::GetIfValid(p1);
00373   if (v == NULL) return CMD_ERROR;
00374 
00375   if (!v->IsPrimaryVehicle()) return CMD_ERROR;
00376 
00377   CommandCost ret = CheckOwnership(v->owner);
00378   if (ret.Failed()) return ret;
00379 
00380   if ((v->vehstatus & VS_STOPPED) ||
00381       (v->vehstatus & VS_CRASHED) ||
00382       v->breakdown_ctr != 0 ||
00383       v->overtaking != 0 ||
00384       v->state == RVSB_WORMHOLE ||
00385       v->IsInDepot() ||
00386       v->current_order.IsType(OT_LOADING)) {
00387     return CMD_ERROR;
00388   }
00389 
00390   if (IsNormalRoadTile(v->tile) && GetDisallowedRoadDirections(v->tile) != DRD_NONE) return CMD_ERROR;
00391 
00392   if (IsTileType(v->tile, MP_TUNNELBRIDGE) && DirToDiagDir(v->direction) == GetTunnelBridgeDirection(v->tile)) return CMD_ERROR;
00393 
00394   if (flags & DC_EXEC) v->reverse_ctr = 180;
00395 
00396   return CommandCost();
00397 }
00398 
00399 
00400 void RoadVehicle::MarkDirty()
00401 {
00402   for (RoadVehicle *v = this; v != NULL; v = v->Next()) {
00403     v->colourmap = PAL_NONE;
00404     v->UpdateViewport(true, false);
00405   }
00406   this->CargoChanged();
00407 }
00408 
00409 void RoadVehicle::UpdateDeltaXY(Direction direction)
00410 {
00411   static const int8 _delta_xy_table[8][10] = {
00412     /* y_extent, x_extent, y_offs, x_offs, y_bb_offs, x_bb_offs, y_extent_shorten, x_extent_shorten, y_bb_offs_shorten, x_bb_offs_shorten */
00413     {3, 3, -1, -1,  0,  0, -1, -1, -1, -1}, // N
00414     {3, 7, -1, -3,  0, -1,  0, -1,  0,  0}, // NE
00415     {3, 3, -1, -1,  0,  0,  1, -1,  1, -1}, // E
00416     {7, 3, -3, -1, -1,  0,  0,  0,  1,  0}, // SE
00417     {3, 3, -1, -1,  0,  0,  1,  1,  1,  1}, // S
00418     {3, 7, -1, -3,  0, -1,  0,  0,  0,  1}, // SW
00419     {3, 3, -1, -1,  0,  0, -1,  1, -1,  1}, // W
00420     {7, 3, -3, -1, -1,  0, -1,  0,  0,  0}, // NW
00421   };
00422 
00423   int shorten = VEHICLE_LENGTH - this->gcache.cached_veh_length;
00424   if (!IsDiagonalDirection(direction)) shorten >>= 1;
00425 
00426   const int8 *bb = _delta_xy_table[direction];
00427   this->x_bb_offs     = bb[5] + bb[9] * shorten;
00428   this->y_bb_offs     = bb[4] + bb[8] * shorten;;
00429   this->x_offs        = bb[3];
00430   this->y_offs        = bb[2];
00431   this->x_extent      = bb[1] + bb[7] * shorten;
00432   this->y_extent      = bb[0] + bb[6] * shorten;
00433   this->z_extent      = 6;
00434 }
00435 
00440 inline int RoadVehicle::GetCurrentMaxSpeed() const
00441 {
00442   int max_speed = this->vcache.cached_max_speed;
00443 
00444   /* Limit speed to 50% while reversing, 75% in curves. */
00445   for (const RoadVehicle *u = this; u != NULL; u = u->Next()) {
00446     if (_settings_game.vehicle.roadveh_acceleration_model == AM_REALISTIC) {
00447       if (this->state <= RVSB_TRACKDIR_MASK && IsReversingRoadTrackdir((Trackdir)this->state)) {
00448         max_speed = this->vcache.cached_max_speed / 2;
00449         break;
00450       } else if ((u->direction & 1) == 0) {
00451         max_speed = this->vcache.cached_max_speed * 3 / 4;
00452       }
00453     }
00454 
00455     /* Vehicle is on the middle part of a bridge. */
00456     if (u->state == RVSB_WORMHOLE && !(u->vehstatus & VS_HIDDEN)) {
00457       max_speed = min(max_speed, GetBridgeSpec(GetBridgeType(u->tile))->speed * 2);
00458     }
00459   }
00460 
00461   return min(max_speed, this->current_order.max_speed * 2);
00462 }
00463 
00468 static void DeleteLastRoadVeh(RoadVehicle *v)
00469 {
00470   RoadVehicle *first = v->First();
00471   Vehicle *u = v;
00472   for (; v->Next() != NULL; v = v->Next()) u = v;
00473   u->SetNext(NULL);
00474   v->last_station_visited = first->last_station_visited; // for PreDestructor
00475 
00476   /* Only leave the road stop when we're really gone. */
00477   if (IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v);
00478 
00479   delete v;
00480 }
00481 
00482 static void RoadVehSetRandomDirection(RoadVehicle *v)
00483 {
00484   static const DirDiff delta[] = {
00485     DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT
00486   };
00487 
00488   do {
00489     uint32 r = Random();
00490 
00491     v->direction = ChangeDir(v->direction, delta[r & 3]);
00492     v->UpdateViewport(true, true);
00493   } while ((v = v->Next()) != NULL);
00494 }
00495 
00501 static bool RoadVehIsCrashed(RoadVehicle *v)
00502 {
00503   v->crashed_ctr++;
00504   if (v->crashed_ctr == 2) {
00505     CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
00506   } else if (v->crashed_ctr <= 45) {
00507     if ((v->tick_counter & 7) == 0) RoadVehSetRandomDirection(v);
00508   } else if (v->crashed_ctr >= 2220 && !(v->tick_counter & 0x1F)) {
00509     bool ret = v->Next() != NULL;
00510     DeleteLastRoadVeh(v);
00511     return ret;
00512   }
00513 
00514   return true;
00515 }
00516 
00523 static Vehicle *EnumCheckRoadVehCrashTrain(Vehicle *v, void *data)
00524 {
00525   const Vehicle *u = (Vehicle*)data;
00526 
00527   return (v->type == VEH_TRAIN &&
00528       abs(v->z_pos - u->z_pos) <= 6 &&
00529       abs(v->x_pos - u->x_pos) <= 4 &&
00530       abs(v->y_pos - u->y_pos) <= 4) ? v : NULL;
00531 }
00532 
00533 uint RoadVehicle::Crash(bool flooded)
00534 {
00535   uint pass = this->GroundVehicleBase::Crash(flooded);
00536   if (this->IsFrontEngine()) {
00537     pass += 1; // driver
00538 
00539     /* If we're in a drive through road stop we ought to leave it */
00540     if (IsInsideMM(this->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END)) {
00541       RoadStop::GetByTile(this->tile, GetRoadStopType(this->tile))->Leave(this);
00542     }
00543   }
00544   this->crashed_ctr = flooded ? 2000 : 1; // max 2220, disappear pretty fast when flooded
00545   return pass;
00546 }
00547 
00548 static void RoadVehCrash(RoadVehicle *v)
00549 {
00550   uint pass = v->Crash();
00551 
00552   AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING));
00553   Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING));
00554 
00555   SetDParam(0, pass);
00556   AddVehicleNewsItem(
00557     (pass == 1) ?
00558       STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER : STR_NEWS_ROAD_VEHICLE_CRASH,
00559     NT_ACCIDENT,
00560     v->index
00561   );
00562 
00563   ModifyStationRatingAround(v->tile, v->owner, -160, 22);
00564   if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
00565 }
00566 
00567 static bool RoadVehCheckTrainCrash(RoadVehicle *v)
00568 {
00569   for (RoadVehicle *u = v; u != NULL; u = u->Next()) {
00570     if (u->state == RVSB_WORMHOLE) continue;
00571 
00572     TileIndex tile = u->tile;
00573 
00574     if (!IsLevelCrossingTile(tile)) continue;
00575 
00576     if (HasVehicleOnPosXY(v->x_pos, v->y_pos, u, EnumCheckRoadVehCrashTrain)) {
00577       RoadVehCrash(v);
00578       return true;
00579     }
00580   }
00581 
00582   return false;
00583 }
00584 
00585 TileIndex RoadVehicle::GetOrderStationLocation(StationID station)
00586 {
00587   if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
00588 
00589   const Station *st = Station::Get(station);
00590   if (!CanVehicleUseStation(this, st)) {
00591     /* There is no stop left at the station, so don't even TRY to go there */
00592     this->IncrementRealOrderIndex();
00593     return 0;
00594   }
00595 
00596   return st->xy;
00597 }
00598 
00599 static void StartRoadVehSound(const RoadVehicle *v)
00600 {
00601   if (!PlayVehicleSound(v, VSE_START)) {
00602     SoundID s = RoadVehInfo(v->engine_type)->sfx;
00603     if (s == SND_19_BUS_START_PULL_AWAY && (v->tick_counter & 3) == 0) {
00604       s = SND_1A_BUS_START_PULL_AWAY_WITH_HORN;
00605     }
00606     SndPlayVehicleFx(s, v);
00607   }
00608 }
00609 
00610 struct RoadVehFindData {
00611   int x;
00612   int y;
00613   const Vehicle *veh;
00614   Vehicle *best;
00615   uint best_diff;
00616   Direction dir;
00617 };
00618 
00619 static Vehicle *EnumCheckRoadVehClose(Vehicle *v, void *data)
00620 {
00621   static const int8 dist_x[] = { -4, -8, -4, -1, 4, 8, 4, 1 };
00622   static const int8 dist_y[] = { -4, -1, 4, 8, 4, 1, -4, -8 };
00623 
00624   RoadVehFindData *rvf = (RoadVehFindData*)data;
00625 
00626   short x_diff = v->x_pos - rvf->x;
00627   short y_diff = v->y_pos - rvf->y;
00628 
00629   if (v->type == VEH_ROAD &&
00630       !v->IsInDepot() &&
00631       abs(v->z_pos - rvf->veh->z_pos) < 6 &&
00632       v->direction == rvf->dir &&
00633       rvf->veh->First() != v->First() &&
00634       (dist_x[v->direction] >= 0 || (x_diff > dist_x[v->direction] && x_diff <= 0)) &&
00635       (dist_x[v->direction] <= 0 || (x_diff < dist_x[v->direction] && x_diff >= 0)) &&
00636       (dist_y[v->direction] >= 0 || (y_diff > dist_y[v->direction] && y_diff <= 0)) &&
00637       (dist_y[v->direction] <= 0 || (y_diff < dist_y[v->direction] && y_diff >= 0))) {
00638     uint diff = abs(x_diff) + abs(y_diff);
00639 
00640     if (diff < rvf->best_diff || (diff == rvf->best_diff && v->index < rvf->best->index)) {
00641       rvf->best = v;
00642       rvf->best_diff = diff;
00643     }
00644   }
00645 
00646   return NULL;
00647 }
00648 
00649 static RoadVehicle *RoadVehFindCloseTo(RoadVehicle *v, int x, int y, Direction dir, bool update_blocked_ctr = true)
00650 {
00651   RoadVehFindData rvf;
00652   RoadVehicle *front = v->First();
00653 
00654   if (front->reverse_ctr != 0) return NULL;
00655 
00656   rvf.x = x;
00657   rvf.y = y;
00658   rvf.dir = dir;
00659   rvf.veh = v;
00660   rvf.best_diff = UINT_MAX;
00661 
00662   if (front->state == RVSB_WORMHOLE) {
00663     FindVehicleOnPos(v->tile, &rvf, EnumCheckRoadVehClose);
00664     FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), &rvf, EnumCheckRoadVehClose);
00665   } else {
00666     FindVehicleOnPosXY(x, y, &rvf, EnumCheckRoadVehClose);
00667   }
00668 
00669   /* This code protects a roadvehicle from being blocked for ever
00670    * If more than 1480 / 74 days a road vehicle is blocked, it will
00671    * drive just through it. The ultimate backup-code of TTD.
00672    * It can be disabled. */
00673   if (rvf.best_diff == UINT_MAX) {
00674     front->blocked_ctr = 0;
00675     return NULL;
00676   }
00677 
00678   if (update_blocked_ctr && ++front->blocked_ctr > 1480) return NULL;
00679 
00680   return RoadVehicle::From(rvf.best);
00681 }
00682 
00688 static void RoadVehArrivesAt(const RoadVehicle *v, Station *st)
00689 {
00690   if (v->IsBus()) {
00691     /* Check if station was ever visited before */
00692     if (!(st->had_vehicle_of_type & HVOT_BUS)) {
00693       st->had_vehicle_of_type |= HVOT_BUS;
00694       SetDParam(0, st->index);
00695       AddVehicleNewsItem(
00696         v->roadtype == ROADTYPE_ROAD ? STR_NEWS_FIRST_BUS_ARRIVAL : STR_NEWS_FIRST_PASSENGER_TRAM_ARRIVAL,
00697         (v->owner == _local_company) ? NT_ARRIVAL_COMPANY : NT_ARRIVAL_OTHER,
00698         v->index,
00699         st->index
00700       );
00701       AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
00702       Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
00703     }
00704   } else {
00705     /* Check if station was ever visited before */
00706     if (!(st->had_vehicle_of_type & HVOT_TRUCK)) {
00707       st->had_vehicle_of_type |= HVOT_TRUCK;
00708       SetDParam(0, st->index);
00709       AddVehicleNewsItem(
00710         v->roadtype == ROADTYPE_ROAD ? STR_NEWS_FIRST_TRUCK_ARRIVAL : STR_NEWS_FIRST_CARGO_TRAM_ARRIVAL,
00711         (v->owner == _local_company) ? NT_ARRIVAL_COMPANY : NT_ARRIVAL_OTHER,
00712         v->index,
00713         st->index
00714       );
00715       AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
00716       Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
00717     }
00718   }
00719 }
00720 
00728 int RoadVehicle::UpdateSpeed()
00729 {
00730   switch (_settings_game.vehicle.roadveh_acceleration_model) {
00731     default: NOT_REACHED();
00732     case AM_ORIGINAL:
00733       return this->DoUpdateSpeed(this->overtaking != 0 ? 512 : 256, 0, this->GetCurrentMaxSpeed());
00734 
00735     case AM_REALISTIC:
00736       return this->DoUpdateSpeed(this->GetAcceleration() + (this->overtaking != 0 ? 256 : 0), this->GetAccelerationStatus() == AS_BRAKE ? 0 : 4, this->GetCurrentMaxSpeed());
00737   }
00738 }
00739 
00740 static Direction RoadVehGetNewDirection(const RoadVehicle *v, int x, int y)
00741 {
00742   static const Direction _roadveh_new_dir[] = {
00743     DIR_N , DIR_NW, DIR_W , INVALID_DIR,
00744     DIR_NE, DIR_N , DIR_SW, INVALID_DIR,
00745     DIR_E , DIR_SE, DIR_S
00746   };
00747 
00748   x = x - v->x_pos + 1;
00749   y = y - v->y_pos + 1;
00750 
00751   if ((uint)x > 2 || (uint)y > 2) return v->direction;
00752   return _roadveh_new_dir[y * 4 + x];
00753 }
00754 
00755 static Direction RoadVehGetSlidingDirection(const RoadVehicle *v, int x, int y)
00756 {
00757   Direction new_dir = RoadVehGetNewDirection(v, x, y);
00758   Direction old_dir = v->direction;
00759   DirDiff delta;
00760 
00761   if (new_dir == old_dir) return old_dir;
00762   delta = (DirDifference(new_dir, old_dir) > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT);
00763   return ChangeDir(old_dir, delta);
00764 }
00765 
00766 struct OvertakeData {
00767   const RoadVehicle *u;
00768   const RoadVehicle *v;
00769   TileIndex tile;
00770   Trackdir trackdir;
00771 };
00772 
00773 static Vehicle *EnumFindVehBlockingOvertake(Vehicle *v, void *data)
00774 {
00775   const OvertakeData *od = (OvertakeData*)data;
00776 
00777   return (v->type == VEH_ROAD && v->First() == v && v != od->u && v != od->v) ? v : NULL;
00778 }
00779 
00786 static bool CheckRoadBlockedForOvertaking(OvertakeData *od)
00787 {
00788   TrackStatus ts = GetTileTrackStatus(od->tile, TRANSPORT_ROAD, od->v->compatible_roadtypes);
00789   TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts);
00790   TrackdirBits red_signals = TrackStatusToRedSignals(ts); // barred level crossing
00791   TrackBits trackbits = TrackdirBitsToTrackBits(trackdirbits);
00792 
00793   /* Track does not continue along overtaking direction || track has junction || levelcrossing is barred */
00794   if (!HasBit(trackdirbits, od->trackdir) || (trackbits & ~TRACK_BIT_CROSS) || (red_signals != TRACKDIR_BIT_NONE)) return true;
00795 
00796   /* Are there more vehicles on the tile except the two vehicles involved in overtaking */
00797   return HasVehicleOnPos(od->tile, od, EnumFindVehBlockingOvertake);
00798 }
00799 
00800 static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u)
00801 {
00802   OvertakeData od;
00803 
00804   od.v = v;
00805   od.u = u;
00806 
00807   if (u->vcache.cached_max_speed >= v->vcache.cached_max_speed &&
00808       !(u->vehstatus & VS_STOPPED) &&
00809       u->cur_speed != 0) {
00810     return;
00811   }
00812 
00813   /* Trams can't overtake other trams */
00814   if (v->roadtype == ROADTYPE_TRAM) return;
00815 
00816   /* Don't overtake in stations */
00817   if (IsTileType(v->tile, MP_STATION) || IsTileType(u->tile, MP_STATION)) return;
00818 
00819   /* For now, articulated road vehicles can't overtake anything. */
00820   if (v->HasArticulatedPart()) return;
00821 
00822   /* Vehicles are not driving in same direction || direction is not a diagonal direction */
00823   if (v->direction != u->direction || !(v->direction & 1)) return;
00824 
00825   /* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */
00826   if (v->state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->state & RVSB_TRACKDIR_MASK))) return;
00827 
00828   od.trackdir = DiagDirToDiagTrackdir(DirToDiagDir(v->direction));
00829 
00830   /* Are the current and the next tile suitable for overtaking?
00831    *  - Does the track continue along od.trackdir
00832    *  - No junctions
00833    *  - No barred levelcrossing
00834    *  - No other vehicles in the way
00835    */
00836   od.tile = v->tile;
00837   if (CheckRoadBlockedForOvertaking(&od)) return;
00838 
00839   od.tile = v->tile + TileOffsByDiagDir(DirToDiagDir(v->direction));
00840   if (CheckRoadBlockedForOvertaking(&od)) return;
00841 
00842   /* When the vehicle in front of us is stopped we may only take
00843    * half the time to pass it than when the vehicle is moving. */
00844   v->overtaking_ctr = (od.u->cur_speed == 0 || (od.u->vehstatus & VS_STOPPED)) ? RV_OVERTAKE_TIMEOUT / 2 : 0;
00845   v->overtaking = RVSB_DRIVE_SIDE;
00846 }
00847 
00848 static void RoadZPosAffectSpeed(RoadVehicle *v, byte old_z)
00849 {
00850   if (old_z == v->z_pos || _settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL) return;
00851 
00852   if (old_z < v->z_pos) {
00853     v->cur_speed = v->cur_speed * 232 / 256; // slow down by ~10%
00854   } else {
00855     uint16 spd = v->cur_speed + 2;
00856     if (spd <= v->vcache.cached_max_speed) v->cur_speed = spd;
00857   }
00858 }
00859 
00860 static int PickRandomBit(uint bits)
00861 {
00862   uint i;
00863   uint num = RandomRange(CountBits(bits));
00864 
00865   for (i = 0; !(bits & 1) || (int)--num >= 0; bits >>= 1, i++) {}
00866   return i;
00867 }
00868 
00877 static Trackdir RoadFindPathToDest(RoadVehicle *v, TileIndex tile, DiagDirection enterdir)
00878 {
00879 #define return_track(x) { best_track = (Trackdir)x; goto found_best_track; }
00880 
00881   TileIndex desttile;
00882   Trackdir best_track;
00883   bool path_found = true;
00884 
00885   TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_ROAD, v->compatible_roadtypes);
00886   TrackdirBits red_signals = TrackStatusToRedSignals(ts); // crossing
00887   TrackdirBits trackdirs = TrackStatusToTrackdirBits(ts);
00888 
00889   if (IsTileType(tile, MP_ROAD)) {
00890     if (IsRoadDepot(tile) && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir || (GetRoadTypes(tile) & v->compatible_roadtypes) == 0)) {
00891       /* Road depot owned by another company or with the wrong orientation */
00892       trackdirs = TRACKDIR_BIT_NONE;
00893     }
00894   } else if (IsTileType(tile, MP_STATION) && IsStandardRoadStopTile(tile)) {
00895     /* Standard road stop (drive-through stops are treated as normal road) */
00896 
00897     if (!IsTileOwner(tile, v->owner) || GetRoadStopDir(tile) == enterdir || v->HasArticulatedPart()) {
00898       /* different station owner or wrong orientation or the vehicle has articulated parts */
00899       trackdirs = TRACKDIR_BIT_NONE;
00900     } else {
00901       /* Our station */
00902       RoadStopType rstype = v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK;
00903 
00904       if (GetRoadStopType(tile) != rstype) {
00905         /* Wrong station type */
00906         trackdirs = TRACKDIR_BIT_NONE;
00907       } else {
00908         /* Proper station type, check if there is free loading bay */
00909         if (!_settings_game.pf.roadveh_queue && IsStandardRoadStopTile(tile) &&
00910             !RoadStop::GetByTile(tile, rstype)->HasFreeBay()) {
00911           /* Station is full and RV queuing is off */
00912           trackdirs = TRACKDIR_BIT_NONE;
00913         }
00914       }
00915     }
00916   }
00917   /* The above lookups should be moved to GetTileTrackStatus in the
00918    * future, but that requires more changes to the pathfinder and other
00919    * stuff, probably even more arguments to GTTS.
00920    */
00921 
00922   /* Remove tracks unreachable from the enter dir */
00923   trackdirs &= _road_enter_dir_to_reachable_trackdirs[enterdir];
00924   if (trackdirs == TRACKDIR_BIT_NONE) {
00925     /* No reachable tracks, so we'll reverse */
00926     return_track(_road_reverse_table[enterdir]);
00927   }
00928 
00929   if (v->reverse_ctr != 0) {
00930     bool reverse = true;
00931     if (v->roadtype == ROADTYPE_TRAM) {
00932       /* Trams may only reverse on a tile if it contains at least the straight
00933        * trackbits or when it is a valid turning tile (i.e. one roadbit) */
00934       RoadBits rb = GetAnyRoadBits(tile, ROADTYPE_TRAM);
00935       RoadBits straight = AxisToRoadBits(DiagDirToAxis(enterdir));
00936       reverse = ((rb & straight) == straight) ||
00937                 (rb == DiagDirToRoadBits(enterdir));
00938     }
00939     if (reverse) {
00940       v->reverse_ctr = 0;
00941       if (v->tile != tile) {
00942         return_track(_road_reverse_table[enterdir]);
00943       }
00944     }
00945   }
00946 
00947   desttile = v->dest_tile;
00948   if (desttile == 0) {
00949     /* We've got no destination, pick a random track */
00950     return_track(PickRandomBit(trackdirs));
00951   }
00952 
00953   /* Only one track to choose between? */
00954   if (KillFirstBit(trackdirs) == TRACKDIR_BIT_NONE) {
00955     return_track(FindFirstBit2x64(trackdirs));
00956   }
00957 
00958   switch (_settings_game.pf.pathfinder_for_roadvehs) {
00959     case VPF_NPF:  best_track = NPFRoadVehicleChooseTrack(v, tile, enterdir, trackdirs, path_found); break;
00960     case VPF_YAPF: best_track = YapfRoadVehicleChooseTrack(v, tile, enterdir, trackdirs, path_found); break;
00961 
00962     default: NOT_REACHED();
00963   }
00964   v->HandlePathfindingResult(path_found);
00965 
00966 found_best_track:;
00967 
00968   if (HasBit(red_signals, best_track)) return INVALID_TRACKDIR;
00969 
00970   return best_track;
00971 }
00972 
00973 struct RoadDriveEntry {
00974   byte x, y;
00975 };
00976 
00977 #include "table/roadveh_movement.h"
00978 
00979 static bool RoadVehLeaveDepot(RoadVehicle *v, bool first)
00980 {
00981   /* Don't leave unless v and following wagons are in the depot. */
00982   for (const RoadVehicle *u = v; u != NULL; u = u->Next()) {
00983     if (u->state != RVSB_IN_DEPOT || u->tile != v->tile) return false;
00984   }
00985 
00986   DiagDirection dir = GetRoadDepotDirection(v->tile);
00987   v->direction = DiagDirToDir(dir);
00988 
00989   Trackdir tdir = _roadveh_depot_exit_trackdir[dir];
00990   const RoadDriveEntry *rdp = _road_drive_data[v->roadtype][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + tdir];
00991 
00992   int x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF);
00993   int y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF);
00994 
00995   if (first) {
00996     /* We are leaving a depot, but have to go to the exact same one; re-enter */
00997     if (v->current_order.IsType(OT_GOTO_DEPOT) && v->tile == v->dest_tile) {
00998       VehicleEnterDepot(v);
00999       return true;
01000     }
01001 
01002     if (RoadVehFindCloseTo(v, x, y, v->direction, false) != NULL) return true;
01003 
01004     VehicleServiceInDepot(v);
01005 
01006     StartRoadVehSound(v);
01007 
01008     /* Vehicle is about to leave a depot */
01009     v->cur_speed = 0;
01010   }
01011 
01012   v->vehstatus &= ~VS_HIDDEN;
01013   v->state = tdir;
01014   v->frame = RVC_DEPOT_START_FRAME;
01015 
01016   v->x_pos = x;
01017   v->y_pos = y;
01018   VehicleUpdatePosition(v);
01019   v->UpdateInclination(true, true);
01020 
01021   InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
01022 
01023   return true;
01024 }
01025 
01026 static Trackdir FollowPreviousRoadVehicle(const RoadVehicle *v, const RoadVehicle *prev, TileIndex tile, DiagDirection entry_dir, bool already_reversed)
01027 {
01028   if (prev->tile == v->tile && !already_reversed) {
01029     /* If the previous vehicle is on the same tile as this vehicle is
01030      * then it must have reversed. */
01031     return _road_reverse_table[entry_dir];
01032   }
01033 
01034   byte prev_state = prev->state;
01035   Trackdir dir;
01036 
01037   if (prev_state == RVSB_WORMHOLE || prev_state == RVSB_IN_DEPOT) {
01038     DiagDirection diag_dir = INVALID_DIAGDIR;
01039 
01040     if (IsTileType(tile, MP_TUNNELBRIDGE)) {
01041       diag_dir = GetTunnelBridgeDirection(tile);
01042     } else if (IsRoadDepotTile(tile)) {
01043       diag_dir = ReverseDiagDir(GetRoadDepotDirection(tile));
01044     }
01045 
01046     if (diag_dir == INVALID_DIAGDIR) return INVALID_TRACKDIR;
01047     dir = DiagDirToDiagTrackdir(diag_dir);
01048   } else {
01049     if (already_reversed && prev->tile != tile) {
01050       /*
01051        * The vehicle has reversed, but did not go straight back.
01052        * It immediately turn onto another tile. This means that
01053        * the roadstate of the previous vehicle cannot be used
01054        * as the direction we have to go with this vehicle.
01055        *
01056        * Next table is build in the following way:
01057        *  - first row for when the vehicle in front went to the northern or
01058        *    western tile, second for southern and eastern.
01059        *  - columns represent the entry direction.
01060        *  - cell values are determined by the Trackdir one has to take from
01061        *    the entry dir (column) to the tile in north or south by only
01062        *    going over the trackdirs used for turning 90 degrees, i.e.
01063        *    TRACKDIR_{UPPER,RIGHT,LOWER,LEFT}_{N,E,S,W}.
01064        */
01065       static const Trackdir reversed_turn_lookup[2][DIAGDIR_END] = {
01066         { TRACKDIR_UPPER_W, TRACKDIR_RIGHT_N, TRACKDIR_LEFT_N,  TRACKDIR_UPPER_E },
01067         { TRACKDIR_RIGHT_S, TRACKDIR_LOWER_W, TRACKDIR_LOWER_E, TRACKDIR_LEFT_S  }};
01068       dir = reversed_turn_lookup[prev->tile < tile ? 0 : 1][ReverseDiagDir(entry_dir)];
01069     } else if (HasBit(prev_state, RVS_IN_DT_ROAD_STOP)) {
01070       dir = (Trackdir)(prev_state & RVSB_ROAD_STOP_TRACKDIR_MASK);
01071     } else if (prev_state < TRACKDIR_END) {
01072       dir = (Trackdir)prev_state;
01073     } else {
01074       return INVALID_TRACKDIR;
01075     }
01076   }
01077 
01078   /* Do some sanity checking. */
01079   static const RoadBits required_roadbits[] = {
01080     ROAD_X,            ROAD_Y,            ROAD_NW | ROAD_NE, ROAD_SW | ROAD_SE,
01081     ROAD_NW | ROAD_SW, ROAD_NE | ROAD_SE, ROAD_X,            ROAD_Y
01082   };
01083   RoadBits required = required_roadbits[dir & 0x07];
01084 
01085   if ((required & GetAnyRoadBits(tile, v->roadtype, true)) == ROAD_NONE) {
01086     dir = INVALID_TRACKDIR;
01087   }
01088 
01089   return dir;
01090 }
01091 
01099 static bool CanBuildTramTrackOnTile(CompanyID c, TileIndex t, RoadBits r)
01100 {
01101   /* The 'current' company is not necessarily the owner of the vehicle. */
01102   Backup<CompanyByte> cur_company(_current_company, c, FILE_LINE);
01103 
01104   CommandCost ret = DoCommand(t, ROADTYPE_TRAM << 4 | r, 0, DC_NO_WATER, CMD_BUILD_ROAD);
01105 
01106   cur_company.Restore();
01107   return ret.Succeeded();
01108 }
01109 
01110 bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev)
01111 {
01112   if (v->overtaking != 0)  {
01113     if (IsTileType(v->tile, MP_STATION)) {
01114       /* Force us to be not overtaking! */
01115       v->overtaking = 0;
01116     } else if (++v->overtaking_ctr >= RV_OVERTAKE_TIMEOUT) {
01117       /* If overtaking just aborts at a random moment, we can have a out-of-bound problem,
01118        *  if the vehicle started a corner. To protect that, only allow an abort of
01119        *  overtake if we are on straight roads */
01120       if (v->state < RVSB_IN_ROAD_STOP && IsStraightRoadTrackdir((Trackdir)v->state)) {
01121         v->overtaking = 0;
01122       }
01123     }
01124   }
01125 
01126   /* If this vehicle is in a depot and we've reached this point it must be
01127    * one of the articulated parts. It will stay in the depot until activated
01128    * by the previous vehicle in the chain when it gets to the right place. */
01129   if (v->IsInDepot()) return true;
01130 
01131   if (v->state == RVSB_WORMHOLE) {
01132     /* Vehicle is entering a depot or is on a bridge or in a tunnel */
01133     GetNewVehiclePosResult gp = GetNewVehiclePos(v);
01134 
01135     if (v->IsFrontEngine()) {
01136       const Vehicle *u = RoadVehFindCloseTo(v, gp.x, gp.y, v->direction);
01137       if (u != NULL) {
01138         v->cur_speed = u->First()->cur_speed;
01139         return false;
01140       }
01141     }
01142 
01143     if (IsTileType(gp.new_tile, MP_TUNNELBRIDGE) && HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
01144       /* Vehicle has just entered a bridge or tunnel */
01145       v->x_pos = gp.x;
01146       v->y_pos = gp.y;
01147       VehicleUpdatePosition(v);
01148       v->UpdateInclination(true, true);
01149       return true;
01150     }
01151 
01152     v->x_pos = gp.x;
01153     v->y_pos = gp.y;
01154     VehicleUpdatePosition(v);
01155     if ((v->vehstatus & VS_HIDDEN) == 0) VehicleUpdateViewport(v, true);
01156     return true;
01157   }
01158 
01159   /* Get move position data for next frame.
01160    * For a drive-through road stop use 'straight road' move data.
01161    * In this case v->state is masked to give the road stop entry direction. */
01162   RoadDriveEntry rd = _road_drive_data[v->roadtype][(
01163     (HasBit(v->state, RVS_IN_DT_ROAD_STOP) ? v->state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->state) +
01164     (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->overtaking][v->frame + 1];
01165 
01166   if (rd.x & RDE_NEXT_TILE) {
01167     TileIndex tile = v->tile + TileOffsByDiagDir((DiagDirection)(rd.x & 3));
01168     Trackdir dir;
01169 
01170     if (v->IsFrontEngine()) {
01171       /* If this is the front engine, look for the right path. */
01172       dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3));
01173     } else {
01174       dir = FollowPreviousRoadVehicle(v, prev, tile, (DiagDirection)(rd.x & 3), false);
01175     }
01176 
01177     if (dir == INVALID_TRACKDIR) {
01178       if (!v->IsFrontEngine()) error("Disconnecting road vehicle.");
01179       v->cur_speed = 0;
01180       return false;
01181     }
01182 
01183 again:
01184     uint start_frame = RVC_DEFAULT_START_FRAME;
01185     if (IsReversingRoadTrackdir(dir)) {
01186       /* When turning around we can't be overtaking. */
01187       v->overtaking = 0;
01188 
01189       /* Turning around */
01190       if (v->roadtype == ROADTYPE_TRAM) {
01191         /* Determine the road bits the tram needs to be able to turn around
01192          * using the 'big' corner loop. */
01193         RoadBits needed;
01194         switch (dir) {
01195           default: NOT_REACHED();
01196           case TRACKDIR_RVREV_NE: needed = ROAD_SW; break;
01197           case TRACKDIR_RVREV_SE: needed = ROAD_NW; break;
01198           case TRACKDIR_RVREV_SW: needed = ROAD_NE; break;
01199           case TRACKDIR_RVREV_NW: needed = ROAD_SE; break;
01200         }
01201         if ((v->Previous() != NULL && v->Previous()->tile == tile) ||
01202             (v->IsFrontEngine() && IsNormalRoadTile(tile) && !HasRoadWorks(tile) &&
01203               (needed & GetRoadBits(tile, ROADTYPE_TRAM)) != ROAD_NONE)) {
01204           /*
01205            * Taking the 'big' corner for trams only happens when:
01206            * - The previous vehicle in this (articulated) tram chain is
01207            *   already on the 'next' tile, we just follow them regardless of
01208            *   anything. When it is NOT on the 'next' tile, the tram started
01209            *   doing a reversing turn when the piece of tram track on the next
01210            *   tile did not exist yet. Do not use the big tram loop as that is
01211            *   going to cause the tram to split up.
01212            * - Or the front of the tram can drive over the next tile.
01213            */
01214         } else if (!v->IsFrontEngine() || !CanBuildTramTrackOnTile(v->owner, tile, needed) || ((~needed & GetAnyRoadBits(v->tile, ROADTYPE_TRAM, false)) == ROAD_NONE)) {
01215           /*
01216            * Taking the 'small' corner for trams only happens when:
01217            * - We are not the from vehicle of an articulated tram.
01218            * - Or when the company cannot build on the next tile.
01219            *
01220            * The 'small' corner means that the vehicle is on the end of a
01221            * tram track and needs to start turning there. To do this properly
01222            * the tram needs to start at an offset in the tram turning 'code'
01223            * for 'big' corners. It furthermore does not go to the next tile,
01224            * so that needs to be fixed too.
01225            */
01226           tile = v->tile;
01227           start_frame = RVC_TURN_AROUND_START_FRAME_SHORT_TRAM;
01228         } else {
01229           /* The company can build on the next tile, so wait till (s)he does. */
01230           v->cur_speed = 0;
01231           return false;
01232         }
01233       } else if (IsNormalRoadTile(v->tile) && GetDisallowedRoadDirections(v->tile) != DRD_NONE) {
01234         v->cur_speed = 0;
01235         return false;
01236       } else {
01237         tile = v->tile;
01238       }
01239     }
01240 
01241     /* Get position data for first frame on the new tile */
01242     const RoadDriveEntry *rdp = _road_drive_data[v->roadtype][(dir + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->overtaking];
01243 
01244     int x = TileX(tile) * TILE_SIZE + rdp[start_frame].x;
01245     int y = TileY(tile) * TILE_SIZE + rdp[start_frame].y;
01246 
01247     Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
01248     if (v->IsFrontEngine()) {
01249       Vehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
01250       if (u != NULL) {
01251         v->cur_speed = u->First()->cur_speed;
01252         return false;
01253       }
01254     }
01255 
01256     uint32 r = VehicleEnterTile(v, tile, x, y);
01257     if (HasBit(r, VETS_CANNOT_ENTER)) {
01258       if (!IsTileType(tile, MP_TUNNELBRIDGE)) {
01259         v->cur_speed = 0;
01260         return false;
01261       }
01262       /* Try an about turn to re-enter the previous tile */
01263       dir = _road_reverse_table[rd.x & 3];
01264       goto again;
01265     }
01266 
01267     if (IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) && IsTileType(v->tile, MP_STATION)) {
01268       if (IsReversingRoadTrackdir(dir) && IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
01269         /* New direction is trying to turn vehicle around.
01270          * We can't turn at the exit of a road stop so wait.*/
01271         v->cur_speed = 0;
01272         return false;
01273       }
01274 
01275       /* If we are a drive through road stop and the next tile is of
01276        * the same road stop and the next tile isn't this one (i.e. we
01277        * are not reversing), then keep the reservation and state.
01278        * This way we will not be shortly unregister from the road
01279        * stop. It also makes it possible to load when on the edge of
01280        * two road stops; otherwise you could get vehicles that should
01281        * be loading but are not actually loading. */
01282       if (IsDriveThroughStopTile(v->tile) &&
01283           RoadStop::IsDriveThroughRoadStopContinuation(v->tile, tile) &&
01284           v->tile != tile) {
01285         /* So, keep 'our' state */
01286         dir = (Trackdir)v->state;
01287       } else if (IsRoadStop(v->tile)) {
01288         /* We're not continuing our drive through road stop, so leave. */
01289         RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v);
01290       }
01291     }
01292 
01293     if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
01294       v->tile = tile;
01295       v->state = (byte)dir;
01296       v->frame = start_frame;
01297     }
01298     if (new_dir != v->direction) {
01299       v->direction = new_dir;
01300       if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) v->cur_speed -= v->cur_speed >> 2;
01301     }
01302     v->x_pos = x;
01303     v->y_pos = y;
01304     VehicleUpdatePosition(v);
01305     RoadZPosAffectSpeed(v, v->UpdateInclination(true, true));
01306     return true;
01307   }
01308 
01309   if (rd.x & RDE_TURNED) {
01310     /* Vehicle has finished turning around, it will now head back onto the same tile */
01311     Trackdir dir;
01312     uint turn_around_start_frame = RVC_TURN_AROUND_START_FRAME;
01313 
01314     if (v->roadtype == ROADTYPE_TRAM && !IsRoadDepotTile(v->tile) && HasExactlyOneBit(GetAnyRoadBits(v->tile, ROADTYPE_TRAM, true))) {
01315       /*
01316        * The tram is turning around with one tram 'roadbit'. This means that
01317        * it is using the 'big' corner 'drive data'. However, to support the
01318        * trams to take a small corner, there is a 'turned' marker in the middle
01319        * of the turning 'drive data'. When the tram took the long corner, we
01320        * will still use the 'big' corner drive data, but we advance it one
01321        * frame. We furthermore set the driving direction so the turning is
01322        * going to be properly shown.
01323        */
01324       turn_around_start_frame = RVC_START_FRAME_AFTER_LONG_TRAM;
01325       switch (rd.x & 0x3) {
01326         default: NOT_REACHED();
01327         case DIAGDIR_NW: dir = TRACKDIR_RVREV_SE; break;
01328         case DIAGDIR_NE: dir = TRACKDIR_RVREV_SW; break;
01329         case DIAGDIR_SE: dir = TRACKDIR_RVREV_NW; break;
01330         case DIAGDIR_SW: dir = TRACKDIR_RVREV_NE; break;
01331       }
01332     } else {
01333       if (v->IsFrontEngine()) {
01334         /* If this is the front engine, look for the right path. */
01335         dir = RoadFindPathToDest(v, v->tile, (DiagDirection)(rd.x & 3));
01336       } else {
01337         dir = FollowPreviousRoadVehicle(v, prev, v->tile, (DiagDirection)(rd.x & 3), true);
01338       }
01339     }
01340 
01341     if (dir == INVALID_TRACKDIR) {
01342       v->cur_speed = 0;
01343       return false;
01344     }
01345 
01346     const RoadDriveEntry *rdp = _road_drive_data[v->roadtype][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + dir];
01347 
01348     int x = TileX(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].x;
01349     int y = TileY(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].y;
01350 
01351     Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
01352     if (v->IsFrontEngine() && RoadVehFindCloseTo(v, x, y, new_dir) != NULL) return false;
01353 
01354     uint32 r = VehicleEnterTile(v, v->tile, x, y);
01355     if (HasBit(r, VETS_CANNOT_ENTER)) {
01356       v->cur_speed = 0;
01357       return false;
01358     }
01359 
01360     v->state = dir;
01361     v->frame = turn_around_start_frame;
01362 
01363     if (new_dir != v->direction) {
01364       v->direction = new_dir;
01365       if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) v->cur_speed -= v->cur_speed >> 2;
01366     }
01367 
01368     v->x_pos = x;
01369     v->y_pos = y;
01370     VehicleUpdatePosition(v);
01371     RoadZPosAffectSpeed(v, v->UpdateInclination(true, true));
01372     return true;
01373   }
01374 
01375   /* This vehicle is not in a wormhole and it hasn't entered a new tile. If
01376    * it's on a depot tile, check if it's time to activate the next vehicle in
01377    * the chain yet. */
01378   if (v->Next() != NULL && IsRoadDepotTile(v->tile)) {
01379     if (v->frame == v->gcache.cached_veh_length + RVC_DEPOT_START_FRAME) {
01380       RoadVehLeaveDepot(v->Next(), false);
01381     }
01382   }
01383 
01384   /* Calculate new position for the vehicle */
01385   int x = (v->x_pos & ~15) + (rd.x & 15);
01386   int y = (v->y_pos & ~15) + (rd.y & 15);
01387 
01388   Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
01389 
01390   if (v->IsFrontEngine() && !IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
01391     /* Vehicle is not in a road stop.
01392      * Check for another vehicle to overtake */
01393     RoadVehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
01394 
01395     if (u != NULL) {
01396       u = u->First();
01397       /* There is a vehicle in front overtake it if possible */
01398       if (v->overtaking == 0) RoadVehCheckOvertake(v, u);
01399       if (v->overtaking == 0) v->cur_speed = u->cur_speed;
01400 
01401       /* In case an RV is stopped in a road stop, why not try to load? */
01402       if (v->cur_speed == 0 && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
01403           v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
01404           v->owner == GetTileOwner(v->tile) && !v->current_order.IsType(OT_LEAVESTATION) &&
01405           GetRoadStopType(v->tile) == (v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK)) {
01406         Station *st = Station::GetByTile(v->tile);
01407         v->last_station_visited = st->index;
01408         RoadVehArrivesAt(v, st);
01409         v->BeginLoading();
01410       }
01411       return false;
01412     }
01413   }
01414 
01415   Direction old_dir = v->direction;
01416   if (new_dir != old_dir) {
01417     v->direction = new_dir;
01418     if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) v->cur_speed -= v->cur_speed >> 2;
01419 
01420     /* Delay the vehicle in curves by making it require one additional frame per turning direction (two in total).
01421      * A vehicle has to spend at least 9 frames on a tile, so the following articulated part can follow.
01422      * (The following part may only be one tile behind, and the front part is moved before the following ones.)
01423      * The short (inner) curve has 8 frames, this elongates it to 10. */
01424     v->UpdateInclination(false, true);
01425     return true;
01426   }
01427 
01428   /* If the vehicle is in a normal road stop and the frame equals the stop frame OR
01429    * if the vehicle is in a drive-through road stop and this is the destination station
01430    * and it's the correct type of stop (bus or truck) and the frame equals the stop frame...
01431    * (the station test and stop type test ensure that other vehicles, using the road stop as
01432    * a through route, do not stop) */
01433   if (v->IsFrontEngine() && ((IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) &&
01434       _road_stop_stop_frame[v->state - RVSB_IN_ROAD_STOP + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)] == v->frame) ||
01435       (IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
01436       v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
01437       v->owner == GetTileOwner(v->tile) &&
01438       GetRoadStopType(v->tile) == (v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK) &&
01439       v->frame == RVC_DRIVE_THROUGH_STOP_FRAME))) {
01440 
01441     RoadStop *rs = RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile));
01442     Station *st = Station::GetByTile(v->tile);
01443 
01444     /* Vehicle is at the stop position (at a bay) in a road stop.
01445      * Note, if vehicle is loading/unloading it has already been handled,
01446      * so if we get here the vehicle has just arrived or is just ready to leave. */
01447     if (!HasBit(v->state, RVS_ENTERED_STOP)) {
01448       /* Vehicle has arrived at a bay in a road stop */
01449 
01450       if (IsDriveThroughStopTile(v->tile)) {
01451         TileIndex next_tile = TILE_ADD(v->tile, TileOffsByDir(v->direction));
01452 
01453         /* Check if next inline bay is free and has compatible road. */
01454         if (RoadStop::IsDriveThroughRoadStopContinuation(v->tile, next_tile) && (GetRoadTypes(next_tile) & v->compatible_roadtypes) != 0) {
01455           v->frame++;
01456           v->x_pos = x;
01457           v->y_pos = y;
01458           VehicleUpdatePosition(v);
01459           RoadZPosAffectSpeed(v, v->UpdateInclination(true, false));
01460           return true;
01461         }
01462       }
01463 
01464       rs->SetEntranceBusy(false);
01465       SetBit(v->state, RVS_ENTERED_STOP);
01466 
01467       v->last_station_visited = st->index;
01468 
01469       if (IsDriveThroughStopTile(v->tile) || (v->current_order.IsType(OT_GOTO_STATION) && v->current_order.GetDestination() == st->index)) {
01470         RoadVehArrivesAt(v, st);
01471         v->BeginLoading();
01472         return false;
01473       }
01474     } else {
01475       /* Vehicle is ready to leave a bay in a road stop */
01476       if (rs->IsEntranceBusy()) {
01477         /* Road stop entrance is busy, so wait as there is nowhere else to go */
01478         v->cur_speed = 0;
01479         return false;
01480       }
01481       if (v->current_order.IsType(OT_LEAVESTATION)) v->current_order.Free();
01482     }
01483 
01484     if (IsStandardRoadStopTile(v->tile)) rs->SetEntranceBusy(true);
01485 
01486     StartRoadVehSound(v);
01487     SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
01488   }
01489 
01490   /* Check tile position conditions - i.e. stop position in depot,
01491    * entry onto bridge or into tunnel */
01492   uint32 r = VehicleEnterTile(v, v->tile, x, y);
01493   if (HasBit(r, VETS_CANNOT_ENTER)) {
01494     v->cur_speed = 0;
01495     return false;
01496   }
01497 
01498   if (v->current_order.IsType(OT_LEAVESTATION) && IsDriveThroughStopTile(v->tile)) {
01499     v->current_order.Free();
01500   }
01501 
01502   /* Move to next frame unless vehicle arrived at a stop position
01503    * in a depot or entered a tunnel/bridge */
01504   if (!HasBit(r, VETS_ENTERED_WORMHOLE)) v->frame++;
01505   v->x_pos = x;
01506   v->y_pos = y;
01507   VehicleUpdatePosition(v);
01508   RoadZPosAffectSpeed(v, v->UpdateInclination(false, true));
01509   return true;
01510 }
01511 
01512 static bool RoadVehController(RoadVehicle *v)
01513 {
01514   /* decrease counters */
01515   v->current_order_time++;
01516   if (v->reverse_ctr != 0) v->reverse_ctr--;
01517 
01518   /* handle crashed */
01519   if (v->vehstatus & VS_CRASHED || RoadVehCheckTrainCrash(v)) {
01520     return RoadVehIsCrashed(v);
01521   }
01522 
01523   /* road vehicle has broken down? */
01524   if (v->HandleBreakdown()) return true;
01525   if (v->vehstatus & VS_STOPPED) return true;
01526 
01527   ProcessOrders(v);
01528   v->HandleLoading();
01529 
01530   if (v->current_order.IsType(OT_LOADING)) return true;
01531 
01532   if (v->IsInDepot() && RoadVehLeaveDepot(v, true)) return true;
01533 
01534   v->ShowVisualEffect();
01535 
01536   /* Check how far the vehicle needs to proceed */
01537   int j = v->UpdateSpeed();
01538 
01539   int adv_spd = v->GetAdvanceDistance();
01540   bool blocked = false;
01541   while (j >= adv_spd) {
01542     j -= adv_spd;
01543 
01544     RoadVehicle *u = v;
01545     for (RoadVehicle *prev = NULL; u != NULL; prev = u, u = u->Next()) {
01546       if (!IndividualRoadVehicleController(u, prev)) {
01547         blocked = true;
01548         break;
01549       }
01550     }
01551     if (blocked) break;
01552 
01553     /* Determine distance to next map position */
01554     adv_spd = v->GetAdvanceDistance();
01555 
01556     /* Test for a collision, but only if another movement will occur. */
01557     if (j >= adv_spd && RoadVehCheckTrainCrash(v)) break;
01558   }
01559 
01560   v->SetLastSpeed();
01561 
01562   for (RoadVehicle *u = v; u != NULL; u = u->Next()) {
01563     if ((u->vehstatus & VS_HIDDEN) != 0) continue;
01564 
01565     u->UpdateViewport(false, false);
01566   }
01567 
01568   /* If movement is blocked, set 'progress' to its maximum, so the roadvehicle does
01569    * not accelerate again before it can actually move. I.e. make sure it tries to advance again
01570    * on next tick to discover whether it is still blocked. */
01571   if (v->progress == 0) v->progress = blocked ? adv_spd - 1 : j;
01572 
01573   return true;
01574 }
01575 
01576 Money RoadVehicle::GetRunningCost() const
01577 {
01578   const Engine *e = this->GetEngine();
01579   if (e->u.road.running_cost_class == INVALID_PRICE) return 0;
01580 
01581   uint cost_factor = GetVehicleProperty(this, PROP_ROADVEH_RUNNING_COST_FACTOR, e->u.road.running_cost);
01582   if (cost_factor == 0) return 0;
01583 
01584   return GetPrice(e->u.road.running_cost_class, cost_factor, e->GetGRF());
01585 }
01586 
01587 bool RoadVehicle::Tick()
01588 {
01589   this->tick_counter++;
01590 
01591   if (this->IsFrontEngine()) {
01592     if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
01593     return RoadVehController(this);
01594   }
01595 
01596   return true;
01597 }
01598 
01599 static void CheckIfRoadVehNeedsService(RoadVehicle *v)
01600 {
01601   /* If we already got a slot at a stop, use that FIRST, and go to a depot later */
01602   if (Company::Get(v->owner)->settings.vehicle.servint_roadveh == 0 || !v->NeedsAutomaticServicing()) return;
01603   if (v->IsChainInDepot()) {
01604     VehicleServiceInDepot(v);
01605     return;
01606   }
01607 
01608   uint max_penalty;
01609   switch (_settings_game.pf.pathfinder_for_roadvehs) {
01610     case VPF_NPF:  max_penalty = _settings_game.pf.npf.maximum_go_to_depot_penalty;  break;
01611     case VPF_YAPF: max_penalty = _settings_game.pf.yapf.maximum_go_to_depot_penalty; break;
01612     default: NOT_REACHED();
01613   }
01614 
01615   FindDepotData rfdd = FindClosestRoadDepot(v, max_penalty);
01616   /* Only go to the depot if it is not too far out of our way. */
01617   if (rfdd.best_length == UINT_MAX || rfdd.best_length > max_penalty) {
01618     if (v->current_order.IsType(OT_GOTO_DEPOT)) {
01619       /* If we were already heading for a depot but it has
01620        * suddenly moved farther away, we continue our normal
01621        * schedule? */
01622       v->current_order.MakeDummy();
01623       SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
01624     }
01625     return;
01626   }
01627 
01628   DepotID depot = GetDepotIndex(rfdd.tile);
01629 
01630   if (v->current_order.IsType(OT_GOTO_DEPOT) &&
01631       v->current_order.GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS &&
01632       !Chance16(1, 20)) {
01633     return;
01634   }
01635 
01636   SetBit(v->gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
01637   v->current_order.MakeGoToDepot(depot, ODTFB_SERVICE);
01638   v->dest_tile = rfdd.tile;
01639   SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
01640 }
01641 
01642 void RoadVehicle::OnNewDay()
01643 {
01644   AgeVehicle(this);
01645 
01646   if (!this->IsFrontEngine()) return;
01647 
01648   if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
01649   if (this->blocked_ctr == 0) CheckVehicleBreakdown(this);
01650 
01651   CheckIfRoadVehNeedsService(this);
01652 
01653   CheckOrders(this);
01654 
01655   if (this->running_ticks == 0) return;
01656 
01657   CommandCost cost(EXPENSES_ROADVEH_RUN, this->GetRunningCost() * this->running_ticks / (DAYS_IN_YEAR * DAY_TICKS));
01658 
01659   this->profit_this_year -= cost.GetCost();
01660   this->running_ticks = 0;
01661 
01662   SubtractMoneyFromCompanyFract(this->owner, cost);
01663 
01664   SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
01665   SetWindowClassesDirty(WC_ROADVEH_LIST);
01666 }
01667 
01668 Trackdir RoadVehicle::GetVehicleTrackdir() const
01669 {
01670   if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
01671 
01672   if (this->IsInDepot()) {
01673     /* We'll assume the road vehicle is facing outwards */
01674     return DiagDirToDiagTrackdir(GetRoadDepotDirection(this->tile));
01675   }
01676 
01677   if (IsStandardRoadStopTile(this->tile)) {
01678     /* We'll assume the road vehicle is facing outwards */
01679     return DiagDirToDiagTrackdir(GetRoadStopDir(this->tile)); // Road vehicle in a station
01680   }
01681 
01682   /* Drive through road stops / wormholes (tunnels) */
01683   if (this->state > RVSB_TRACKDIR_MASK) return DiagDirToDiagTrackdir(DirToDiagDir(this->direction));
01684 
01685   /* If vehicle's state is a valid track direction (vehicle is not turning around) return it,
01686    * otherwise transform it into a valid track direction */
01687   return (Trackdir)((IsReversingRoadTrackdir((Trackdir)this->state)) ? (this->state - 6) : this->state);
01688 }