roadveh_cmd.cpp

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