# roadveh_cmd.cpp

Go to the documentation of this file.

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