# roadveh_cmd.cpp

Go to the documentation of this file.

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