# roadveh_cmd.cpp

Go to the documentation of this file.

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