# roadveh_cmd.cpp

Go to the documentation of this file.

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