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