# roadveh_cmd.cpp

Go to the documentation of this file.

    00001 /* $Id: roadveh_cmd.cpp 17516 2009-09-12 20:44:12Z rubidium $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "landscape.h"
    00007 #include "roadveh.h"
    00008 #include "station_map.h"
    00009 #include "command_func.h"
    00010 #include "news_func.h"
    00011 #include "pathfind.h"
    00012 #include "npf.h"
    00013 #include "company_func.h"
    00014 #include "vehicle_gui.h"
    00015 #include "articulated_vehicles.h"
    00016 #include "newgrf_engine.h"
    00017 #include "newgrf_sound.h"
    00018 #include "yapf/yapf.h"
    00019 #include "strings_func.h"
    00020 #include "tunnelbridge_map.h"
    00021 #include "functions.h"
    00022 #include "window_func.h"
    00023 #include "date_func.h"
    00024 #include "vehicle_func.h"
    00025 #include "sound_func.h"
    00026 #include "variables.h"
    00027 #include "autoreplace_gui.h"
    00028 #include "gfx_func.h"
    00029 #include "ai/ai.hpp"
    00030 #include "depot_base.h"
    00031 #include "effectvehicle_func.h"
    00032 #include "settings_type.h"
    00033
    00034 #include "table/strings.h"
    00035 #include "table/sprites.h"
    00036
    00037 static const uint16 _roadveh_images[63] = {
    00038   0xCD4, 0xCDC, 0xCE4, 0xCEC, 0xCF4, 0xCFC, 0xD0C, 0xD14,
    00039   0xD24, 0xD1C, 0xD2C, 0xD04, 0xD1C, 0xD24, 0xD6C, 0xD74,
    00040   0xD7C, 0xC14, 0xC1C, 0xC24, 0xC2C, 0xC34, 0xC3C, 0xC4C,
    00041   0xC54, 0xC64, 0xC5C, 0xC6C, 0xC44, 0xC5C, 0xC64, 0xCAC,
    00042   0xCB4, 0xCBC, 0xD94, 0xD9C, 0xDA4, 0xDAC, 0xDB4, 0xDBC,
    00043   0xDCC, 0xDD4, 0xDE4, 0xDDC, 0xDEC, 0xDC4, 0xDDC, 0xDE4,
    00044   0xE2C, 0xE34, 0xE3C, 0xC14, 0xC1C, 0xC2C, 0xC3C, 0xC4C,
    00045   0xC5C, 0xC64, 0xC6C, 0xC74, 0xC84, 0xC94, 0xCA4
    00046 };
    00047
    00048 static const uint16 _roadveh_full_adder[63] = {
    00049    0,  88,   0,   0,   0,   0,  48,  48,
    00050   48,  48,   0,   0,  64,  64,   0,  16,
    00051   16,   0,  88,   0,   0,   0,   0,  48,
    00052   48,  48,  48,   0,   0,  64,  64,   0,
    00053   16,  16,   0,  88,   0,   0,   0,   0,
    00054   48,  48,  48,  48,   0,   0,  64,  64,
    00055    0,  16,  16,   0,   8,   8,   8,   8,
    00056    0,   0,   0,   8,   8,   8,   8
    00057 };
    00058
    00060 static const TrackdirBits _road_enter_dir_to_reachable_trackdirs[DIAGDIR_END] = {
    00061   TRACKDIR_BIT_LEFT_N  | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_X_NE,    // Enter from north east
    00062   TRACKDIR_BIT_LEFT_S  | TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_Y_SE,    // Enter from south east
    00063   TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_X_SW    | TRACKDIR_BIT_RIGHT_S, // Enter from south west
    00064   TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_Y_NW     // Enter from north west
    00065 };
    00066
    00067 static const Trackdir _road_reverse_table[DIAGDIR_END] = {
    00068   TRACKDIR_RVREV_NE, TRACKDIR_RVREV_SE, TRACKDIR_RVREV_SW, TRACKDIR_RVREV_NW
    00069 };
    00070
    00073 static const TrackdirBits _road_exit_dir_to_incoming_trackdirs[DIAGDIR_END] = {
    00074   TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_X_SW    | TRACKDIR_BIT_LEFT_S,
    00075   TRACKDIR_BIT_LEFT_N  | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_Y_NW,
    00076   TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_X_NE,
    00077   TRACKDIR_BIT_RIGHT_S | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_Y_SE
    00078 };
    00079
    00081 static const Trackdir _roadveh_depot_exit_trackdir[DIAGDIR_END] = {
    00082   TRACKDIR_X_NE, TRACKDIR_Y_SE, TRACKDIR_X_SW, TRACKDIR_Y_NW
    00083 };
    00084
    00085 static SpriteID GetRoadVehIcon(EngineID engine)
    00086 {
    00087   uint8 spritenum = RoadVehInfo(engine)->image_index;
    00088
    00089   if (is_custom_sprite(spritenum)) {
    00090     SpriteID sprite = GetCustomVehicleIcon(engine, DIR_W);
    00091     if (sprite != 0) return sprite;
    00092
    00093     spritenum = GetEngine(engine)->image_index;
    00094   }
    00095
    00096   return 6 + _roadveh_images[spritenum];
    00097 }
    00098
    00099 SpriteID RoadVehicle::GetImage(Direction direction) const
    00100 {
    00101   uint8 spritenum = this->spritenum;
    00102   SpriteID sprite;
    00103
    00104   if (is_custom_sprite(spritenum)) {
    00105     sprite = GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)));
    00106     if (sprite != 0) return sprite;
    00107
    00108     spritenum = GetEngine(this->engine_type)->image_index;
    00109   }
    00110
    00111   sprite = direction + _roadveh_images[spritenum];
    00112
    00113   if (this->cargo.Count() >= this->cargo_cap / 2U) sprite += _roadveh_full_adder[spritenum];
    00114
    00115   return sprite;
    00116 }
    00117
    00118 void DrawRoadVehEngine(int x, int y, EngineID engine, SpriteID pal)
    00119 {
    00120   DrawSprite(GetRoadVehIcon(engine), pal, x, y);
    00121 }
    00122
    00123 byte GetRoadVehLength(const Vehicle *v)
    00124 {
    00125   byte length = 8;
    00126
    00127   uint16 veh_len = GetVehicleCallback(CBID_VEHICLE_LENGTH, 0, 0, v->engine_type, v);
    00128   if (veh_len != CALLBACK_FAILED) {
    00129     length -= Clamp(veh_len, 0, 7);
    00130   }
    00131
    00132   return length;
    00133 }
    00134
    00135 void RoadVehUpdateCache(Vehicle *v)
    00136 {
    00137   assert(v->type == VEH_ROAD);
    00138   assert(IsRoadVehFront(v));
    00139
    00140   v->InvalidateNewGRFCacheOfChain();
    00141
    00142   for (Vehicle *u = v; u != NULL; u = u->Next()) {
    00143     /* Check the v->first cache. */
    00144     assert(u->First() == v);
    00145
    00146     /* Update the 'first engine' */
    00147     u->u.road.first_engine = (v == u) ? INVALID_ENGINE : v->engine_type;
    00148
    00149     /* Update the length of the vehicle. */
    00150     u->u.road.cached_veh_length = GetRoadVehLength(u);
    00151
    00152     /* Invalidate the vehicle colour map */
    00153     u->colourmap = PAL_NONE;
    00154   }
    00155 }
    00156
    00163 CommandCost CmdBuildRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    00164 {
    00165   Vehicle *v;
    00166   UnitID unit_num;
    00167
    00168   if (!IsEngineBuildable(p1, VEH_ROAD, _current_company)) return_cmd_error(STR_ROAD_VEHICLE_NOT_AVAILABLE);
    00169
    00170   const Engine *e = GetEngine(p1);
    00171   /* Engines without valid cargo should not be available */
    00172   if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR;
    00173
    00174   CommandCost cost(EXPENSES_NEW_VEHICLES, e->GetCost());
    00175   if (flags & DC_QUERY_COST) return cost;
    00176
    00177   /* The ai_new queries the vehicle cost before building the route,
    00178    * so we must check against cheaters no sooner than now. --pasky */
    00179   if (!IsRoadDepotTile(tile)) return CMD_ERROR;
    00180   if (!IsTileOwner(tile, _current_company)) return CMD_ERROR;
    00181
    00182   if (HasTileRoadType(tile, ROADTYPE_TRAM) != HasBit(EngInfo(p1)->misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_DEPOT_WRONG_DEPOT_TYPE);
    00183
    00184   uint num_vehicles = 1 + CountArticulatedParts(p1, false);
    00185
    00186   /* Allow for the front and the articulated parts, plus one to "terminate" the list. */
    00187   Vehicle **vl = AllocaM(Vehicle*, num_vehicles + 1);
    00188   memset(vl, 0, sizeof(*vl) * (num_vehicles + 1));
    00189
    00190   if (!Vehicle::AllocateList(vl, num_vehicles)) {
    00191     return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
    00192   }
    00193
    00194   v = vl[0];
    00195
    00196   /* find the first free roadveh id */
    00197   unit_num = (flags & DC_AUTOREPLACE) ? 0 : GetFreeUnitNumber(VEH_ROAD);
    00198   if (unit_num > _settings_game.vehicle.max_roadveh)
    00199     return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
    00200
    00201   if (flags & DC_EXEC) {
    00202     int x;
    00203     int y;
    00204
    00205     const RoadVehicleInfo *rvi = RoadVehInfo(p1);
    00206
    00207     v = new (v) RoadVehicle();
    00208     v->unitnumber = unit_num;
    00209     v->direction = DiagDirToDir(GetRoadDepotDirection(tile));
    00210     v->owner = _current_company;
    00211
    00212     v->tile = tile;
    00213     x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2;
    00214     y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2;
    00215     v->x_pos = x;
    00216     v->y_pos = y;
    00217     v->z_pos = GetSlopeZ(x, y);
    00218
    00219     v->running_ticks = 0;
    00220
    00221     v->u.road.state = RVSB_IN_DEPOT;
    00222     v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
    00223
    00224     v->spritenum = rvi->image_index;
    00225     v->cargo_type = e->GetDefaultCargoType();
    00226     v->cargo_subtype = 0;
    00227     v->cargo_cap = rvi->capacity;
    00228 //    v->cargo_count = 0;
    00229     v->value = cost.GetCost();
    00230 //    v->day_counter = 0;
    00231 //    v->next_order_param = v->next_order = 0;
    00232 //    v->load_unload_time_rem = 0;
    00233 //    v->progress = 0;
    00234
    00235 //  v->u.road.overtaking = 0;
    00236
    00237     v->last_station_visited = INVALID_STATION;
    00238     v->max_speed = rvi->max_speed;
    00239     v->engine_type = (EngineID)p1;
    00240
    00241     v->reliability = e->reliability;
    00242     v->reliability_spd_dec = e->reliability_spd_dec;
    00243     v->max_age = e->lifelength * DAYS_IN_LEAP_YEAR;
    00244     _new_vehicle_id = v->index;
    00245
    00246     v->name = NULL;
    00247
    00248     v->service_interval = _settings_game.vehicle.servint_roadveh;
    00249
    00250     v->date_of_last_service = _date;
    00251     v->build_year = _cur_year;
    00252
    00253     v->cur_image = 0xC15;
    00254     v->random_bits = VehicleRandomBits();
    00255     SetRoadVehFront(v);
    00256
    00257     v->u.road.roadtype = HasBit(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
    00258     v->u.road.compatible_roadtypes = RoadTypeToRoadTypes(v->u.road.roadtype);
    00259     v->u.road.cached_veh_length = 8;
    00260
    00261     v->vehicle_flags = 0;
    00262     if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
    00263
    00264     v->cargo_cap = rvi->capacity;
    00265
    00266     AddArticulatedParts(vl, VEH_ROAD);
    00267     v->InvalidateNewGRFCacheOfChain();
    00268
    00269     /* Call various callbacks after the whole consist has been constructed */
    00270     for (Vehicle *u = v; u != NULL; u = u->Next()) {
    00271       u->u.road.cached_veh_length = GetRoadVehLength(u);
    00272       /* Cargo capacity is zero if and only if the vehicle cannot carry anything */
    00273       if (u->cargo_cap != 0) u->cargo_cap = GetVehicleProperty(u, 0x0F, u->cargo_cap);
    00274       v->InvalidateNewGRFCache();
    00275       u->InvalidateNewGRFCache();
    00276     }
    00277
    00278     VehicleMove(v, false);
    00279
    00280     InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
    00281     InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
    00282     InvalidateWindow(WC_COMPANY, v->owner);
    00283     if (IsLocalCompany()) {
    00284       InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Road window
    00285     }
    00286
    00287     GetCompany(_current_company)->num_engines[p1]++;
    00288
    00289     CheckConsistencyOfArticulatedVehicle(v);
    00290   }
    00291
    00292   return cost;
    00293 }
    00294
    00295 void ClearSlot(Vehicle *v)
    00296 {
    00297   RoadStop *rs = v->u.road.slot;
    00298   if (v->u.road.slot == NULL) return;
    00299
    00300   v->u.road.slot = NULL;
    00301   v->u.road.slot_age = 0;
    00302
    00303   assert(rs->num_vehicles != 0);
    00304   rs->num_vehicles--;
    00305
    00306   DEBUG(ms, 3, "Clearing slot at 0x%X", rs->xy);
    00307 }
    00308
    00309 bool RoadVehicle::IsStoppedInDepot() const
    00310 {
    00311   TileIndex tile = this->tile;
    00312
    00313   if (!IsRoadDepotTile(tile)) return false;
    00314   if (IsRoadVehFront(this) && !(this->vehstatus & VS_STOPPED)) return false;
    00315
    00316   for (const Vehicle *v = this; v != NULL; v = v->Next()) {
    00317     if (v->u.road.state != RVSB_IN_DEPOT || v->tile != tile) return false;
    00318   }
    00319   return true;
    00320 }
    00321
    00328 CommandCost CmdSellRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    00329 {
    00330   Vehicle *v;
    00331
    00332   if (!IsValidVehicleID(p1)) return CMD_ERROR;
    00333
    00334   v = GetVehicle(p1);
    00335
    00336   if (v->type != VEH_ROAD || !CheckOwnership(v->owner)) return CMD_ERROR;
    00337
    00338   if (HASBITS(v->vehstatus, VS_CRASHED)) return_cmd_error(STR_CAN_T_SELL_DESTROYED_VEHICLE);
    00339
    00340   if (!v->IsStoppedInDepot()) {
    00341     return_cmd_error(STR_9013_MUST_BE_STOPPED_INSIDE);
    00342   }
    00343
    00344   CommandCost ret(EXPENSES_NEW_VEHICLES, -v->value);
    00345
    00346   if (flags & DC_EXEC) {
    00347     delete v;
    00348   }
    00349
    00350   return ret;
    00351 }
    00352
    00353 struct RoadFindDepotData {
    00354   uint best_length;
    00355   TileIndex tile;
    00356   OwnerByte owner;
    00357 };
    00358
    00359 static const DiagDirection _road_pf_directions[] = {
    00360   DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SW, DIAGDIR_SE, INVALID_DIAGDIR, INVALID_DIAGDIR,
    00361   DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE, INVALID_DIAGDIR, INVALID_DIAGDIR
    00362 };
    00363
    00364 static bool EnumRoadSignalFindDepot(TileIndex tile, void *data, Trackdir trackdir, uint length)
    00365 {
    00366   RoadFindDepotData *rfdd = (RoadFindDepotData*)data;
    00367
    00368   tile += TileOffsByDiagDir(_road_pf_directions[trackdir]);
    00369
    00370   if (IsRoadDepotTile(tile) &&
    00371       IsTileOwner(tile, rfdd->owner) &&
    00372       length < rfdd->best_length) {
    00373     rfdd->best_length = length;
    00374     rfdd->tile = tile;
    00375   }
    00376   return false;
    00377 }
    00378
    00379 static const Depot *FindClosestRoadDepot(const Vehicle *v)
    00380 {
    00381   switch (_settings_game.pf.pathfinder_for_roadvehs) {
    00382     case VPF_YAPF: // YAPF
    00383       return YapfFindNearestRoadDepot(v);
    00384
    00385     case VPF_NPF: { // NPF
    00386       /* See where we are now */
    00387       Trackdir trackdir = GetVehicleTrackdir(v);
    00388
    00389       NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, v->tile, ReverseTrackdir(trackdir), false, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPES, 0);
    00390
    00391       if (ftd.best_bird_dist == 0) return GetDepotByTile(ftd.node.tile); // Target found
    00392     } break;
    00393
    00394     default:
    00395     case VPF_OPF: { // OPF
    00396       RoadFindDepotData rfdd;
    00397
    00398       rfdd.owner = v->owner;
    00399       rfdd.best_length = UINT_MAX;
    00400
    00401       /* search in all directions */
    00402       for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
    00403         FollowTrack(v->tile, PATHFIND_FLAGS_NONE, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, d, EnumRoadSignalFindDepot, NULL, &rfdd);
    00404       }
    00405
    00406       if (rfdd.best_length != UINT_MAX) return GetDepotByTile(rfdd.tile);
    00407     } break;
    00408   }
    00409
    00410   return NULL; // Target not found
    00411 }
    00412
    00413 bool RoadVehicle::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
    00414 {
    00415   const Depot *depot = FindClosestRoadDepot(this);
    00416
    00417   if (depot == NULL) return false;
    00418
    00419   if (location    != NULL) *location    = depot->xy;
    00420   if (destination != NULL) *destination = depot->index;
    00421
    00422   return true;
    00423 }
    00424
    00433 CommandCost CmdSendRoadVehToDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    00434 {
    00435   if (p2 & DEPOT_MASS_SEND) {
    00436     /* Mass goto depot requested */
    00437     if (!ValidVLWFlags(p2 & VLW_MASK)) return CMD_ERROR;
    00438     return SendAllVehiclesToDepot(VEH_ROAD, flags, p2 & DEPOT_SERVICE, _current_company, (p2 & VLW_MASK), p1);
    00439   }
    00440
    00441   if (!IsValidVehicleID(p1)) return CMD_ERROR;
    00442
    00443   Vehicle *v = GetVehicle(p1);
    00444
    00445   if (v->type != VEH_ROAD) return CMD_ERROR;
    00446
    00447   return v->SendToDepot(flags, (DepotCommand)(p2 & DEPOT_COMMAND_MASK));
    00448 }
    00449
    00456 CommandCost CmdTurnRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    00457 {
    00458   Vehicle *v;
    00459
    00460   if (!IsValidVehicleID(p1)) return CMD_ERROR;
    00461
    00462   v = GetVehicle(p1);
    00463
    00464   if (v->type != VEH_ROAD || !CheckOwnership(v->owner)) return CMD_ERROR;
    00465
    00466   if (v->vehstatus & VS_STOPPED ||
    00467       v->vehstatus & VS_CRASHED ||
    00468       v->breakdown_ctr != 0 ||
    00469       v->u.road.overtaking != 0 ||
    00470       v->u.road.state == RVSB_WORMHOLE ||
    00471       v->IsInDepot() ||
    00472       v->cur_speed < 5) {
    00473     return CMD_ERROR;
    00474   }
    00475
    00476   if (IsNormalRoadTile(v->tile) && GetDisallowedRoadDirections(v->tile) != DRD_NONE) return CMD_ERROR;
    00477
    00478   if (IsTileType(v->tile, MP_TUNNELBRIDGE) && DirToDiagDir(v->direction) == GetTunnelBridgeDirection(v->tile)) return CMD_ERROR;
    00479
    00480   if (flags & DC_EXEC) v->u.road.reverse_ctr = 180;
    00481
    00482   return CommandCost();
    00483 }
    00484
    00485
    00486 void RoadVehicle::MarkDirty()
    00487 {
    00488   for (Vehicle *v = this; v != NULL; v = v->Next()) {
    00489     v->UpdateViewport(false, false);
    00490   }
    00491 }
    00492
    00493 void RoadVehicle::UpdateDeltaXY(Direction direction)
    00494 {
    00495 #define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0)
    00496   static const uint32 _delta_xy_table[8] = {
    00497     MKIT(3, 3, -1, -1),
    00498     MKIT(3, 7, -1, -3),
    00499     MKIT(3, 3, -1, -1),
    00500     MKIT(7, 3, -3, -1),
    00501     MKIT(3, 3, -1, -1),
    00502     MKIT(3, 7, -1, -3),
    00503     MKIT(3, 3, -1, -1),
    00504     MKIT(7, 3, -3, -1),
    00505   };
    00506 #undef MKIT
    00507
    00508   uint32 x = _delta_xy_table[direction];
    00509   this->x_offs        = GB(x,  0, 8);
    00510   this->y_offs        = GB(x,  8, 8);
    00511   this->x_extent      = GB(x, 16, 8);
    00512   this->y_extent      = GB(x, 24, 8);
    00513   this->z_extent      = 6;
    00514 }
    00515
    00516 static void ClearCrashedStation(Vehicle *v)
    00517 {
    00518   RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile));
    00519
    00520   /* Mark the station entrance as not busy */
    00521   rs->SetEntranceBusy(false);
    00522
    00523   /* Free the parking bay */
    00524   rs->FreeBay(HasBit(v->u.road.state, RVS_USING_SECOND_BAY));
    00525 }
    00526
    00527 static void DeleteLastRoadVeh(Vehicle *v)
    00528 {
    00529   Vehicle *u = v;
    00530   for (; v->Next() != NULL; v = v->Next()) u = v;
    00531   u->SetNext(NULL);
    00532
    00533   if (IsTileType(v->tile, MP_STATION)) ClearCrashedStation(v);
    00534
    00535   delete v;
    00536 }
    00537
    00538 static byte SetRoadVehPosition(Vehicle *v, int x, int y, bool turned)
    00539 {
    00540   byte new_z, old_z;
    00541
    00542   /* need this hint so it returns the right z coordinate on bridges. */
    00543   v->x_pos = x;
    00544   v->y_pos = y;
    00545   new_z = GetSlopeZ(x, y);
    00546
    00547   old_z = v->z_pos;
    00548   v->z_pos = new_z;
    00549
    00550   v->UpdateViewport(true, turned);
    00551   return old_z;
    00552 }
    00553
    00554 static void RoadVehSetRandomDirection(Vehicle *v)
    00555 {
    00556   static const DirDiff delta[] = {
    00557     DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT
    00558   };
    00559
    00560   do {
    00561     uint32 r = Random();
    00562
    00563     v->direction = ChangeDir(v->direction, delta[r & 3]);
    00564     SetRoadVehPosition(v, v->x_pos, v->y_pos, true);
    00565   } while ((v = v->Next()) != NULL);
    00566 }
    00567
    00568 static void RoadVehIsCrashed(Vehicle *v)
    00569 {
    00570   v->u.road.crashed_ctr++;
    00571   if (v->u.road.crashed_ctr == 2) {
    00572     CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
    00573   } else if (v->u.road.crashed_ctr <= 45) {
    00574     if ((v->tick_counter & 7) == 0) RoadVehSetRandomDirection(v);
    00575   } else if (v->u.road.crashed_ctr >= 2220 && !(v->tick_counter & 0x1F)) {
    00576     DeleteLastRoadVeh(v);
    00577   }
    00578 }
    00579
    00580 static Vehicle *EnumCheckRoadVehCrashTrain(Vehicle *v, void *data)
    00581 {
    00582   const Vehicle *u = (Vehicle*)data;
    00583
    00584   return
    00585     v->type == VEH_TRAIN &&
    00586     abs(v->z_pos - u->z_pos) <= 6 &&
    00587     abs(v->x_pos - u->x_pos) <= 4 &&
    00588     abs(v->y_pos - u->y_pos) <= 4 ?
    00589       v : NULL;
    00590 }
    00591
    00592 static void RoadVehCrash(Vehicle *v)
    00593 {
    00594   uint16 pass = 1;
    00595
    00596   v->u.road.crashed_ctr++;
    00597
    00598   for (Vehicle *u = v; u != NULL; u = u->Next()) {
    00599     if (IsCargoInClass(u->cargo_type, CC_PASSENGERS)) pass += u->cargo.Count();
    00600
    00601     u->vehstatus |= VS_CRASHED;
    00602
    00603     MarkSingleVehicleDirty(u);
    00604   }
    00605
    00606   ClearSlot(v);
    00607
    00608   InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
    00609
    00610   AI::NewEvent(v->owner, new AIEventVehicleCrashed(v->index, v->tile, AIEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING));
    00611
    00612   SetDParam(0, pass);
    00613   AddNewsItem(
    00614     (pass == 1) ?
    00615       STR_9031_ROAD_VEHICLE_CRASH_DRIVER : STR_9032_ROAD_VEHICLE_CRASH_DIE,
    00616     NS_ACCIDENT_VEHICLE,
    00617     v->index,
    00618     0
    00619   );
    00620
    00621   ModifyStationRatingAround(v->tile, v->owner, -160, 22);
    00622   SndPlayVehicleFx(SND_12_EXPLOSION, v);
    00623 }
    00624
    00625 static bool RoadVehCheckTrainCrash(Vehicle *v)
    00626 {
    00627   for (Vehicle *u = v; u != NULL; u = u->Next()) {
    00628     if (u->u.road.state == RVSB_WORMHOLE) continue;
    00629
    00630     TileIndex tile = u->tile;
    00631
    00632     if (!IsLevelCrossingTile(tile)) continue;
    00633
    00634     if (HasVehicleOnPosXY(v->x_pos, v->y_pos, u, EnumCheckRoadVehCrashTrain)) {
    00635       RoadVehCrash(v);
    00636       return true;
    00637     }
    00638   }
    00639
    00640   return false;
    00641 }
    00642
    00643 static void HandleBrokenRoadVeh(Vehicle *v)
    00644 {
    00645   if (v->breakdown_ctr != 1) {
    00646     v->breakdown_ctr = 1;
    00647     v->cur_speed = 0;
    00648
    00649     if (v->breakdowns_since_last_service != 255)
    00650       v->breakdowns_since_last_service++;
    00651
    00652     InvalidateWindow(WC_VEHICLE_VIEW, v->index);
    00653     InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
    00654
    00655     if (!PlayVehicleSound(v, VSE_BREAKDOWN)) {
    00656       SndPlayVehicleFx((_settings_game.game_creation.landscape != LT_TOYLAND) ?
    00657         SND_0F_VEHICLE_BREAKDOWN : SND_35_COMEDY_BREAKDOWN, v);
    00658     }
    00659
    00660     if (!(v->vehstatus & VS_HIDDEN)) {
    00661       Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE);
    00662       if (u != NULL) u->u.effect.animation_state = v->breakdown_delay * 2;
    00663     }
    00664   }
    00665
    00666   if ((v->tick_counter & 1) == 0) {
    00667     if (--v->breakdown_delay == 0) {
    00668       v->breakdown_ctr = 0;
    00669       InvalidateWindow(WC_VEHICLE_VIEW, v->index);
    00670     }
    00671   }
    00672 }
    00673
    00674 TileIndex RoadVehicle::GetOrderStationLocation(StationID station)
    00675 {
    00676   if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
    00677
    00678   TileIndex dest;
    00679   if (YapfFindNearestRoadVehicleCompatibleStop(this, station, &dest)) {
    00680     return dest;
    00681   } else {
    00682     /* There is no stop left at the station, so don't even TRY to go there */
    00683     this->cur_order_index++;
    00684     return 0;
    00685   }
    00686 }
    00687
    00688 static void StartRoadVehSound(const Vehicle *v)
    00689 {
    00690   if (!PlayVehicleSound(v, VSE_START)) {
    00691     SoundFx s = RoadVehInfo(v->engine_type)->sfx;
    00692     if (s == SND_19_BUS_START_PULL_AWAY && (v->tick_counter & 3) == 0)
    00693       s = SND_1A_BUS_START_PULL_AWAY_WITH_HORN;
    00694     SndPlayVehicleFx(s, v);
    00695   }
    00696 }
    00697
    00698 struct RoadVehFindData {
    00699   int x;
    00700   int y;
    00701   const Vehicle *veh;
    00702   Vehicle *best;
    00703   uint best_diff;
    00704   Direction dir;
    00705 };
    00706
    00707 static Vehicle *EnumCheckRoadVehClose(Vehicle *v, void *data)
    00708 {
    00709   static const int8 dist_x[] = { -4, -8, -4, -1, 4, 8, 4, 1 };
    00710   static const int8 dist_y[] = { -4, -1, 4, 8, 4, 1, -4, -8 };
    00711
    00712   RoadVehFindData *rvf = (RoadVehFindData*)data;
    00713
    00714   short x_diff = v->x_pos - rvf->x;
    00715   short y_diff = v->y_pos - rvf->y;
    00716
    00717   if (v->type == VEH_ROAD &&
    00718       !v->IsInDepot() &&
    00719       abs(v->z_pos - rvf->veh->z_pos) < 6 &&
    00720       v->direction == rvf->dir &&
    00721       rvf->veh->First() != v->First() &&
    00722       (dist_x[v->direction] >= 0 || (x_diff > dist_x[v->direction] && x_diff <= 0)) &&
    00723       (dist_x[v->direction] <= 0 || (x_diff < dist_x[v->direction] && x_diff >= 0)) &&
    00724       (dist_y[v->direction] >= 0 || (y_diff > dist_y[v->direction] && y_diff <= 0)) &&
    00725       (dist_y[v->direction] <= 0 || (y_diff < dist_y[v->direction] && y_diff >= 0))) {
    00726     uint diff = abs(x_diff) + abs(y_diff);
    00727
    00728     if (diff < rvf->best_diff || (diff == rvf->best_diff && v->index < rvf->best->index)) {
    00729       rvf->best = v;
    00730       rvf->best_diff = diff;
    00731     }
    00732   }
    00733
    00734   return NULL;
    00735 }
    00736
    00737 static Vehicle *RoadVehFindCloseTo(Vehicle *v, int x, int y, Direction dir)
    00738 {
    00739   RoadVehFindData rvf;
    00740   Vehicle *front = v->First();
    00741
    00742   if (front->u.road.reverse_ctr != 0) return NULL;
    00743
    00744   rvf.x = x;
    00745   rvf.y = y;
    00746   rvf.dir = dir;
    00747   rvf.veh = v;
    00748   rvf.best_diff = UINT_MAX;
    00749
    00750   if (front->u.road.state == RVSB_WORMHOLE) {
    00751     FindVehicleOnPos(v->tile, &rvf, EnumCheckRoadVehClose);
    00752     FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), &rvf, EnumCheckRoadVehClose);
    00753   } else {
    00754     FindVehicleOnPosXY(x, y, &rvf, EnumCheckRoadVehClose);
    00755   }
    00756
    00757   /* This code protects a roadvehicle from being blocked for ever
    00758    * If more than 1480 / 74 days a road vehicle is blocked, it will
    00759    * drive just through it. The ultimate backup-code of TTD.
    00760    * It can be disabled. */
    00761   if (rvf.best_diff == UINT_MAX) {
    00762     front->u.road.blocked_ctr = 0;
    00763     return NULL;
    00764   }
    00765
    00766   if (++front->u.road.blocked_ctr > 1480) return NULL;
    00767
    00768   return rvf.best;
    00769 }
    00770
    00771 static void RoadVehArrivesAt(const Vehicle *v, Station *st)
    00772 {
    00773   if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) {
    00774     /* Check if station was ever visited before */
    00775     if (!(st->had_vehicle_of_type & HVOT_BUS)) {
    00776       st->had_vehicle_of_type |= HVOT_BUS;
    00777       SetDParam(0, st->index);
    00778       AddNewsItem(
    00779         v->u.road.roadtype == ROADTYPE_ROAD ? STR_902F_CITIZENS_CELEBRATE_FIRST : STR_CITIZENS_CELEBRATE_FIRST_PASSENGER_TRAM,
    00780         (v->owner == _local_company) ? NS_ARRIVAL_COMPANY : NS_ARRIVAL_OTHER,
    00781         v->index,
    00782         st->index
    00783       );
    00784       AI::NewEvent(v->owner, new AIEventStationFirstVehicle(st->index, v->index));
    00785     }
    00786   } else {
    00787     /* Check if station was ever visited before */
    00788     if (!(st->had_vehicle_of_type & HVOT_TRUCK)) {
    00789       st->had_vehicle_of_type |= HVOT_TRUCK;
    00790       SetDParam(0, st->index);
    00791       AddNewsItem(
    00792         v->u.road.roadtype == ROADTYPE_ROAD ? STR_9030_CITIZENS_CELEBRATE_FIRST : STR_CITIZENS_CELEBRATE_FIRST_CARGO_TRAM,
    00793         (v->owner == _local_company) ? NS_ARRIVAL_COMPANY : NS_ARRIVAL_OTHER,
    00794         v->index,
    00795         st->index
    00796       );
    00797       AI::NewEvent(v->owner, new AIEventStationFirstVehicle(st->index, v->index));
    00798     }
    00799   }
    00800 }
    00801
    00802 static int RoadVehAccelerate(Vehicle *v)
    00803 {
    00804   uint oldspeed = v->cur_speed;
    00805   uint accel = 256 + (v->u.road.overtaking != 0 ? 256 : 0);
    00806   uint spd = v->subspeed + accel;
    00807
    00808   v->subspeed = (uint8)spd;
    00809
    00810   int tempmax = v->max_speed;
    00811   if (v->cur_speed > v->max_speed) {
    00812     tempmax = v->cur_speed - (v->cur_speed / 10) - 1;
    00813   }
    00814
    00815   v->cur_speed = spd = Clamp(v->cur_speed + ((int)spd >> 8), 0, tempmax);
    00816
    00817   /* Apply bridge speed limit */
    00818   if (v->u.road.state == RVSB_WORMHOLE && !(v->vehstatus & VS_HIDDEN)) {
    00819     v->cur_speed = min(v->cur_speed, GetBridgeSpec(GetBridgeType(v->tile))->speed * 2);
    00820   }
    00821
    00822   /* Update statusbar only if speed has changed to save CPU time */
    00823   if (oldspeed != v->cur_speed) {
    00824     if (_settings_client.gui.vehicle_speed) {
    00825       InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
    00826     }
    00827   }
    00828
    00829   /* Speed is scaled in the same manner as for trains. @see train_cmd.cpp */
    00830   int scaled_spd = spd * 3 >> 2;
    00831
    00832   scaled_spd += v->progress;
    00833   v->progress = 0;
    00834   return scaled_spd;
    00835 }
    00836
    00837 static Direction RoadVehGetNewDirection(const Vehicle *v, int x, int y)
    00838 {
    00839   static const Direction _roadveh_new_dir[] = {
    00840     DIR_N , DIR_NW, DIR_W , INVALID_DIR,
    00841     DIR_NE, DIR_N , DIR_SW, INVALID_DIR,
    00842     DIR_E , DIR_SE, DIR_S
    00843   };
    00844
    00845   x = x - v->x_pos + 1;
    00846   y = y - v->y_pos + 1;
    00847
    00848   if ((uint)x > 2 || (uint)y > 2) return v->direction;
    00849   return _roadveh_new_dir[y * 4 + x];
    00850 }
    00851
    00852 static Direction RoadVehGetSlidingDirection(const Vehicle *v, int x, int y)
    00853 {
    00854   Direction new_dir = RoadVehGetNewDirection(v, x, y);
    00855   Direction old_dir = v->direction;
    00856   DirDiff delta;
    00857
    00858   if (new_dir == old_dir) return old_dir;
    00859   delta = (DirDifference(new_dir, old_dir) > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT);
    00860   return ChangeDir(old_dir, delta);
    00861 }
    00862
    00863 struct OvertakeData {
    00864   const Vehicle *u;
    00865   const Vehicle *v;
    00866   TileIndex tile;
    00867   Trackdir trackdir;
    00868 };
    00869
    00870 static Vehicle *EnumFindVehBlockingOvertake(Vehicle *v, void *data)
    00871 {
    00872   const OvertakeData *od = (OvertakeData*)data;
    00873
    00874   return
    00875     v->type == VEH_ROAD && v->First() == v && v != od->u && v != od->v ?
    00876       v : NULL;
    00877 }
    00878
    00885 static bool CheckRoadBlockedForOvertaking(OvertakeData *od)
    00886 {
    00887   TrackStatus ts = GetTileTrackStatus(od->tile, TRANSPORT_ROAD, od->v->u.road.compatible_roadtypes);
    00888   TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts);
    00889   TrackdirBits red_signals = TrackStatusToRedSignals(ts); // barred level crossing
    00890   TrackBits trackbits = TrackdirBitsToTrackBits(trackdirbits);
    00891
    00892   /* Track does not continue along overtaking direction || track has junction || levelcrossing is barred */
    00893   if (!HasBit(trackdirbits, od->trackdir) || (trackbits & ~TRACK_BIT_CROSS) || (red_signals != TRACKDIR_BIT_NONE)) return true;
    00894
    00895   /* Are there more vehicles on the tile except the two vehicles involved in overtaking */
    00896   return HasVehicleOnPos(od->tile, od, EnumFindVehBlockingOvertake);
    00897 }
    00898
    00899 static void RoadVehCheckOvertake(Vehicle *v, Vehicle *u)
    00900 {
    00901   OvertakeData od;
    00902
    00903   od.v = v;
    00904   od.u = u;
    00905
    00906   if (u->max_speed >= v->max_speed &&
    00907       !(u->vehstatus & VS_STOPPED) &&
    00908       u->cur_speed != 0) {
    00909     return;
    00910   }
    00911
    00912   /* Trams can't overtake other trams */
    00913   if (v->u.road.roadtype == ROADTYPE_TRAM) return;
    00914
    00915   /* Don't overtake in stations */
    00916   if (IsTileType(v->tile, MP_STATION)) return;
    00917
    00918   /* For now, articulated road vehicles can't overtake anything. */
    00919   if (RoadVehHasArticPart(v)) return;
    00920
    00921   /* Vehicles are not driving in same direction || direction is not a diagonal direction */
    00922   if (v->direction != u->direction || !(v->direction & 1)) return;
    00923
    00924   /* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */
    00925   if (v->u.road.state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->u.road.state & RVSB_TRACKDIR_MASK))) return;
    00926
    00927   od.trackdir = DiagDirToDiagTrackdir(DirToDiagDir(v->direction));
    00928
    00929   /* Are the current and the next tile suitable for overtaking?
    00930    *  - Does the track continue along od.trackdir
    00931    *  - No junctions
    00932    *  - No barred levelcrossing
    00933    *  - No other vehicles in the way
    00934    */
    00935   od.tile = v->tile;
    00936   if (CheckRoadBlockedForOvertaking(&od)) return;
    00937
    00938   od.tile = v->tile + TileOffsByDiagDir(DirToDiagDir(v->direction));
    00939   if (CheckRoadBlockedForOvertaking(&od)) return;
    00940
    00941   if (od.u->cur_speed == 0 || od.u->vehstatus& VS_STOPPED) {
    00942     v->u.road.overtaking_ctr = 0x11;
    00943     v->u.road.overtaking = 0x10;
    00944   } else {
    00945 //    if (CheckRoadBlockedForOvertaking(&od)) return;
    00946     v->u.road.overtaking_ctr = 0;
    00947     v->u.road.overtaking = 0x10;
    00948   }
    00949 }
    00950
    00951 static void RoadZPosAffectSpeed(Vehicle *v, byte old_z)
    00952 {
    00953   if (old_z == v->z_pos) return;
    00954
    00955   if (old_z < v->z_pos) {
    00956     v->cur_speed = v->cur_speed * 232 / 256; // slow down by ~10%
    00957   } else {
    00958     uint16 spd = v->cur_speed + 2;
    00959     if (spd <= v->max_speed) v->cur_speed = spd;
    00960   }
    00961 }
    00962
    00963 static int PickRandomBit(uint bits)
    00964 {
    00965   uint i;
    00966   uint num = RandomRange(CountBits(bits));
    00967
    00968   for (i = 0; !(bits & 1) || (int)--num >= 0; bits >>= 1, i++) {}
    00969   return i;
    00970 }
    00971
    00972 struct FindRoadToChooseData {
    00973   TileIndex dest;
    00974   uint maxtracklen;
    00975   uint mindist;
    00976 };
    00977
    00978 static bool EnumRoadTrackFindDist(TileIndex tile, void *data, Trackdir trackdir, uint length)
    00979 {
    00980   FindRoadToChooseData *frd = (FindRoadToChooseData*)data;
    00981   uint dist = DistanceManhattan(tile, frd->dest);
    00982
    00983   if (dist <= frd->mindist) {
    00984     if (dist != frd->mindist || length < frd->maxtracklen) {
    00985       frd->maxtracklen = length;
    00986     }
    00987     frd->mindist = dist;
    00988   }
    00989   return false;
    00990 }
    00991
    00992 static inline NPFFoundTargetData PerfNPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, bool ignore_start_tile, NPFFindStationOrTileData *target, TransportType type, uint sub_type, Owner owner, RailTypes railtypes)
    00993 {
    00994
    00995   void *perf = NpfBeginInterval();
    00996   NPFFoundTargetData ret = NPFRouteToStationOrTile(tile, trackdir, ignore_start_tile, target, type, sub_type, owner, railtypes);
    00997   int t = NpfEndInterval(perf);
    00998   DEBUG(yapf, 4, "[NPFR] %d us - %d rounds - %d open - %d closed -- ", t, 0, _aystar_stats_open_size, _aystar_stats_closed_size);
    00999   return ret;
    01000 }
    01001
    01010 static Trackdir RoadFindPathToDest(Vehicle *v, TileIndex tile, DiagDirection enterdir)
    01011 {
    01012 #define return_track(x) { best_track = (Trackdir)x; goto found_best_track; }
    01013
    01014   TileIndex desttile;
    01015   FindRoadToChooseData frd;
    01016   Trackdir best_track;
    01017
    01018   TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes);
    01019   TrackdirBits red_signals = TrackStatusToRedSignals(ts); // crossing
    01020   TrackdirBits trackdirs = TrackStatusToTrackdirBits(ts);
    01021
    01022   if (IsTileType(tile, MP_ROAD)) {
    01023     if (IsRoadDepot(tile) && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir || (GetRoadTypes(tile) & v->u.road.compatible_roadtypes) == 0)) {
    01024       /* Road depot owned by another company or with the wrong orientation */
    01025       trackdirs = TRACKDIR_BIT_NONE;
    01026     }
    01027   } else if (IsTileType(tile, MP_STATION) && IsStandardRoadStopTile(tile)) {
    01028     /* Standard road stop (drive-through stops are treated as normal road) */
    01029
    01030     if (!IsTileOwner(tile, v->owner) || GetRoadStopDir(tile) == enterdir || RoadVehHasArticPart(v)) {
    01031       /* different station owner or wrong orientation or the vehicle has articulated parts */
    01032       trackdirs = TRACKDIR_BIT_NONE;
    01033     } else {
    01034       /* Our station */
    01035       RoadStopType rstype = IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? ROADSTOP_BUS : ROADSTOP_TRUCK;
    01036
    01037       if (GetRoadStopType(tile) != rstype) {
    01038         /* Wrong station type */
    01039         trackdirs = TRACKDIR_BIT_NONE;
    01040       } else {
    01041         /* Proper station type, check if there is free loading bay */
    01042         if (!_settings_game.pf.roadveh_queue && IsStandardRoadStopTile(tile) &&
    01043             !GetRoadStopByTile(tile, rstype)->HasFreeBay()) {
    01044           /* Station is full and RV queuing is off */
    01045           trackdirs = TRACKDIR_BIT_NONE;
    01046         }
    01047       }
    01048     }
    01049   }
    01050   /* The above lookups should be moved to GetTileTrackStatus in the
    01051    * future, but that requires more changes to the pathfinder and other
    01052    * stuff, probably even more arguments to GTTS.
    01053    */
    01054
    01055   /* Remove tracks unreachable from the enter dir */
    01056   trackdirs &= _road_enter_dir_to_reachable_trackdirs[enterdir];
    01057   if (trackdirs == TRACKDIR_BIT_NONE) {
    01058     /* No reachable tracks, so we'll reverse */
    01059     return_track(_road_reverse_table[enterdir]);
    01060   }
    01061
    01062   if (v->u.road.reverse_ctr != 0) {
    01063     bool reverse = true;
    01064     if (v->u.road.roadtype == ROADTYPE_TRAM) {
    01065       /* Trams may only reverse on a tile if it contains at least the straight
    01066        * trackbits or when it is a valid turning tile (i.e. one roadbit) */
    01067       RoadBits rb = GetAnyRoadBits(tile, ROADTYPE_TRAM);
    01068       RoadBits straight = AxisToRoadBits(DiagDirToAxis(enterdir));
    01069       reverse = ((rb & straight) == straight) ||
    01070                 (rb == DiagDirToRoadBits(enterdir));
    01071     }
    01072     if (reverse) {
    01073       v->u.road.reverse_ctr = 0;
    01074       if (v->tile != tile) {
    01075         return_track(_road_reverse_table[enterdir]);
    01076       }
    01077     }
    01078   }
    01079
    01080   desttile = v->dest_tile;
    01081   if (desttile == 0) {
    01082     /* We've got no destination, pick a random track */
    01083     return_track(PickRandomBit(trackdirs));
    01084   }
    01085
    01086   /* Only one track to choose between? */
    01087   if (KillFirstBit(trackdirs) == TRACKDIR_BIT_NONE) {
    01088     return_track(FindFirstBit2x64(trackdirs));
    01089   }
    01090
    01091   switch (_settings_game.pf.pathfinder_for_roadvehs) {
    01092     case VPF_YAPF: { // YAPF
    01093       Trackdir trackdir = YapfChooseRoadTrack(v, tile, enterdir);
    01094       if (trackdir != INVALID_TRACKDIR) return_track(trackdir);
    01095       return_track(PickRandomBit(trackdirs));
    01096     } break;
    01097
    01098     case VPF_NPF: { // NPF
    01099       NPFFindStationOrTileData fstd;
    01100
    01101       NPFFillWithOrderData(&fstd, v);
    01102       Trackdir trackdir = DiagDirToDiagTrackdir(enterdir);
    01103       /* debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir); */
    01104
    01105       NPFFoundTargetData ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, true, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPES);
    01106       if (ftd.best_trackdir == INVALID_TRACKDIR) {
    01107         /* We are already at our target. Just do something
    01108          * @todo: maybe display error?
    01109          * @todo: go straight ahead if possible? */
    01110         return_track(FindFirstBit2x64(trackdirs));
    01111       } else {
    01112         /* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
    01113          * the direction we need to take to get there, if ftd.best_bird_dist is not 0,
    01114          * we did not find our target, but ftd.best_trackdir contains the direction leading
    01115          * to the tile closest to our target. */
    01116         return_track(ftd.best_trackdir);
    01117       }
    01118     } break;
    01119
    01120     default:
    01121     case VPF_OPF: { // OPF
    01122       DiagDirection dir;
    01123
    01124       if (IsTileType(desttile, MP_ROAD)) {
    01125         if (IsRoadDepot(desttile)) {
    01126           dir = GetRoadDepotDirection(desttile);
    01127           goto do_it;
    01128         }
    01129       } else if (IsTileType(desttile, MP_STATION)) {
    01130         /* For drive-through stops we can head for the actual station tile */
    01131         if (IsStandardRoadStopTile(desttile)) {
    01132           dir = GetRoadStopDir(desttile);
    01133 do_it:;
    01134           /* When we are heading for a depot or station, we just
    01135            * pretend we are heading for the tile in front, we'll
    01136            * see from there */
    01137           desttile += TileOffsByDiagDir(dir);
    01138           if (desttile == tile && trackdirs & _road_exit_dir_to_incoming_trackdirs[dir]) {
    01139             /* If we are already in front of the
    01140              * station/depot and we can get in from here,
    01141              * we enter */
    01142             return_track(FindFirstBit2x64(trackdirs & _road_exit_dir_to_incoming_trackdirs[dir]));
    01143           }
    01144         }
    01145       }
    01146       /* Do some pathfinding */
    01147       frd.dest = desttile;
    01148
    01149       best_track = INVALID_TRACKDIR;
    01150       uint best_dist = UINT_MAX;
    01151       uint best_maxlen = UINT_MAX;
    01152       uint bitmask = (uint)trackdirs;
    01153       uint i;
    01154       FOR_EACH_SET_BIT(i, bitmask) {
    01155         if (best_track == INVALID_TRACKDIR) best_track = (Trackdir)i; // in case we don't find the path, just pick a track
    01156         frd.maxtracklen = UINT_MAX;
    01157         frd.mindist = UINT_MAX;
    01158         FollowTrack(tile, PATHFIND_FLAGS_NONE, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, _road_pf_directions[i], EnumRoadTrackFindDist, NULL, &frd);
    01159
    01160         if (frd.mindist < best_dist || (frd.mindist == best_dist && frd.maxtracklen < best_maxlen)) {
    01161           best_dist = frd.mindist;
    01162           best_maxlen = frd.maxtracklen;
    01163           best_track = (Trackdir)i;
    01164         }
    01165       }
    01166     } break;
    01167   }
    01168
    01169 found_best_track:;
    01170
    01171   if (HasBit(red_signals, best_track)) return INVALID_TRACKDIR;
    01172
    01173   return best_track;
    01174 }
    01175
    01176 static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile)
    01177 {
    01178   if (_settings_game.pf.pathfinder_for_roadvehs == VPF_YAPF) {
    01179     /* use YAPF */
    01180     return YapfRoadVehDistanceToTile(v, tile);
    01181   }
    01182
    01183   /* use NPF */
    01184   Trackdir trackdir = GetVehicleTrackdir(v);
    01185   assert(trackdir != INVALID_TRACKDIR);
    01186
    01187   NPFFindStationOrTileData fstd;
    01188   fstd.dest_coords = tile;
    01189   fstd.station_index = INVALID_STATION; // indicates that the destination is a tile, not a station
    01190
    01191   uint dist = NPFRouteToStationOrTile(v->tile, trackdir, false, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPES).best_path_dist;
    01192   /* change units from NPF_TILE_LENGTH to # of tiles */
    01193   if (dist != UINT_MAX) dist = (dist + NPF_TILE_LENGTH - 1) / NPF_TILE_LENGTH;
    01194
    01195   return dist;
    01196 }
    01197
    01198 struct RoadDriveEntry {
    01199   byte x, y;
    01200 };
    01201
    01202 #include "table/roadveh_movement.h"
    01203
    01204 static const byte _road_veh_data_1[] = {
    01205   20, 20, 16, 16, 0, 0, 0, 0,
    01206   19, 19, 15, 15, 0, 0, 0, 0,
    01207   16, 16, 12, 12, 0, 0, 0, 0,
    01208   15, 15, 11, 11
    01209 };
    01210
    01211 static bool RoadVehLeaveDepot(Vehicle *v, bool first)
    01212 {
    01213   /* Don't leave if not all the wagons are in the depot. */
    01214   for (const Vehicle *u = v; u != NULL; u = u->Next()) {
    01215     if (u->u.road.state != RVSB_IN_DEPOT || u->tile != v->tile) return false;
    01216   }
    01217
    01218   DiagDirection dir = GetRoadDepotDirection(v->tile);
    01219   v->direction = DiagDirToDir(dir);
    01220
    01221   Trackdir tdir = _roadveh_depot_exit_trackdir[dir];
    01222   const RoadDriveEntry *rdp = _road_drive_data[v->u.road.roadtype][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + tdir];
    01223
    01224   int x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF);
    01225   int y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF);
    01226
    01227   if (first) {
    01228     if (RoadVehFindCloseTo(v, x, y, v->direction) != NULL) return true;
    01229
    01230     VehicleServiceInDepot(v);
    01231
    01232     StartRoadVehSound(v);
    01233
    01234     /* Vehicle is about to leave a depot */
    01235     v->cur_speed = 0;
    01236   }
    01237
    01238   v->vehstatus &= ~VS_HIDDEN;
    01239   v->u.road.state = tdir;
    01240   v->u.road.frame = RVC_DEPOT_START_FRAME;
    01241
    01242   SetRoadVehPosition(v, x, y, true);
    01243
    01244   InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
    01245
    01246   return true;
    01247 }
    01248
    01249 static Trackdir FollowPreviousRoadVehicle(const Vehicle *v, const Vehicle *prev, TileIndex tile, DiagDirection entry_dir, bool already_reversed)
    01250 {
    01251   if (prev->tile == v->tile && !already_reversed) {
    01252     /* If the previous vehicle is on the same tile as this vehicle is
    01253      * then it must have reversed. */
    01254     return _road_reverse_table[entry_dir];
    01255   }
    01256
    01257   byte prev_state = prev->u.road.state;
    01258   Trackdir dir;
    01259
    01260   if (prev_state == RVSB_WORMHOLE || prev_state == RVSB_IN_DEPOT) {
    01261     DiagDirection diag_dir = INVALID_DIAGDIR;
    01262
    01263     if (IsTileType(tile, MP_TUNNELBRIDGE)) {
    01264       diag_dir = GetTunnelBridgeDirection(tile);
    01265     } else if (IsRoadDepotTile(tile)) {
    01266       diag_dir = ReverseDiagDir(GetRoadDepotDirection(tile));
    01267     }
    01268
    01269     if (diag_dir == INVALID_DIAGDIR) return INVALID_TRACKDIR;
    01270     dir = DiagDirToDiagTrackdir(diag_dir);
    01271   } else {
    01272     if (already_reversed && prev->tile != tile) {
    01273       /*
    01274        * The vehicle has reversed, but did not go straight back.
    01275        * It immediatelly turn onto another tile. This means that
    01276        * the roadstate of the previous vehicle cannot be used
    01277        * as the direction we have to go with this vehicle.
    01278        *
    01279        * Next table is build in the following way:
    01280        *  - first row for when the vehicle in front went to the northern or
    01281        *    western tile, second for southern and eastern.
    01282        *  - columns represent the entry direction.
    01283        *  - cell values are determined by the Trackdir one has to take from
    01284        *    the entry dir (column) to the tile in north or south by only
    01285        *    going over the trackdirs used for turning 90 degrees, i.e.
    01286        *    TRACKDIR_{UPPER,RIGHT,LOWER,LEFT}_{N,E,S,W}.
    01287        */
    01288       Trackdir reversed_turn_lookup[2][DIAGDIR_END] = {
    01289         { TRACKDIR_UPPER_W, TRACKDIR_RIGHT_N, TRACKDIR_LEFT_N,  TRACKDIR_UPPER_E },
    01290         { TRACKDIR_RIGHT_S, TRACKDIR_LOWER_W, TRACKDIR_LOWER_E, TRACKDIR_LEFT_S  }};
    01291       dir = reversed_turn_lookup[prev->tile < tile ? 0 : 1][ReverseDiagDir(entry_dir)];
    01292     } else if (HasBit(prev_state, RVS_IN_DT_ROAD_STOP)) {
    01293       dir = (Trackdir)(prev_state & RVSB_ROAD_STOP_TRACKDIR_MASK);
    01294     } else if (prev_state < TRACKDIR_END) {
    01295       dir = (Trackdir)prev_state;
    01296     } else {
    01297       return INVALID_TRACKDIR;
    01298     }
    01299   }
    01300
    01301   /* Do some sanity checking. */
    01302   static const RoadBits required_roadbits[] = {
    01303     ROAD_X,            ROAD_Y,            ROAD_NW | ROAD_NE, ROAD_SW | ROAD_SE,
    01304     ROAD_NW | ROAD_SW, ROAD_NE | ROAD_SE, ROAD_X,            ROAD_Y
    01305   };
    01306   RoadBits required = required_roadbits[dir & 0x07];
    01307
    01308   if ((required & GetAnyRoadBits(tile, v->u.road.roadtype, true)) == ROAD_NONE) {
    01309     dir = INVALID_TRACKDIR;
    01310   }
    01311
    01312   return dir;
    01313 }
    01314
    01322 static bool CanBuildTramTrackOnTile(CompanyID c, TileIndex t, RoadBits r)
    01323 {
    01324   /* The 'current' company is not necessarily the owner of the vehicle. */
    01325   CompanyID original_company = _current_company;
    01326   _current_company = c;
    01327
    01328   CommandCost ret = DoCommand(t, ROADTYPE_TRAM << 4 | r, 0, DC_NONE, CMD_BUILD_ROAD);
    01329
    01330   _current_company = original_company;
    01331   return CmdSucceeded(ret);
    01332 }
    01333
    01334 static bool IndividualRoadVehicleController(Vehicle *v, const Vehicle *prev)
    01335 {
    01336   if (v->u.road.overtaking != 0)  {
    01337     if (IsTileType(v->tile, MP_STATION)) {
    01338       /* Force us to be not overtaking! */
    01339       v->u.road.overtaking = 0;
    01340     } else if (++v->u.road.overtaking_ctr >= 35) {
    01341       /* If overtaking just aborts at a random moment, we can have a out-of-bound problem,
    01342        *  if the vehicle started a corner. To protect that, only allow an abort of
    01343        *  overtake if we are on straight roads */
    01344       if (v->u.road.state < RVSB_IN_ROAD_STOP && IsStraightRoadTrackdir((Trackdir)v->u.road.state)) {
    01345         v->u.road.overtaking = 0;
    01346       }
    01347     }
    01348   }
    01349
    01350   /* If this vehicle is in a depot and we've reached this point it must be
    01351    * one of the articulated parts. It will stay in the depot until activated
    01352    * by the previous vehicle in the chain when it gets to the right place. */
    01353   if (v->IsInDepot()) return true;
    01354
    01355   if (v->u.road.state == RVSB_WORMHOLE) {
    01356     /* Vehicle is entering a depot or is on a bridge or in a tunnel */
    01357     GetNewVehiclePosResult gp = GetNewVehiclePos(v);
    01358
    01359     if (IsRoadVehFront(v)) {
    01360       const Vehicle *u = RoadVehFindCloseTo(v, gp.x, gp.y, v->direction);
    01361       if (u != NULL) {
    01362         v->cur_speed = u->First()->cur_speed;
    01363         return false;
    01364       }
    01365     }
    01366
    01367     if (IsTileType(gp.new_tile, MP_TUNNELBRIDGE) && HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
    01368       /* Vehicle has just entered a bridge or tunnel */
    01369       SetRoadVehPosition(v, gp.x, gp.y, true);
    01370       return true;
    01371     }
    01372
    01373     v->x_pos = gp.x;
    01374     v->y_pos = gp.y;
    01375     VehicleMove(v, !(v->vehstatus & VS_HIDDEN));
    01376     return true;
    01377   }
    01378
    01379   /* Get move position data for next frame.
    01380    * For a drive-through road stop use 'straight road' move data.
    01381    * In this case v->u.road.state is masked to give the road stop entry direction. */
    01382   RoadDriveEntry rd = _road_drive_data[v->u.road.roadtype][(
    01383     (HasBit(v->u.road.state, RVS_IN_DT_ROAD_STOP) ? v->u.road.state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->u.road.state) +
    01384     (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1];
    01385
    01386   if (rd.x & RDE_NEXT_TILE) {
    01387     TileIndex tile = v->tile + TileOffsByDiagDir((DiagDirection)(rd.x & 3));
    01388     Trackdir dir;
    01389
    01390     if (IsRoadVehFront(v)) {
    01391       /* If this is the front engine, look for the right path. */
    01392       dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3));
    01393     } else {
    01394       dir = FollowPreviousRoadVehicle(v, prev, tile, (DiagDirection)(rd.x & 3), false);
    01395     }
    01396
    01397     if (dir == INVALID_TRACKDIR) {
    01398       if (!IsRoadVehFront(v)) error("Disconnecting road vehicle.");
    01399       v->cur_speed = 0;
    01400       return false;
    01401     }
    01402
    01403 again:
    01404     uint start_frame = RVC_DEFAULT_START_FRAME;
    01405     if (IsReversingRoadTrackdir(dir)) {
    01406       /* Turning around */
    01407       if (v->u.road.roadtype == ROADTYPE_TRAM) {
    01408         /* Determine the road bits the tram needs to be able to turn around
    01409          * using the 'big' corner loop. */
    01410         RoadBits needed;
    01411         switch (dir) {
    01412           default: NOT_REACHED();
    01413           case TRACKDIR_RVREV_NE: needed = ROAD_SW; break;
    01414           case TRACKDIR_RVREV_SE: needed = ROAD_NW; break;
    01415           case TRACKDIR_RVREV_SW: needed = ROAD_NE; break;
    01416           case TRACKDIR_RVREV_NW: needed = ROAD_SE; break;
    01417         }
    01418         if ((v->Previous() != NULL && v->Previous()->tile == tile) ||
    01419             (IsRoadVehFront(v) && IsNormalRoadTile(tile) && !HasRoadWorks(tile) &&
    01420               (needed & GetRoadBits(tile, ROADTYPE_TRAM)) != ROAD_NONE)) {
    01421           /*
    01422            * Taking the 'big' corner for trams only happens when:
    01423            * - The previous vehicle in this (articulated) tram chain is
    01424            *   already on the 'next' tile, we just follow them regardless of
    01425            *   anything. When it is NOT on the 'next' tile, the tram started
    01426            *   doing a reversing turn when the piece of tram track on the next
    01427            *   tile did not exist yet. Do not use the big tram loop as that is
    01428            *   going to cause the tram to split up.
    01429            * - Or the front of the tram can drive over the next tile.
    01430            */
    01431         } else if (!IsRoadVehFront(v) || !CanBuildTramTrackOnTile(v->owner, tile, needed) || ((~needed & GetAnyRoadBits(v->tile, ROADTYPE_TRAM, false)) == ROAD_NONE)) {
    01432           /*
    01433            * Taking the 'small' corner for trams only happens when:
    01434            * - We are not the from vehicle of an articulated tram.
    01435            * - Or when the company cannot build on the next tile.
    01436            *
    01437            * The 'small' corner means that the vehicle is on the end of a
    01438            * tram track and needs to start turning there. To do this properly
    01439            * the tram needs to start at an offset in the tram turning 'code'
    01440            * for 'big' corners. It furthermore does not go to the next tile,
    01441            * so that needs to be fixed too.
    01442            */
    01443           tile = v->tile;
    01444           start_frame = RVC_TURN_AROUND_START_FRAME_SHORT_TRAM;
    01445         } else {
    01446           /* The company can build on the next tile, so wait till (s)he does. */
    01447           v->cur_speed = 0;
    01448           return false;
    01449         }
    01450       } else if (IsNormalRoadTile(v->tile) && GetDisallowedRoadDirections(v->tile) != DRD_NONE) {
    01451         v->cur_speed = 0;
    01452         return false;
    01453       } else {
    01454         tile = v->tile;
    01455       }
    01456     }
    01457
    01458     /* Get position data for first frame on the new tile */
    01459     const RoadDriveEntry *rdp = _road_drive_data[v->u.road.roadtype][(dir + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking];
    01460
    01461     int x = TileX(tile) * TILE_SIZE + rdp[start_frame].x;
    01462     int y = TileY(tile) * TILE_SIZE + rdp[start_frame].y;
    01463
    01464     Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
    01465     if (IsRoadVehFront(v)) {
    01466       Vehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
    01467       if (u != NULL) {
    01468         v->cur_speed = u->First()->cur_speed;
    01469         return false;
    01470       }
    01471     }
    01472
    01473     uint32 r = VehicleEnterTile(v, tile, x, y);
    01474     if (HasBit(r, VETS_CANNOT_ENTER)) {
    01475       if (!IsTileType(tile, MP_TUNNELBRIDGE)) {
    01476         v->cur_speed = 0;
    01477         return false;
    01478       }
    01479       /* Try an about turn to re-enter the previous tile */
    01480       dir = _road_reverse_table[rd.x & 3];
    01481       goto again;
    01482     }
    01483
    01484     if (IsInsideMM(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) && IsTileType(v->tile, MP_STATION)) {
    01485       if (IsReversingRoadTrackdir(dir) && IsInsideMM(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
    01486         /* New direction is trying to turn vehicle around.
    01487          * We can't turn at the exit of a road stop so wait.*/
    01488         v->cur_speed = 0;
    01489         return false;
    01490       }
    01491       if (IsRoadStop(v->tile)) {
    01492         RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile));
    01493
    01494         /* Vehicle is leaving a road stop tile, mark bay as free
    01495          * For drive-through stops, only do it if the vehicle stopped here */
    01496         if (IsStandardRoadStopTile(v->tile) || HasBit(v->u.road.state, RVS_IS_STOPPING)) {
    01497           rs->FreeBay(HasBit(v->u.road.state, RVS_USING_SECOND_BAY));
    01498           ClrBit(v->u.road.state, RVS_IS_STOPPING);
    01499         }
    01500         if (IsStandardRoadStopTile(v->tile)) rs->SetEntranceBusy(false);
    01501       }
    01502     }
    01503
    01504     if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
    01505       v->tile = tile;
    01506       v->u.road.state = (byte)dir;
    01507       v->u.road.frame = start_frame;
    01508     }
    01509     if (new_dir != v->direction) {
    01510       v->direction = new_dir;
    01511       v->cur_speed -= v->cur_speed >> 2;
    01512     }
    01513
    01514     RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, true));
    01515     return true;
    01516   }
    01517
    01518   if (rd.x & RDE_TURNED) {
    01519     /* Vehicle has finished turning around, it will now head back onto the same tile */
    01520     Trackdir dir;
    01521     uint turn_around_start_frame = RVC_TURN_AROUND_START_FRAME;
    01522
    01523     RoadBits tram;
    01524     if (v->u.road.roadtype == ROADTYPE_TRAM && !IsRoadDepotTile(v->tile) && CountBits(tram = GetAnyRoadBits(v->tile, ROADTYPE_TRAM, true)) == 1) {
    01525       /*
    01526        * The tram is turning around with one tram 'roadbit'. This means that
    01527        * it is using the 'big' corner 'drive data'. However, to support the
    01528        * trams to take a small corner, there is a 'turned' marker in the middle
    01529        * of the turning 'drive data'. When the tram took the long corner, we
    01530        * will still use the 'big' corner drive data, but we advance it one
    01531        * frame. We furthermore set the driving direction so the turning is
    01532        * going to be properly shown.
    01533        */
    01534       turn_around_start_frame = RVC_START_FRAME_AFTER_LONG_TRAM;
    01535       switch (rd.x & 0x3) {
    01536         default: NOT_REACHED();
    01537         case DIAGDIR_NW: dir = TRACKDIR_RVREV_SE; break;
    01538         case DIAGDIR_NE: dir = TRACKDIR_RVREV_SW; break;
    01539         case DIAGDIR_SE: dir = TRACKDIR_RVREV_NW; break;
    01540         case DIAGDIR_SW: dir = TRACKDIR_RVREV_NE; break;
    01541       }
    01542     } else {
    01543       if (IsRoadVehFront(v)) {
    01544         /* If this is the front engine, look for the right path. */
    01545         dir = RoadFindPathToDest(v, v->tile, (DiagDirection)(rd.x & 3));
    01546       } else {
    01547         dir = FollowPreviousRoadVehicle(v, prev, v->tile, (DiagDirection)(rd.x & 3), true);
    01548       }
    01549     }
    01550
    01551     if (dir == INVALID_TRACKDIR) {
    01552       v->cur_speed = 0;
    01553       return false;
    01554     }
    01555
    01556     const RoadDriveEntry *rdp = _road_drive_data[v->u.road.roadtype][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + dir];
    01557
    01558     int x = TileX(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].x;
    01559     int y = TileY(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].y;
    01560
    01561     Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
    01562     if (IsRoadVehFront(v) && RoadVehFindCloseTo(v, x, y, new_dir) != NULL) return false;
    01563
    01564     uint32 r = VehicleEnterTile(v, v->tile, x, y);
    01565     if (HasBit(r, VETS_CANNOT_ENTER)) {
    01566       v->cur_speed = 0;
    01567       return false;
    01568     }
    01569
    01570     v->u.road.state = dir;
    01571     v->u.road.frame = turn_around_start_frame;
    01572
    01573     if (new_dir != v->direction) {
    01574       v->direction = new_dir;
    01575       v->cur_speed -= v->cur_speed >> 2;
    01576     }
    01577
    01578     RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, true));
    01579     return true;
    01580   }
    01581
    01582   /* This vehicle is not in a wormhole and it hasn't entered a new tile. If
    01583    * it's on a depot tile, check if it's time to activate the next vehicle in
    01584    * the chain yet. */
    01585   if (v->Next() != NULL && IsRoadDepotTile(v->tile)) {
    01586     if (v->u.road.frame == v->u.road.cached_veh_length + RVC_DEPOT_START_FRAME) {
    01587       RoadVehLeaveDepot(v->Next(), false);
    01588     }
    01589   }
    01590
    01591   /* Calculate new position for the vehicle */
    01592   int x = (v->x_pos & ~15) + (rd.x & 15);
    01593   int y = (v->y_pos & ~15) + (rd.y & 15);
    01594
    01595   Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
    01596
    01597   if (IsRoadVehFront(v) && !IsInsideMM(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
    01598     /* Vehicle is not in a road stop.
    01599      * Check for another vehicle to overtake */
    01600     Vehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
    01601
    01602     if (u != NULL) {
    01603       u = u->First();
    01604       /* There is a vehicle in front overtake it if possible */
    01605       if (v->u.road.overtaking == 0) RoadVehCheckOvertake(v, u);
    01606       if (v->u.road.overtaking == 0) v->cur_speed = u->cur_speed;
    01607       return false;
    01608     }
    01609   }
    01610
    01611   Direction old_dir = v->direction;
    01612   if (new_dir != old_dir) {
    01613     v->direction = new_dir;
    01614     v->cur_speed -= (v->cur_speed >> 2);
    01615     if (old_dir != v->u.road.state) {
    01616       /* The vehicle is in a road stop */
    01617       SetRoadVehPosition(v, v->x_pos, v->y_pos, true);
    01618       /* Note, return here means that the frame counter is not incremented
    01619        * for vehicles changing direction in a road stop. This causes frames to
    01620        * be repeated. (XXX) Is this intended? */
    01621       return true;
    01622     }
    01623   }
    01624
    01625   /* If the vehicle is in a normal road stop and the frame equals the stop frame OR
    01626    * if the vehicle is in a drive-through road stop and this is the destination station
    01627    * and it's the correct type of stop (bus or truck) and the frame equals the stop frame...
    01628    * (the station test and stop type test ensure that other vehicles, using the road stop as
    01629    * a through route, do not stop) */
    01630   if (IsRoadVehFront(v) && ((IsInsideMM(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) &&
    01631       _road_veh_data_1[v->u.road.state - RVSB_IN_ROAD_STOP + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)] == v->u.road.frame) ||
    01632       (IsInsideMM(v->u.road.state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
    01633       v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
    01634       v->owner == GetTileOwner(v->tile) &&
    01635       GetRoadStopType(v->tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? ROADSTOP_BUS : ROADSTOP_TRUCK) &&
    01636       v->u.road.frame == RVC_DRIVE_THROUGH_STOP_FRAME))) {
    01637
    01638     RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile));
    01639     Station *st = GetStationByTile(v->tile);
    01640
    01641     /* Vehicle is at the stop position (at a bay) in a road stop.
    01642      * Note, if vehicle is loading/unloading it has already been handled,
    01643      * so if we get here the vehicle has just arrived or is just ready to leave. */
    01644     if (!v->current_order.IsType(OT_LEAVESTATION)) {
    01645       /* Vehicle has arrived at a bay in a road stop */
    01646
    01647       if (IsDriveThroughStopTile(v->tile)) {
    01648         TileIndex next_tile = TILE_ADD(v->tile, TileOffsByDir(v->direction));
    01649         RoadStopType type = IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? ROADSTOP_BUS : ROADSTOP_TRUCK;
    01650
    01651         /* Check if next inline bay is free */
    01652         if (IsDriveThroughStopTile(next_tile) && (GetRoadStopType(next_tile) == type) && GetStationIndex(v->tile) == GetStationIndex(next_tile)) {
    01653           RoadStop *rs_n = GetRoadStopByTile(next_tile, type);
    01654
    01655           if (rs_n->IsFreeBay(HasBit(v->u.road.state, RVS_USING_SECOND_BAY)) && rs_n->num_vehicles < RoadStop::MAX_VEHICLES) {
    01656             /* Bay in next stop along is free - use it */
    01657             ClearSlot(v);
    01658             rs_n->num_vehicles++;
    01659             v->u.road.slot = rs_n;
    01660             v->dest_tile = rs_n->xy;
    01661             v->u.road.slot_age = 14;
    01662
    01663             v->u.road.frame++;
    01664             RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, false));
    01665             return true;
    01666           }
    01667         }
    01668       }
    01669
    01670       rs->SetEntranceBusy(false);
    01671
    01672       v->last_station_visited = st->index;
    01673
    01674       if (IsDriveThroughStopTile(v->tile) || (v->current_order.IsType(OT_GOTO_STATION) && v->current_order.GetDestination() == st->index)) {
    01675         RoadVehArrivesAt(v, st);
    01676         v->BeginLoading();
    01677         return false;
    01678       }
    01679     } else {
    01680       /* Vehicle is ready to leave a bay in a road stop */
    01681       if (rs->IsEntranceBusy()) {
    01682         /* Road stop entrance is busy, so wait as there is nowhere else to go */
    01683         v->cur_speed = 0;
    01684         return false;
    01685       }
    01686       v->current_order.Free();
    01687       ClearSlot(v);
    01688     }
    01689
    01690     if (IsStandardRoadStopTile(v->tile)) rs->SetEntranceBusy(true);
    01691
    01692     if (rs == v->u.road.slot) {
    01693       /* We are leaving the correct station */
    01694       ClearSlot(v);
    01695     } else if (v->u.road.slot != NULL) {
    01696       /* We are leaving the wrong station
    01697        * XXX The question is .. what to do? Actually we shouldn't be here
    01698        * but I guess we need to clear the slot */
    01699       DEBUG(ms, 0, "Vehicle %d (index %d) arrived at wrong stop", v->unitnumber, v->index);
    01700       if (v->tile != v->dest_tile) {
    01701         DEBUG(ms, 2, " current tile 0x%X is not destination tile 0x%X. Route problem", v->tile, v->dest_tile);
    01702       }
    01703       if (v->dest_tile != v->u.road.slot->xy) {
    01704         DEBUG(ms, 2, " stop tile 0x%X is not destination tile 0x%X. Multistop desync", v->u.road.slot->xy, v->dest_tile);
    01705       }
    01706       if (!v->current_order.IsType(OT_GOTO_STATION)) {
    01707         DEBUG(ms, 2, " current order type (%d) is not OT_GOTO_STATION", v->current_order.GetType());
    01708       } else {
    01709         if (v->current_order.GetDestination() != st->index)
    01710           DEBUG(ms, 2, " current station %d is not target station in current_order.station (%d)",
    01711               st->index, v->current_order.GetDestination());
    01712       }
    01713
    01714       DEBUG(ms, 2, " force a slot clearing");
    01715       ClearSlot(v);
    01716     }
    01717
    01718     StartRoadVehSound(v);
    01719     InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
    01720   }
    01721
    01722   /* Check tile position conditions - i.e. stop position in depot,
    01723    * entry onto bridge or into tunnel */
    01724   uint32 r = VehicleEnterTile(v, v->tile, x, y);
    01725   if (HasBit(r, VETS_CANNOT_ENTER)) {
    01726     v->cur_speed = 0;
    01727     return false;
    01728   }
    01729
    01730   if (v->current_order.IsType(OT_LEAVESTATION) && IsDriveThroughStopTile(v->tile)) {
    01731     v->current_order.Free();
    01732     ClearSlot(v);
    01733   }
    01734
    01735   /* Move to next frame unless vehicle arrived at a stop position
    01736    * in a depot or entered a tunnel/bridge */
    01737   if (!HasBit(r, VETS_ENTERED_WORMHOLE)) v->u.road.frame++;
    01738
    01739   RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, true));
    01740   return true;
    01741 }
    01742
    01743 static void RoadVehController(Vehicle *v)
    01744 {
    01745   /* decrease counters */
    01746   v->tick_counter++;
    01747   v->current_order_time++;
    01748   if (v->u.road.reverse_ctr != 0) v->u.road.reverse_ctr--;
    01749
    01750   /* handle crashed */
    01751   if (v->vehstatus & VS_CRASHED) {
    01752     RoadVehIsCrashed(v);
    01753     return;
    01754   }
    01755
    01756   RoadVehCheckTrainCrash(v);
    01757
    01758   /* road vehicle has broken down? */
    01759   if (v->breakdown_ctr != 0) {
    01760     if (v->breakdown_ctr <= 2) {
    01761       HandleBrokenRoadVeh(v);
    01762       return;
    01763     }
    01764     if (!v->current_order.IsType(OT_LOADING)) v->breakdown_ctr--;
    01765   }
    01766
    01767   if (v->vehstatus & VS_STOPPED) return;
    01768
    01769   ProcessOrders(v);
    01770   v->HandleLoading();
    01771
    01772   if (v->current_order.IsType(OT_LOADING)) return;
    01773
    01774   if (v->IsInDepot() && RoadVehLeaveDepot(v, true)) return;
    01775
    01776   /* Check how far the vehicle needs to proceed */
    01777   int j = RoadVehAccelerate(v);
    01778
    01779   int adv_spd = (v->direction & 1) ? 192 : 256;
    01780   while (j >= adv_spd) {
    01781     j -= adv_spd;
    01782
    01783     Vehicle *u = v;
    01784     for (Vehicle *prev = NULL; u != NULL; prev = u, u = u->Next()) {
    01785       if (!IndividualRoadVehicleController(u, prev)) break;
    01786     }
    01787
    01788     /* 192 spd used for going straight, 256 for going diagonally. */
    01789     adv_spd = (v->direction & 1) ? 192 : 256;
    01790
    01791     /* Test for a collision, but only if another movement will occur. */
    01792     if (j >= adv_spd && RoadVehCheckTrainCrash(v)) break;
    01793   }
    01794
    01795   for (Vehicle *u = v; u != NULL; u = u->Next()) {
    01796     if ((u->vehstatus & VS_HIDDEN) != 0) continue;
    01797
    01798     u->UpdateViewport(false, false);
    01799   }
    01800
    01801   if (v->progress == 0) v->progress = j;
    01802 }
    01803
    01804 static void AgeRoadVehCargo(Vehicle *v)
    01805 {
    01806   if (_age_cargo_skip_counter != 0) return;
    01807   v->cargo.AgeCargo();
    01808 }
    01809
    01810 void RoadVehicle::Tick()
    01811 {
    01812   AgeRoadVehCargo(this);
    01813
    01814   if (IsRoadVehFront(this)) {
    01815     if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
    01816     RoadVehController(this);
    01817   }
    01818 }
    01819
    01820 static void CheckIfRoadVehNeedsService(Vehicle *v)
    01821 {
    01822   /* If we already got a slot at a stop, use that FIRST, and go to a depot later */
    01823   if (v->u.road.slot != NULL || _settings_game.vehicle.servint_roadveh == 0 || !v->NeedsAutomaticServicing()) return;
    01824   if (v->IsInDepot()) {
    01825     VehicleServiceInDepot(v);
    01826     return;
    01827   }
    01828
    01829   /* XXX If we already have a depot order, WHY do we search over and over? */
    01830   const Depot *depot = FindClosestRoadDepot(v);
    01831
    01832   if (depot == NULL || DistanceManhattan(v->tile, depot->xy) > 12) {
    01833     if (v->current_order.IsType(OT_GOTO_DEPOT)) {
    01834       v->current_order.MakeDummy();
    01835       InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
    01836     }
    01837     return;
    01838   }
    01839
    01840   if (v->current_order.IsType(OT_GOTO_DEPOT) &&
    01841       v->current_order.GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS &&
    01842       !Chance16(1, 20)) {
    01843     return;
    01844   }
    01845
    01846   if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
    01847   ClearSlot(v);
    01848
    01849   v->current_order.MakeGoToDepot(depot->index, ODTFB_SERVICE);
    01850   v->dest_tile = depot->xy;
    01851   InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
    01852 }
    01853
    01854 void RoadVehicle::OnNewDay()
    01855 {
    01856   if (!IsRoadVehFront(this)) return;
    01857
    01858   if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
    01859   if (this->u.road.blocked_ctr == 0) CheckVehicleBreakdown(this);
    01860
    01861   AgeVehicle(this);
    01862   CheckIfRoadVehNeedsService(this);
    01863
    01864   CheckOrders(this);
    01865
    01866   /* Current slot has expired */
    01867   if (this->current_order.IsType(OT_GOTO_STATION) && this->u.road.slot != NULL && this->u.road.slot_age-- == 0) {
    01868     DEBUG(ms, 3, "Slot expired for vehicle %d (index %d) at stop 0x%X",
    01869       this->unitnumber, this->index, this->u.road.slot->xy);
    01870     ClearSlot(this);
    01871   }
    01872
    01873   /* update destination */
    01874   if (!(this->vehstatus & VS_STOPPED) && this->current_order.IsType(OT_GOTO_STATION) && !(this->current_order.GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) && this->u.road.slot == NULL && !(this->vehstatus & VS_CRASHED)) {
    01875     Station *st = GetStation(this->current_order.GetDestination());
    01876     RoadStop *rs = st->GetPrimaryRoadStop(this);
    01877     RoadStop *best = NULL;
    01878
    01879     if (rs != NULL) {
    01880       /* We try to obtain a slot if:
    01881        * 1) we're reasonably close to the primary road stop
    01882        * or
    01883        * 2) we're somewhere close to the station rectangle (to make sure we do assign
    01884        *    slots even if the station and its road stops are incredibly spread out)
    01885        */
    01886       if (DistanceManhattan(this->tile, rs->xy) < 16 || st->rect.PtInExtendedRect(TileX(this->tile), TileY(this->tile), 2)) {
    01887         uint dist, badness;
    01888         uint minbadness = UINT_MAX;
    01889
    01890         DEBUG(ms, 2, "Attempting to obtain a slot for vehicle %d (index %d) at station %d (0x%X)",
    01891           this->unitnumber, this->index, st->index, st->xy
    01892         );
    01893         /* Now we find the nearest road stop that has a free slot */
    01894         for (; rs != NULL; rs = rs->GetNextRoadStop(this)) {
    01895           if (rs->num_vehicles >= RoadStop::MAX_VEHICLES) {
    01896             DEBUG(ms, 4, " stop 0x%X's queue is full, not treating further", rs->xy);
    01897             continue;
    01898           }
    01899           dist = RoadFindPathToStop(this, rs->xy);
    01900           if (dist == UINT_MAX) {
    01901             DEBUG(ms, 4, " stop 0x%X is unreachable, not treating further", rs->xy);
    01902             continue;
    01903           }
    01904           badness = (rs->num_vehicles + 1) * (rs->num_vehicles + 1) + dist;
    01905
    01906           DEBUG(ms, 4, " stop 0x%X has %d vehicle%s waiting", rs->xy, rs->num_vehicles, rs->num_vehicles == 1 ? "":"s");
    01907           DEBUG(ms, 4, " distance is %u", dist);
    01908           DEBUG(ms, 4, " badness %u", badness);
    01909
    01910           if (badness < minbadness) {
    01911             best = rs;
    01912             minbadness = badness;
    01913           }
    01914         }
    01915
    01916         if (best != NULL) {
    01917           best->num_vehicles++;
    01918           DEBUG(ms, 3, "Assigned to stop 0x%X", best->xy);
    01919
    01920           this->u.road.slot = best;
    01921           this->dest_tile = best->xy;
    01922           this->u.road.slot_age = 14;
    01923         } else {
    01924           DEBUG(ms, 3, "Could not find a suitable stop");
    01925         }
    01926       } else {
    01927         DEBUG(ms, 5, "Distance from station too far. Postponing slotting for vehicle %d (index %d) at station %d, (0x%X)",
    01928             this->unitnumber, this->index, st->index, st->xy);
    01929       }
    01930     } else {
    01931       DEBUG(ms, 4, "No road stop for vehicle %d (index %d) at station %d (0x%X)",
    01932           this->unitnumber, this->index, st->index, st->xy);
    01933     }
    01934   }
    01935
    01936   if (this->running_ticks == 0) return;
    01937
    01938   CommandCost cost(EXPENSES_ROADVEH_RUN, this->GetRunningCost() * this->running_ticks / (DAYS_IN_YEAR * DAY_TICKS));
    01939
    01940   this->profit_this_year -= cost.GetCost();
    01941   this->running_ticks = 0;
    01942
    01943   SubtractMoneyFromCompanyFract(this->owner, cost);
    01944
    01945   InvalidateWindow(WC_VEHICLE_DETAILS, this->index);
    01946   InvalidateWindowClasses(WC_ROADVEH_LIST);
    01947 }
    01948
    01959 CommandCost CmdRefitRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    01960 {
    01961   Vehicle *v;
    01962   CommandCost cost(EXPENSES_ROADVEH_RUN);
    01963   CargoID new_cid = GB(p2, 0, 8);
    01964   byte new_subtype = GB(p2, 8, 8);
    01965   bool only_this = HasBit(p2, 16);
    01966   uint16 capacity = CALLBACK_FAILED;
    01967   uint total_capacity = 0;
    01968
    01969   if (!IsValidVehicleID(p1)) return CMD_ERROR;
    01970
    01971   v = GetVehicle(p1);
    01972
    01973   if (v->type != VEH_ROAD || !CheckOwnership(v->owner)) return CMD_ERROR;
    01974   if (!v->IsStoppedInDepot()) return_cmd_error(STR_9013_MUST_BE_STOPPED_INSIDE);
    01975   if (v->vehstatus & VS_CRASHED) return_cmd_error(STR_CAN_T_REFIT_DESTROYED_VEHICLE);
    01976
    01977   if (new_cid >= NUM_CARGO) return CMD_ERROR;
    01978
    01979   for (; v != NULL; v = (only_this ? NULL : v->Next())) {
    01980     /* XXX: We refit all the attached wagons en-masse if they can be
    01981      * refitted. This is how TTDPatch does it.  TODO: Have some nice
    01982      * [Refit] button near each wagon. */
    01983     if (!CanRefitTo(v->engine_type, new_cid)) continue;
    01984
    01985     const Engine *e = GetEngine(v->engine_type);
    01986     if (!e->CanCarryCargo()) continue;
    01987
    01988     if (HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) {
    01989       /* Back up the cargo type */
    01990       CargoID temp_cid = v->cargo_type;
    01991       byte temp_subtype = v->cargo_subtype;
    01992       v->cargo_type = new_cid;
    01993       v->cargo_subtype = new_subtype;
    01994
    01995       /* Check the refit capacity callback */
    01996       capacity = GetVehicleCallback(CBID_VEHICLE_REFIT_CAPACITY, 0, 0, v->engine_type, v);
    01997
    01998       /* Restore the original cargo type */
    01999       v->cargo_type = temp_cid;
    02000       v->cargo_subtype = temp_subtype;
    02001     }
    02002
    02003     if (capacity == CALLBACK_FAILED) {
    02004       /* callback failed or not used, use default capacity */
    02005
    02006       CargoID old_cid = e->GetDefaultCargoType();
    02007       /* normally, the capacity depends on the cargo type, a vehicle can
    02008        * carry twice as much mail/goods as normal cargo, and four times as
    02009        * many passengers
    02010        */
    02011       capacity = GetVehicleProperty(v, 0x0F, e->u.road.capacity);
    02012       switch (old_cid) {
    02013         case CT_PASSENGERS: break;
    02014         case CT_MAIL:
    02015         case CT_GOODS: capacity *= 2; break;
    02016         default:       capacity *= 4; break;
    02017       }
    02018       switch (new_cid) {
    02019         case CT_PASSENGERS: break;
    02020         case CT_MAIL:
    02021         case CT_GOODS: capacity /= 2; break;
    02022         default:       capacity /= 4; break;
    02023       }
    02024     }
    02025
    02026     total_capacity += capacity;
    02027
    02028     if (new_cid != v->cargo_type) {
    02029       cost.AddCost(GetRefitCost(v->engine_type));
    02030     }
    02031
    02032     if (flags & DC_EXEC) {
    02033       v->cargo_cap = capacity;
    02034       v->cargo.Truncate((v->cargo_type == new_cid) ? capacity : 0);
    02035       v->cargo_type = new_cid;
    02036       v->cargo_subtype = new_subtype;
    02037       InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
    02038       InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
    02039       InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
    02040     }
    02041   }
    02042
    02043   if (flags & DC_EXEC) RoadVehUpdateCache(GetVehicle(p1)->First());
    02044
    02045   _returned_refit_capacity = total_capacity;
    02046
    02047   return cost;
    02048 }