# roadveh_cmd.cpp

Go to the documentation of this file.

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