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