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