roadveh_cmd.cpp

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