# roadveh_cmd.cpp

Go to the documentation of this file.

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