# roadveh_cmd.cpp

Go to the documentation of this file.

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