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