roadveh_cmd.cpp

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