# roadveh_cmd.cpp

Go to the documentation of this file.

    00001 /* $Id: roadveh_cmd.cpp 16482 2009-05-31 12:22:53Z 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->cur_image = v->GetImage(v->direction);
    00490     MarkSingleVehicleDirty(v);
    00491   }
    00492 }
    00493
    00494 void RoadVehicle::UpdateDeltaXY(Direction direction)
    00495 {
    00496 #define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0)
    00497   static const uint32 _delta_xy_table[8] = {
    00498     MKIT(3, 3, -1, -1),
    00499     MKIT(3, 7, -1, -3),
    00500     MKIT(3, 3, -1, -1),
    00501     MKIT(7, 3, -3, -1),
    00502     MKIT(3, 3, -1, -1),
    00503     MKIT(3, 7, -1, -3),
    00504     MKIT(3, 3, -1, -1),
    00505     MKIT(7, 3, -3, -1),
    00506   };
    00507 #undef MKIT
    00508
    00509   uint32 x = _delta_xy_table[direction];
    00510   this->x_offs        = GB(x,  0, 8);
    00511   this->y_offs        = GB(x,  8, 8);
    00512   this->x_extent      = GB(x, 16, 8);
    00513   this->y_extent      = GB(x, 24, 8);
    00514   this->z_extent      = 6;
    00515 }
    00516
    00517 static void ClearCrashedStation(Vehicle *v)
    00518 {
    00519   RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile));
    00520
    00521   /* Mark the station entrance as not busy */
    00522   rs->SetEntranceBusy(false);
    00523
    00524   /* Free the parking bay */
    00525   rs->FreeBay(HasBit(v->u.road.state, RVS_USING_SECOND_BAY));
    00526 }
    00527
    00528 static void DeleteLastRoadVeh(Vehicle *v)
    00529 {
    00530   Vehicle *u = v;
    00531   for (; v->Next() != NULL; v = v->Next()) u = v;
    00532   u->SetNext(NULL);
    00533
    00534   if (IsTileType(v->tile, MP_STATION)) ClearCrashedStation(v);
    00535
    00536   delete v;
    00537 }
    00538
    00539 static byte SetRoadVehPosition(Vehicle *v, int x, int y)
    00540 {
    00541   byte new_z, old_z;
    00542
    00543   /* need this hint so it returns the right z coordinate on bridges. */
    00544   v->x_pos = x;
    00545   v->y_pos = y;
    00546   new_z = GetSlopeZ(x, y);
    00547
    00548   old_z = v->z_pos;
    00549   v->z_pos = new_z;
    00550
    00551   VehicleMove(v, true);
    00552   return old_z;
    00553 }
    00554
    00555 static void RoadVehSetRandomDirection(Vehicle *v)
    00556 {
    00557   static const DirDiff delta[] = {
    00558     DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT
    00559   };
    00560
    00561   do {
    00562     uint32 r = Random();
    00563
    00564     v->direction = ChangeDir(v->direction, delta[r & 3]);
    00565     v->UpdateDeltaXY(v->direction);
    00566     v->cur_image = v->GetImage(v->direction);
    00567     SetRoadVehPosition(v, v->x_pos, v->y_pos);
    00568   } while ((v = v->Next()) != NULL);
    00569 }
    00570
    00571 static void RoadVehIsCrashed(Vehicle *v)
    00572 {
    00573   v->u.road.crashed_ctr++;
    00574   if (v->u.road.crashed_ctr == 2) {
    00575     CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
    00576   } else if (v->u.road.crashed_ctr <= 45) {
    00577     if ((v->tick_counter & 7) == 0) RoadVehSetRandomDirection(v);
    00578   } else if (v->u.road.crashed_ctr >= 2220 && !(v->tick_counter & 0x1F)) {
    00579     DeleteLastRoadVeh(v);
    00580   }
    00581 }
    00582
    00583 static Vehicle *EnumCheckRoadVehCrashTrain(Vehicle *v, void *data)
    00584 {
    00585   const Vehicle *u = (Vehicle*)data;
    00586
    00587   return
    00588     v->type == VEH_TRAIN &&
    00589     abs(v->z_pos - u->z_pos) <= 6 &&
    00590     abs(v->x_pos - u->x_pos) <= 4 &&
    00591     abs(v->y_pos - u->y_pos) <= 4 ?
    00592       v : NULL;
    00593 }
    00594
    00595 static void RoadVehCrash(Vehicle *v)
    00596 {
    00597   uint16 pass = 1;
    00598
    00599   v->u.road.crashed_ctr++;
    00600
    00601   for (Vehicle *u = v; u != NULL; u = u->Next()) {
    00602     if (IsCargoInClass(u->cargo_type, CC_PASSENGERS)) pass += u->cargo.Count();
    00603
    00604     u->vehstatus |= VS_CRASHED;
    00605
    00606     MarkSingleVehicleDirty(u);
    00607   }
    00608
    00609   ClearSlot(v);
    00610
    00611   InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
    00612
    00613   AI::NewEvent(v->owner, new AIEventVehicleCrashed(v->index, v->tile, AIEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING));
    00614
    00615   SetDParam(0, pass);
    00616   AddNewsItem(
    00617     (pass == 1) ?
    00618       STR_9031_ROAD_VEHICLE_CRASH_DRIVER : STR_9032_ROAD_VEHICLE_CRASH_DIE,
    00619     NS_ACCIDENT_VEHICLE,
    00620     v->index,
    00621     0
    00622   );
    00623
    00624   ModifyStationRatingAround(v->tile, v->owner, -160, 22);
    00625   SndPlayVehicleFx(SND_12_EXPLOSION, v);
    00626 }
    00627
    00628 static bool RoadVehCheckTrainCrash(Vehicle *v)
    00629 {
    00630   for (Vehicle *u = v; u != NULL; u = u->Next()) {
    00631     if (u->u.road.state == RVSB_WORMHOLE) continue;
    00632
    00633     TileIndex tile = u->tile;
    00634
    00635     if (!IsLevelCrossingTile(tile)) continue;
    00636
    00637     if (HasVehicleOnPosXY(v->x_pos, v->y_pos, u, EnumCheckRoadVehCrashTrain)) {
    00638       RoadVehCrash(v);
    00639       return true;
    00640     }
    00641   }
    00642
    00643   return false;
    00644 }
    00645
    00646 static void HandleBrokenRoadVeh(Vehicle *v)
    00647 {
    00648   if (v->breakdown_ctr != 1) {
    00649     v->breakdown_ctr = 1;
    00650     v->cur_speed = 0;
    00651
    00652     if (v->breakdowns_since_last_service != 255)
    00653       v->breakdowns_since_last_service++;
    00654
    00655     InvalidateWindow(WC_VEHICLE_VIEW, v->index);
    00656     InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
    00657
    00658     if (!PlayVehicleSound(v, VSE_BREAKDOWN)) {
    00659       SndPlayVehicleFx((_settings_game.game_creation.landscape != LT_TOYLAND) ?
    00660         SND_0F_VEHICLE_BREAKDOWN : SND_35_COMEDY_BREAKDOWN, v);
    00661     }
    00662
    00663     if (!(v->vehstatus & VS_HIDDEN)) {
    00664       Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE);
    00665       if (u != NULL) u->u.effect.animation_state = v->breakdown_delay * 2;
    00666     }
    00667   }
    00668
    00669   if ((v->tick_counter & 1) == 0) {
    00670     if (--v->breakdown_delay == 0) {
    00671       v->breakdown_ctr = 0;
    00672       InvalidateWindow(WC_VEHICLE_VIEW, v->index);
    00673     }
    00674   }
    00675 }
    00676
    00677 TileIndex RoadVehicle::GetOrderStationLocation(StationID station)
    00678 {
    00679   if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
    00680
    00681   TileIndex dest = INVALID_TILE;
    00682   const RoadStop *rs = GetStation(station)->GetPrimaryRoadStop(this);
    00683   if (rs != NULL) {
    00684     uint mindist = UINT_MAX;
    00685
    00686     for (; rs != NULL; rs = rs->GetNextRoadStop(this)) {
    00687       uint dist = DistanceManhattan(this->tile, rs->xy);
    00688
    00689       if (dist < mindist) {
    00690         mindist = dist;
    00691         dest = rs->xy;
    00692       }
    00693     }
    00694   }
    00695
    00696   if (dest != INVALID_TILE) {
    00697     return dest;
    00698   } else {
    00699     /* There is no stop left at the station, so don't even TRY to go there */
    00700     this->cur_order_index++;
    00701     return 0;
    00702   }
    00703 }
    00704
    00705 static void StartRoadVehSound(const Vehicle *v)
    00706 {
    00707   if (!PlayVehicleSound(v, VSE_START)) {
    00708     SoundFx s = RoadVehInfo(v->engine_type)->sfx;
    00709     if (s == SND_19_BUS_START_PULL_AWAY && (v->tick_counter & 3) == 0)
    00710       s = SND_1A_BUS_START_PULL_AWAY_WITH_HORN;
    00711     SndPlayVehicleFx(s, v);
    00712   }
    00713 }
    00714
    00715 struct RoadVehFindData {
    00716   int x;
    00717   int y;
    00718   const Vehicle *veh;
    00719   Vehicle *best;
    00720   uint best_diff;
    00721   Direction dir;
    00722 };
    00723
    00724 static Vehicle *EnumCheckRoadVehClose(Vehicle *v, void *data)
    00725 {
    00726   static const int8 dist_x[] = { -4, -8, -4, -1, 4, 8, 4, 1 };
    00727   static const int8 dist_y[] = { -4, -1, 4, 8, 4, 1, -4, -8 };
    00728
    00729   RoadVehFindData *rvf = (RoadVehFindData*)data;
    00730
    00731   short x_diff = v->x_pos - rvf->x;
    00732   short y_diff = v->y_pos - rvf->y;
    00733
    00734   if (v->type == VEH_ROAD &&
    00735       !v->IsInDepot() &&
    00736       abs(v->z_pos - rvf->veh->z_pos) < 6 &&
    00737       v->direction == rvf->dir &&
    00738       rvf->veh->First() != v->First() &&
    00739       (dist_x[v->direction] >= 0 || (x_diff > dist_x[v->direction] && x_diff <= 0)) &&
    00740       (dist_x[v->direction] <= 0 || (x_diff < dist_x[v->direction] && x_diff >= 0)) &&
    00741       (dist_y[v->direction] >= 0 || (y_diff > dist_y[v->direction] && y_diff <= 0)) &&
    00742       (dist_y[v->direction] <= 0 || (y_diff < dist_y[v->direction] && y_diff >= 0))) {
    00743     uint diff = abs(x_diff) + abs(y_diff);
    00744
    00745     if (diff < rvf->best_diff || (diff == rvf->best_diff && v->index < rvf->best->index)) {
    00746       rvf->best = v;
    00747       rvf->best_diff = diff;
    00748     }
    00749   }
    00750
    00751   return NULL;
    00752 }
    00753
    00754 static Vehicle *RoadVehFindCloseTo(Vehicle *v, int x, int y, Direction dir)
    00755 {
    00756   RoadVehFindData rvf;
    00757   Vehicle *front = v->First();
    00758
    00759   if (front->u.road.reverse_ctr != 0) return NULL;
    00760
    00761   rvf.x = x;
    00762   rvf.y = y;
    00763   rvf.dir = dir;
    00764   rvf.veh = v;
    00765   rvf.best_diff = UINT_MAX;
    00766
    00767   if (front->u.road.state == RVSB_WORMHOLE) {
    00768     FindVehicleOnPos(v->tile, &rvf, EnumCheckRoadVehClose);
    00769     FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), &rvf, EnumCheckRoadVehClose);
    00770   } else {
    00771     FindVehicleOnPosXY(x, y, &rvf, EnumCheckRoadVehClose);
    00772   }
    00773
    00774   /* This code protects a roadvehicle from being blocked for ever
    00775    * If more than 1480 / 74 days a road vehicle is blocked, it will
    00776    * drive just through it. The ultimate backup-code of TTD.
    00777    * It can be disabled. */
    00778   if (rvf.best_diff == UINT_MAX) {
    00779     front->u.road.blocked_ctr = 0;
    00780     return NULL;
    00781   }
    00782
    00783   if (++front->u.road.blocked_ctr > 1480) return NULL;
    00784
    00785   return rvf.best;
    00786 }
    00787
    00788 static void RoadVehArrivesAt(const Vehicle *v, Station *st)
    00789 {
    00790   if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) {
    00791     /* Check if station was ever visited before */
    00792     if (!(st->had_vehicle_of_type & HVOT_BUS)) {
    00793       st->had_vehicle_of_type |= HVOT_BUS;
    00794       SetDParam(0, st->index);
    00795       AddNewsItem(
    00796         v->u.road.roadtype == ROADTYPE_ROAD ? STR_902F_CITIZENS_CELEBRATE_FIRST : STR_CITIZENS_CELEBRATE_FIRST_PASSENGER_TRAM,
    00797         (v->owner == _local_company) ? NS_ARRIVAL_COMPANY : NS_ARRIVAL_OTHER,
    00798         v->index,
    00799         st->index
    00800       );
    00801       AI::NewEvent(v->owner, new AIEventStationFirstVehicle(st->index, v->index));
    00802     }
    00803   } else {
    00804     /* Check if station was ever visited before */
    00805     if (!(st->had_vehicle_of_type & HVOT_TRUCK)) {
    00806       st->had_vehicle_of_type |= HVOT_TRUCK;
    00807       SetDParam(0, st->index);
    00808       AddNewsItem(
    00809         v->u.road.roadtype == ROADTYPE_ROAD ? STR_9030_CITIZENS_CELEBRATE_FIRST : STR_CITIZENS_CELEBRATE_FIRST_CARGO_TRAM,
    00810         (v->owner == _local_company) ? NS_ARRIVAL_COMPANY : NS_ARRIVAL_OTHER,
    00811         v->index,
    00812         st->index
    00813       );
    00814       AI::NewEvent(v->owner, new AIEventStationFirstVehicle(st->index, v->index));
    00815     }
    00816   }
    00817 }
    00818
    00819 static int RoadVehAccelerate(Vehicle *v)
    00820 {
    00821   uint oldspeed = v->cur_speed;
    00822   uint accel = 256 + (v->u.road.overtaking != 0 ? 256 : 0);
    00823   uint spd = v->subspeed + accel;
    00824
    00825   v->subspeed = (uint8)spd;
    00826
    00827   int tempmax = v->max_speed;
    00828   if (v->cur_speed > v->max_speed) {
    00829     tempmax = v->cur_speed - (v->cur_speed / 10) - 1;
    00830   }
    00831
    00832   v->cur_speed = spd = Clamp(v->cur_speed + ((int)spd >> 8), 0, tempmax);
    00833
    00834   /* Apply bridge speed limit */
    00835   if (v->u.road.state == RVSB_WORMHOLE && !(v->vehstatus & VS_HIDDEN)) {
    00836     v->cur_speed = min(v->cur_speed, GetBridgeSpec(GetBridgeType(v->tile))->speed * 2);
    00837   }
    00838
    00839   /* Update statusbar only if speed has changed to save CPU time */
    00840   if (oldspeed != v->cur_speed) {
    00841     if (_settings_client.gui.vehicle_speed) {
    00842       InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
    00843     }
    00844   }
    00845
    00846   /* Speed is scaled in the same manner as for trains. @see train_cmd.cpp */
    00847   int scaled_spd = spd * 3 >> 2;
    00848
    00849   scaled_spd += v->progress;
    00850   v->progress = 0;
    00851   return scaled_spd;
    00852 }
    00853
    00854 static Direction RoadVehGetNewDirection(const Vehicle *v, int x, int y)
    00855 {
    00856   static const Direction _roadveh_new_dir[] = {
    00857     DIR_N , DIR_NW, DIR_W , INVALID_DIR,
    00858     DIR_NE, DIR_N , DIR_SW, INVALID_DIR,
    00859     DIR_E , DIR_SE, DIR_S
    00860   };
    00861
    00862   x = x - v->x_pos + 1;
    00863   y = y - v->y_pos + 1;
    00864
    00865   if ((uint)x > 2 || (uint)y > 2) return v->direction;
    00866   return _roadveh_new_dir[y * 4 + x];
    00867 }
    00868
    00869 static Direction RoadVehGetSlidingDirection(const Vehicle *v, int x, int y)
    00870 {
    00871   Direction new_dir = RoadVehGetNewDirection(v, x, y);
    00872   Direction old_dir = v->direction;
    00873   DirDiff delta;
    00874
    00875   if (new_dir == old_dir) return old_dir;
    00876   delta = (DirDifference(new_dir, old_dir) > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT);
    00877   return ChangeDir(old_dir, delta);
    00878 }
    00879
    00880 struct OvertakeData {
    00881   const Vehicle *u;
    00882   const Vehicle *v;
    00883   TileIndex tile;
    00884   Trackdir trackdir;
    00885 };
    00886
    00887 static Vehicle *EnumFindVehBlockingOvertake(Vehicle *v, void *data)
    00888 {
    00889   const OvertakeData *od = (OvertakeData*)data;
    00890
    00891   return
    00892     v->type == VEH_ROAD && v->First() == v && v != od->u && v != od->v ?
    00893       v : NULL;
    00894 }
    00895
    00902 static bool CheckRoadBlockedForOvertaking(OvertakeData *od)
    00903 {
    00904   TrackStatus ts = GetTileTrackStatus(od->tile, TRANSPORT_ROAD, od->v->u.road.compatible_roadtypes);
    00905   TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts);
    00906   TrackdirBits red_signals = TrackStatusToRedSignals(ts); // barred level crossing
    00907   TrackBits trackbits = TrackdirBitsToTrackBits(trackdirbits);
    00908
    00909   /* Track does not continue along overtaking direction || track has junction || levelcrossing is barred */
    00910   if (!HasBit(trackdirbits, od->trackdir) || (trackbits & ~TRACK_BIT_CROSS) || (red_signals != TRACKDIR_BIT_NONE)) return true;
    00911
    00912   /* Are there more vehicles on the tile except the two vehicles involved in overtaking */
    00913   return HasVehicleOnPos(od->tile, od, EnumFindVehBlockingOvertake);
    00914 }
    00915
    00916 static void RoadVehCheckOvertake(Vehicle *v, Vehicle *u)
    00917 {
    00918   OvertakeData od;
    00919
    00920   od.v = v;
    00921   od.u = u;
    00922
    00923   if (u->max_speed >= v->max_speed &&
    00924       !(u->vehstatus & VS_STOPPED) &&
    00925       u->cur_speed != 0) {
    00926     return;
    00927   }
    00928
    00929   /* Trams can't overtake other trams */
    00930   if (v->u.road.roadtype == ROADTYPE_TRAM) return;
    00931
    00932   /* Don't overtake in stations */
    00933   if (IsTileType(v->tile, MP_STATION)) return;
    00934
    00935   /* For now, articulated road vehicles can't overtake anything. */
    00936   if (RoadVehHasArticPart(v)) return;
    00937
    00938   /* Vehicles are not driving in same direction || direction is not a diagonal direction */
    00939   if (v->direction != u->direction || !(v->direction & 1)) return;
    00940
    00941   /* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */
    00942   if (v->u.road.state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->u.road.state & RVSB_TRACKDIR_MASK))) return;
    00943
    00944   od.trackdir = DiagDirToDiagTrackdir(DirToDiagDir(v->direction));
    00945
    00946   /* Are the current and the next tile suitable for overtaking?
    00947    *  - Does the track continue along od.trackdir
    00948    *  - No junctions
    00949    *  - No barred levelcrossing
    00950    *  - No other vehicles in the way
    00951    */
    00952   od.tile = v->tile;
    00953   if (CheckRoadBlockedForOvertaking(&od)) return;
    00954
    00955   od.tile = v->tile + TileOffsByDiagDir(DirToDiagDir(v->direction));
    00956   if (CheckRoadBlockedForOvertaking(&od)) return;
    00957
    00958   if (od.u->cur_speed == 0 || od.u->vehstatus& VS_STOPPED) {
    00959     v->u.road.overtaking_ctr = 0x11;
    00960     v->u.road.overtaking = 0x10;
    00961   } else {
    00962 //    if (CheckRoadBlockedForOvertaking(&od)) return;
    00963     v->u.road.overtaking_ctr = 0;
    00964     v->u.road.overtaking = 0x10;
    00965   }
    00966 }
    00967
    00968 static void RoadZPosAffectSpeed(Vehicle *v, byte old_z)
    00969 {
    00970   if (old_z == v->z_pos) return;
    00971
    00972   if (old_z < v->z_pos) {
    00973     v->cur_speed = v->cur_speed * 232 / 256; // slow down by ~10%
    00974   } else {
    00975     uint16 spd = v->cur_speed + 2;
    00976     if (spd <= v->max_speed) v->cur_speed = spd;
    00977   }
    00978 }
    00979
    00980 static int PickRandomBit(uint bits)
    00981 {
    00982   uint i;
    00983   uint num = RandomRange(CountBits(bits));
    00984
    00985   for (i = 0; !(bits & 1) || (int)--num >= 0; bits >>= 1, i++) {}
    00986   return i;
    00987 }
    00988
    00989 struct FindRoadToChooseData {
    00990   TileIndex dest;
    00991   uint maxtracklen;
    00992   uint mindist;
    00993 };
    00994
    00995 static bool EnumRoadTrackFindDist(TileIndex tile, void *data, Trackdir trackdir, uint length)
    00996 {
    00997   FindRoadToChooseData *frd = (FindRoadToChooseData*)data;
    00998   uint dist = DistanceManhattan(tile, frd->dest);
    00999
    01000   if (dist <= frd->mindist) {
    01001     if (dist != frd->mindist || length < frd->maxtracklen) {
    01002       frd->maxtracklen = length;
    01003     }
    01004     frd->mindist = dist;
    01005   }
    01006   return false;
    01007 }
    01008
    01009 static inline NPFFoundTargetData PerfNPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, bool ignore_start_tile, NPFFindStationOrTileData *target, TransportType type, uint sub_type, Owner owner, RailTypes railtypes)
    01010 {
    01011
    01012   void *perf = NpfBeginInterval();
    01013   NPFFoundTargetData ret = NPFRouteToStationOrTile(tile, trackdir, ignore_start_tile, target, type, sub_type, owner, railtypes);
    01014   int t = NpfEndInterval(perf);
    01015   DEBUG(yapf, 4, "[NPFR] %d us - %d rounds - %d open - %d closed -- ", t, 0, _aystar_stats_open_size, _aystar_stats_closed_size);
    01016   return ret;
    01017 }
    01018
    01027 static Trackdir RoadFindPathToDest(Vehicle *v, TileIndex tile, DiagDirection enterdir)
    01028 {
    01029 #define return_track(x) { best_track = (Trackdir)x; goto found_best_track; }
    01030
    01031   TileIndex desttile;
    01032   FindRoadToChooseData frd;
    01033   Trackdir best_track;
    01034
    01035   TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes);
    01036   TrackdirBits red_signals = TrackStatusToRedSignals(ts); // crossing
    01037   TrackdirBits trackdirs = TrackStatusToTrackdirBits(ts);
    01038
    01039   if (IsTileType(tile, MP_ROAD)) {
    01040     if (IsRoadDepot(tile) && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir || (GetRoadTypes(tile) & v->u.road.compatible_roadtypes) == 0)) {
    01041       /* Road depot owned by another company or with the wrong orientation */
    01042       trackdirs = TRACKDIR_BIT_NONE;
    01043     }
    01044   } else if (IsTileType(tile, MP_STATION) && IsStandardRoadStopTile(tile)) {
    01045     /* Standard road stop (drive-through stops are treated as normal road) */
    01046
    01047     if (!IsTileOwner(tile, v->owner) || GetRoadStopDir(tile) == enterdir || RoadVehHasArticPart(v)) {
    01048       /* different station owner or wrong orientation or the vehicle has articulated parts */
    01049       trackdirs = TRACKDIR_BIT_NONE;
    01050     } else {
    01051       /* Our station */
    01052       RoadStopType rstype = IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? ROADSTOP_BUS : ROADSTOP_TRUCK;
    01053
    01054       if (GetRoadStopType(tile) != rstype) {
    01055         /* Wrong station type */
    01056         trackdirs = TRACKDIR_BIT_NONE;
    01057       } else {
    01058         /* Proper station type, check if there is free loading bay */
    01059         if (!_settings_game.pf.roadveh_queue && IsStandardRoadStopTile(tile) &&
    01060             !GetRoadStopByTile(tile, rstype)->HasFreeBay()) {
    01061           /* Station is full and RV queuing is off */
    01062           trackdirs = TRACKDIR_BIT_NONE;
    01063         }
    01064       }
    01065     }
    01066   }
    01067   /* The above lookups should be moved to GetTileTrackStatus in the
    01068    * future, but that requires more changes to the pathfinder and other
    01069    * stuff, probably even more arguments to GTTS.
    01070    */
    01071
    01072   /* Remove tracks unreachable from the enter dir */
    01073   trackdirs &= _road_enter_dir_to_reachable_trackdirs[enterdir];
    01074   if (trackdirs == TRACKDIR_BIT_NONE) {
    01075     /* No reachable tracks, so we'll reverse */
    01076     return_track(_road_reverse_table[enterdir]);
    01077   }
    01078
    01079   if (v->u.road.reverse_ctr != 0) {
    01080     bool reverse = true;
    01081     if (v->u.road.roadtype == ROADTYPE_TRAM) {
    01082       /* Trams may only reverse on a tile if it contains at least the straight
    01083        * trackbits or when it is a valid turning tile (i.e. one roadbit) */
    01084       RoadBits rb = GetAnyRoadBits(tile, ROADTYPE_TRAM);
    01085       RoadBits straight = AxisToRoadBits(DiagDirToAxis(enterdir));
    01086       reverse = ((rb & straight) == straight) ||
    01087                 (rb == DiagDirToRoadBits(enterdir));
    01088     }
    01089     if (reverse) {
    01090       v->u.road.reverse_ctr = 0;
    01091       if (v->tile != tile) {
    01092         return_track(_road_reverse_table[enterdir]);
    01093       }
    01094     }
    01095   }
    01096
    01097   desttile = v->dest_tile;
    01098   if (desttile == 0) {
    01099     /* We've got no destination, pick a random track */
    01100     return_track(PickRandomBit(trackdirs));
    01101   }
    01102
    01103   /* Only one track to choose between? */
    01104   if (KillFirstBit(trackdirs) == TRACKDIR_BIT_NONE) {
    01105     return_track(FindFirstBit2x64(trackdirs));
    01106   }
    01107
    01108   switch (_settings_game.pf.pathfinder_for_roadvehs) {
    01109     case VPF_YAPF: { // YAPF
    01110       Trackdir trackdir = YapfChooseRoadTrack(v, tile, enterdir);
    01111       if (trackdir != INVALID_TRACKDIR) return_track(trackdir);
    01112       return_track(PickRandomBit(trackdirs));
    01113     } break;
    01114
    01115     case VPF_NPF: { // NPF
    01116       NPFFindStationOrTileData fstd;
    01117
    01118       NPFFillWithOrderData(&fstd, v);
    01119       Trackdir trackdir = DiagDirToDiagTrackdir(enterdir);
    01120       /* debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir); */
    01121
    01122       NPFFoundTargetData ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, true, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPES);
    01123       if (ftd.best_trackdir == INVALID_TRACKDIR) {
    01124         /* We are already at our target. Just do something
    01125          * @todo: maybe display error?
    01126          * @todo: go straight ahead if possible? */
    01127         return_track(FindFirstBit2x64(trackdirs));
    01128       } else {
    01129         /* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
    01130          * the direction we need to take to get there, if ftd.best_bird_dist is not 0,
    01131          * we did not find our target, but ftd.best_trackdir contains the direction leading
    01132          * to the tile closest to our target. */
    01133         return_track(ftd.best_trackdir);
    01134       }
    01135     } break;
    01136
    01137     default:
    01138     case VPF_OPF: { // OPF
    01139       DiagDirection dir;
    01140
    01141       if (IsTileType(desttile, MP_ROAD)) {
    01142         if (IsRoadDepot(desttile)) {
    01143           dir = GetRoadDepotDirection(desttile);
    01144           goto do_it;
    01145         }
    01146       } else if (IsTileType(desttile, MP_STATION)) {
    01147         /* For drive-through stops we can head for the actual station tile */
    01148         if (IsStandardRoadStopTile(desttile)) {
    01149           dir = GetRoadStopDir(desttile);
    01150 do_it:;
    01151           /* When we are heading for a depot or station, we just
    01152            * pretend we are heading for the tile in front, we'll
    01153            * see from there */
    01154           desttile += TileOffsByDiagDir(dir);
    01155           if (desttile == tile && trackdirs & _road_exit_dir_to_incoming_trackdirs[dir]) {
    01156             /* If we are already in front of the
    01157              * station/depot and we can get in from here,
    01158              * we enter */
    01159             return_track(FindFirstBit2x64(trackdirs & _road_exit_dir_to_incoming_trackdirs[dir]));
    01160           }
    01161         }
    01162       }
    01163       /* Do some pathfinding */
    01164       frd.dest = desttile;
    01165
    01166       best_track = INVALID_TRACKDIR;
    01167       uint best_dist = UINT_MAX;
    01168       uint best_maxlen = UINT_MAX;
    01169       uint bitmask = (uint)trackdirs;
    01170       uint i;
    01171       FOR_EACH_SET_BIT(i, bitmask) {
    01172         if (best_track == INVALID_TRACKDIR) best_track = (Trackdir)i; // in case we don't find the path, just pick a track
    01173         frd.maxtracklen = UINT_MAX;
    01174         frd.mindist = UINT_MAX;
    01175         FollowTrack(tile, PATHFIND_FLAGS_NONE, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, _road_pf_directions[i], EnumRoadTrackFindDist, NULL, &frd);
    01176
    01177         if (frd.mindist < best_dist || (frd.mindist == best_dist && frd.maxtracklen < best_maxlen)) {
    01178           best_dist = frd.mindist;
    01179           best_maxlen = frd.maxtracklen;
    01180           best_track = (Trackdir)i;
    01181         }
    01182       }
    01183     } break;
    01184   }
    01185
    01186 found_best_track:;
    01187
    01188   if (HasBit(red_signals, best_track)) return INVALID_TRACKDIR;
    01189
    01190   return best_track;
    01191 }
    01192
    01193 static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile)
    01194 {
    01195   if (_settings_game.pf.pathfinder_for_roadvehs == VPF_YAPF) {
    01196     /* use YAPF */
    01197     return YapfRoadVehDistanceToTile(v, tile);
    01198   }
    01199
    01200   /* use NPF */
    01201   Trackdir trackdir = GetVehicleTrackdir(v);
    01202   assert(trackdir != INVALID_TRACKDIR);
    01203
    01204   NPFFindStationOrTileData fstd;
    01205   fstd.dest_coords = tile;
    01206   fstd.station_index = INVALID_STATION; // indicates that the destination is a tile, not a station
    01207
    01208   uint dist = NPFRouteToStationOrTile(v->tile, trackdir, false, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPES).best_path_dist;
    01209   /* change units from NPF_TILE_LENGTH to # of tiles */
    01210   if (dist != UINT_MAX) dist = (dist + NPF_TILE_LENGTH - 1) / NPF_TILE_LENGTH;
    01211
    01212   return dist;
    01213 }
    01214
    01215 struct RoadDriveEntry {
    01216   byte x, y;
    01217 };
    01218
    01219 #include "table/roadveh_movement.h"
    01220
    01221 static const byte _road_veh_data_1[] = {
    01222   20, 20, 16, 16, 0, 0, 0, 0,
    01223   19, 19, 15, 15, 0, 0, 0, 0,
    01224   16, 16, 12, 12, 0, 0, 0, 0,
    01225   15, 15, 11, 11
    01226 };
    01227
    01228 static bool RoadVehLeaveDepot(Vehicle *v, bool first)
    01229 {
    01230   /* Don't leave if not all the wagons are in the depot. */
    01231   for (const Vehicle *u = v; u != NULL; u = u->Next()) {
    01232     if (u->u.road.state != RVSB_IN_DEPOT || u->tile != v->tile) return false;
    01233   }
    01234
    01235   DiagDirection dir = GetRoadDepotDirection(v->tile);
    01236   v->direction = DiagDirToDir(dir);
    01237
    01238   Trackdir tdir = _roadveh_depot_exit_trackdir[dir];
    01239   const RoadDriveEntry *rdp = _road_drive_data[v->u.road.roadtype][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + tdir];
    01240
    01241   int x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF);
    01242   int y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF);
    01243
    01244   if (first) {
    01245     if (RoadVehFindCloseTo(v, x, y, v->direction) != NULL) return true;
    01246
    01247     VehicleServiceInDepot(v);
    01248
    01249     StartRoadVehSound(v);
    01250
    01251     /* Vehicle is about to leave a depot */
    01252     v->cur_speed = 0;
    01253   }
    01254
    01255   v->vehstatus &= ~VS_HIDDEN;
    01256   v->u.road.state = tdir;
    01257   v->u.road.frame = RVC_DEPOT_START_FRAME;
    01258
    01259   v->UpdateDeltaXY(v->direction);
    01260   SetRoadVehPosition(v, x, y);
    01261
    01262   InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
    01263
    01264   return true;
    01265 }
    01266
    01267 static Trackdir FollowPreviousRoadVehicle(const Vehicle *v, const Vehicle *prev, TileIndex tile, DiagDirection entry_dir, bool already_reversed)
    01268 {
    01269   if (prev->tile == v->tile && !already_reversed) {
    01270     /* If the previous vehicle is on the same tile as this vehicle is
    01271      * then it must have reversed. */
    01272     return _road_reverse_table[entry_dir];
    01273   }
    01274
    01275   byte prev_state = prev->u.road.state;
    01276   Trackdir dir;
    01277
    01278   if (prev_state == RVSB_WORMHOLE || prev_state == RVSB_IN_DEPOT) {
    01279     DiagDirection diag_dir = INVALID_DIAGDIR;
    01280
    01281     if (IsTileType(tile, MP_TUNNELBRIDGE)) {
    01282       diag_dir = GetTunnelBridgeDirection(tile);
    01283     } else if (IsRoadDepotTile(tile)) {
    01284       diag_dir = ReverseDiagDir(GetRoadDepotDirection(tile));
    01285     }
    01286
    01287     if (diag_dir == INVALID_DIAGDIR) return INVALID_TRACKDIR;
    01288     dir = DiagDirToDiagTrackdir(diag_dir);
    01289   } else {
    01290     if (already_reversed && prev->tile != tile) {
    01291       /*
    01292        * The vehicle has reversed, but did not go straight back.
    01293        * It immediatelly turn onto another tile. This means that
    01294        * the roadstate of the previous vehicle cannot be used
    01295        * as the direction we have to go with this vehicle.
    01296        *
    01297        * Next table is build in the following way:
    01298        *  - first row for when the vehicle in front went to the northern or
    01299        *    western tile, second for southern and eastern.
    01300        *  - columns represent the entry direction.
    01301        *  - cell values are determined by the Trackdir one has to take from
    01302        *    the entry dir (column) to the tile in north or south by only
    01303        *    going over the trackdirs used for turning 90 degrees, i.e.
    01304        *    TRACKDIR_{UPPER,RIGHT,LOWER,LEFT}_{N,E,S,W}.
    01305        */
    01306       Trackdir reversed_turn_lookup[2][DIAGDIR_END] = {
    01307         { TRACKDIR_UPPER_W, TRACKDIR_RIGHT_N, TRACKDIR_LEFT_N,  TRACKDIR_UPPER_E },
    01308         { TRACKDIR_RIGHT_S, TRACKDIR_LOWER_W, TRACKDIR_LOWER_E, TRACKDIR_LEFT_S  }};
    01309       dir = reversed_turn_lookup[prev->tile < tile ? 0 : 1][ReverseDiagDir(entry_dir)];
    01310     } else if (HasBit(prev_state, RVS_IN_DT_ROAD_STOP)) {
    01311       dir = (Trackdir)(prev_state & RVSB_ROAD_STOP_TRACKDIR_MASK);
    01312     } else if (prev_state < TRACKDIR_END) {
    01313       dir = (Trackdir)prev_state;
    01314     } else {
    01315       return INVALID_TRACKDIR;
    01316     }
    01317   }
    01318
    01319   /* Do some sanity checking. */
    01320   static const RoadBits required_roadbits[] = {
    01321     ROAD_X,            ROAD_Y,            ROAD_NW | ROAD_NE, ROAD_SW | ROAD_SE,
    01322     ROAD_NW | ROAD_SW, ROAD_NE | ROAD_SE, ROAD_X,            ROAD_Y
    01323   };
    01324   RoadBits required = required_roadbits[dir & 0x07];
    01325
    01326   if ((required & GetAnyRoadBits(tile, v->u.road.roadtype, true)) == ROAD_NONE) {
    01327     dir = INVALID_TRACKDIR;
    01328   }
    01329
    01330   return dir;
    01331 }
    01332
    01340 static bool CanBuildTramTrackOnTile(CompanyID c, TileIndex t, RoadBits r)
    01341 {
    01342   /* The 'current' company is not necessarily the owner of the vehicle. */
    01343   CompanyID original_company = _current_company;
    01344   _current_company = c;
    01345
    01346   CommandCost ret = DoCommand(t, ROADTYPE_TRAM << 4 | r, 0, DC_NONE, CMD_BUILD_ROAD);
    01347
    01348   _current_company = original_company;
    01349   return CmdSucceeded(ret);
    01350 }
    01351
    01352 static bool IndividualRoadVehicleController(Vehicle *v, const Vehicle *prev)
    01353 {
    01354   if (v->u.road.overtaking != 0)  {
    01355     if (IsTileType(v->tile, MP_STATION)) {
    01356       /* Force us to be not overtaking! */
    01357       v->u.road.overtaking = 0;
    01358     } else if (++v->u.road.overtaking_ctr >= 35) {
    01359       /* If overtaking just aborts at a random moment, we can have a out-of-bound problem,
    01360        *  if the vehicle started a corner. To protect that, only allow an abort of
    01361        *  overtake if we are on straight roads */
    01362       if (v->u.road.state < RVSB_IN_ROAD_STOP && IsStraightRoadTrackdir((Trackdir)v->u.road.state)) {
    01363         v->u.road.overtaking = 0;
    01364       }
    01365     }
    01366   }
    01367
    01368   /* If this vehicle is in a depot and we've reached this point it must be
    01369    * one of the articulated parts. It will stay in the depot until activated
    01370    * by the previous vehicle in the chain when it gets to the right place. */
    01371   if (v->IsInDepot()) return true;
    01372
    01373   if (v->u.road.state == RVSB_WORMHOLE) {
    01374     /* Vehicle is entering a depot or is on a bridge or in a tunnel */
    01375     GetNewVehiclePosResult gp = GetNewVehiclePos(v);
    01376
    01377     if (IsRoadVehFront(v)) {
    01378       const Vehicle *u = RoadVehFindCloseTo(v, gp.x, gp.y, v->direction);
    01379       if (u != NULL) {
    01380         v->cur_speed = u->First()->cur_speed;
    01381         return false;
    01382       }
    01383     }
    01384
    01385     if (IsTileType(gp.new_tile, MP_TUNNELBRIDGE) && HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
    01386       /* Vehicle has just entered a bridge or tunnel */
    01387       v->UpdateDeltaXY(v->direction);
    01388       SetRoadVehPosition(v, gp.x, gp.y);
    01389       return true;
    01390     }
    01391
    01392     v->x_pos = gp.x;
    01393     v->y_pos = gp.y;
    01394     VehicleMove(v, !(v->vehstatus & VS_HIDDEN));
    01395     return true;
    01396   }
    01397
    01398   /* Get move position data for next frame.
    01399    * For a drive-through road stop use 'straight road' move data.
    01400    * In this case v->u.road.state is masked to give the road stop entry direction. */
    01401   RoadDriveEntry rd = _road_drive_data[v->u.road.roadtype][(
    01402     (HasBit(v->u.road.state, RVS_IN_DT_ROAD_STOP) ? v->u.road.state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->u.road.state) +
    01403     (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1];
    01404
    01405   if (rd.x & RDE_NEXT_TILE) {
    01406     TileIndex tile = v->tile + TileOffsByDiagDir((DiagDirection)(rd.x & 3));
    01407     Trackdir dir;
    01408
    01409     if (IsRoadVehFront(v)) {
    01410       /* If this is the front engine, look for the right path. */
    01411       dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3));
    01412     } else {
    01413       dir = FollowPreviousRoadVehicle(v, prev, tile, (DiagDirection)(rd.x & 3), false);
    01414     }
    01415
    01416     if (dir == INVALID_TRACKDIR) {
    01417       if (!IsRoadVehFront(v)) error("Disconnecting road vehicle.");
    01418       v->cur_speed = 0;
    01419       return false;
    01420     }
    01421
    01422 again:
    01423     uint start_frame = RVC_DEFAULT_START_FRAME;
    01424     if (IsReversingRoadTrackdir(dir)) {
    01425       /* Turning around */
    01426       if (v->u.road.roadtype == ROADTYPE_TRAM) {
    01427         /* Determine the road bits the tram needs to be able to turn around
    01428          * using the 'big' corner loop. */
    01429         RoadBits needed;
    01430         switch (dir) {
    01431           default: NOT_REACHED();
    01432           case TRACKDIR_RVREV_NE: needed = ROAD_SW; break;
    01433           case TRACKDIR_RVREV_SE: needed = ROAD_NW; break;
    01434           case TRACKDIR_RVREV_SW: needed = ROAD_NE; break;
    01435           case TRACKDIR_RVREV_NW: needed = ROAD_SE; break;
    01436         }
    01437         if ((v->Previous() != NULL && v->Previous()->tile == tile) ||
    01438             (IsRoadVehFront(v) && IsNormalRoadTile(tile) && !HasRoadWorks(tile) &&
    01439               (needed & GetRoadBits(tile, ROADTYPE_TRAM)) != ROAD_NONE)) {
    01440           /*
    01441            * Taking the 'big' corner for trams only happens when:
    01442            * - The previous vehicle in this (articulated) tram chain is
    01443            *   already on the 'next' tile, we just follow them regardless of
    01444            *   anything. When it is NOT on the 'next' tile, the tram started
    01445            *   doing a reversing turn when the piece of tram track on the next
    01446            *   tile did not exist yet. Do not use the big tram loop as that is
    01447            *   going to cause the tram to split up.
    01448            * - Or the front of the tram can drive over the next tile.
    01449            */
    01450         } else if (!IsRoadVehFront(v) || !CanBuildTramTrackOnTile(v->owner, tile, needed) || ((~needed & GetAnyRoadBits(v->tile, ROADTYPE_TRAM, false)) == ROAD_NONE)) {
    01451           /*
    01452            * Taking the 'small' corner for trams only happens when:
    01453            * - We are not the from vehicle of an articulated tram.
    01454            * - Or when the company cannot build on the next tile.
    01455            *
    01456            * The 'small' corner means that the vehicle is on the end of a
    01457            * tram track and needs to start turning there. To do this properly
    01458            * the tram needs to start at an offset in the tram turning 'code'
    01459            * for 'big' corners. It furthermore does not go to the next tile,
    01460            * so that needs to be fixed too.
    01461            */
    01462           tile = v->tile;
    01463           start_frame = RVC_TURN_AROUND_START_FRAME_SHORT_TRAM;
    01464         } else {
    01465           /* The company can build on the next tile, so wait till (s)he does. */
    01466           v->cur_speed = 0;
    01467           return false;
    01468         }
    01469       } else if (IsNormalRoadTile(v->tile) && GetDisallowedRoadDirections(v->tile) != DRD_NONE) {
    01470         v->cur_speed = 0;
    01471         return false;
    01472       } else {
    01473         tile = v->tile;
    01474       }
    01475     }
    01476
    01477     /* Get position data for first frame on the new tile */
    01478     const RoadDriveEntry *rdp = _road_drive_data[v->u.road.roadtype][(dir + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking];
    01479
    01480     int x = TileX(tile) * TILE_SIZE + rdp[start_frame].x;
    01481     int y = TileY(tile) * TILE_SIZE + rdp[start_frame].y;
    01482
    01483     Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
    01484     if (IsRoadVehFront(v)) {
    01485       Vehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
    01486       if (u != NULL) {
    01487         v->cur_speed = u->First()->cur_speed;
    01488         return false;
    01489       }
    01490     }
    01491
    01492     uint32 r = VehicleEnterTile(v, tile, x, y);
    01493     if (HasBit(r, VETS_CANNOT_ENTER)) {
    01494       if (!IsTileType(tile, MP_TUNNELBRIDGE)) {
    01495         v->cur_speed = 0;
    01496         return false;
    01497       }
    01498       /* Try an about turn to re-enter the previous tile */
    01499       dir = _road_reverse_table[rd.x & 3];
    01500       goto again;
    01501     }
    01502
    01503     if (IsInsideMM(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) && IsTileType(v->tile, MP_STATION)) {
    01504       if (IsReversingRoadTrackdir(dir) && IsInsideMM(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
    01505         /* New direction is trying to turn vehicle around.
    01506          * We can't turn at the exit of a road stop so wait.*/
    01507         v->cur_speed = 0;
    01508         return false;
    01509       }
    01510       if (IsRoadStop(v->tile)) {
    01511         RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile));
    01512
    01513         /* Vehicle is leaving a road stop tile, mark bay as free
    01514          * For drive-through stops, only do it if the vehicle stopped here */
    01515         if (IsStandardRoadStopTile(v->tile) || HasBit(v->u.road.state, RVS_IS_STOPPING)) {
    01516           rs->FreeBay(HasBit(v->u.road.state, RVS_USING_SECOND_BAY));
    01517           ClrBit(v->u.road.state, RVS_IS_STOPPING);
    01518         }
    01519         if (IsStandardRoadStopTile(v->tile)) rs->SetEntranceBusy(false);
    01520       }
    01521     }
    01522
    01523     if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
    01524       v->tile = tile;
    01525       v->u.road.state = (byte)dir;
    01526       v->u.road.frame = start_frame;
    01527     }
    01528     if (new_dir != v->direction) {
    01529       v->direction = new_dir;
    01530       v->cur_speed -= v->cur_speed >> 2;
    01531     }
    01532
    01533     v->UpdateDeltaXY(v->direction);
    01534     RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y));
    01535     return true;
    01536   }
    01537
    01538   if (rd.x & RDE_TURNED) {
    01539     /* Vehicle has finished turning around, it will now head back onto the same tile */
    01540     Trackdir dir;
    01541     uint turn_around_start_frame = RVC_TURN_AROUND_START_FRAME;
    01542
    01543     RoadBits tram;
    01544     if (v->u.road.roadtype == ROADTYPE_TRAM && !IsRoadDepotTile(v->tile) && CountBits(tram = GetAnyRoadBits(v->tile, ROADTYPE_TRAM, true)) == 1) {
    01545       /*
    01546        * The tram is turning around with one tram 'roadbit'. This means that
    01547        * it is using the 'big' corner 'drive data'. However, to support the
    01548        * trams to take a small corner, there is a 'turned' marker in the middle
    01549        * of the turning 'drive data'. When the tram took the long corner, we
    01550        * will still use the 'big' corner drive data, but we advance it one
    01551        * frame. We furthermore set the driving direction so the turning is
    01552        * going to be properly shown.
    01553        */
    01554       turn_around_start_frame = RVC_START_FRAME_AFTER_LONG_TRAM;
    01555       switch (rd.x & 0x3) {
    01556         default: NOT_REACHED();
    01557         case DIAGDIR_NW: dir = TRACKDIR_RVREV_SE; break;
    01558         case DIAGDIR_NE: dir = TRACKDIR_RVREV_SW; break;
    01559         case DIAGDIR_SE: dir = TRACKDIR_RVREV_NW; break;
    01560         case DIAGDIR_SW: dir = TRACKDIR_RVREV_NE; break;
    01561       }
    01562     } else {
    01563       if (IsRoadVehFront(v)) {
    01564         /* If this is the front engine, look for the right path. */
    01565         dir = RoadFindPathToDest(v, v->tile, (DiagDirection)(rd.x & 3));
    01566       } else {
    01567         dir = FollowPreviousRoadVehicle(v, prev, v->tile, (DiagDirection)(rd.x & 3), true);
    01568       }
    01569     }
    01570
    01571     if (dir == INVALID_TRACKDIR) {
    01572       v->cur_speed = 0;
    01573       return false;
    01574     }
    01575
    01576     const RoadDriveEntry *rdp = _road_drive_data[v->u.road.roadtype][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + dir];
    01577
    01578     int x = TileX(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].x;
    01579     int y = TileY(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].y;
    01580
    01581     Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
    01582     if (IsRoadVehFront(v) && RoadVehFindCloseTo(v, x, y, new_dir) != NULL) return false;
    01583
    01584     uint32 r = VehicleEnterTile(v, v->tile, x, y);
    01585     if (HasBit(r, VETS_CANNOT_ENTER)) {
    01586       v->cur_speed = 0;
    01587       return false;
    01588     }
    01589
    01590     v->u.road.state = dir;
    01591     v->u.road.frame = turn_around_start_frame;
    01592
    01593     if (new_dir != v->direction) {
    01594       v->direction = new_dir;
    01595       v->cur_speed -= v->cur_speed >> 2;
    01596     }
    01597
    01598     v->UpdateDeltaXY(v->direction);
    01599     RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y));
    01600     return true;
    01601   }
    01602
    01603   /* This vehicle is not in a wormhole and it hasn't entered a new tile. If
    01604    * it's on a depot tile, check if it's time to activate the next vehicle in
    01605    * the chain yet. */
    01606   if (v->Next() != NULL && IsRoadDepotTile(v->tile)) {
    01607     if (v->u.road.frame == v->u.road.cached_veh_length + RVC_DEPOT_START_FRAME) {
    01608       RoadVehLeaveDepot(v->Next(), false);
    01609     }
    01610   }
    01611
    01612   /* Calculate new position for the vehicle */
    01613   int x = (v->x_pos & ~15) + (rd.x & 15);
    01614   int y = (v->y_pos & ~15) + (rd.y & 15);
    01615
    01616   Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
    01617
    01618   if (IsRoadVehFront(v) && !IsInsideMM(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
    01619     /* Vehicle is not in a road stop.
    01620      * Check for another vehicle to overtake */
    01621     Vehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
    01622
    01623     if (u != NULL) {
    01624       u = u->First();
    01625       /* There is a vehicle in front overtake it if possible */
    01626       if (v->u.road.overtaking == 0) RoadVehCheckOvertake(v, u);
    01627       if (v->u.road.overtaking == 0) v->cur_speed = u->cur_speed;
    01628       return false;
    01629     }
    01630   }
    01631
    01632   Direction old_dir = v->direction;
    01633   if (new_dir != old_dir) {
    01634     v->direction = new_dir;
    01635     v->cur_speed -= (v->cur_speed >> 2);
    01636     if (old_dir != v->u.road.state) {
    01637       /* The vehicle is in a road stop */
    01638       v->UpdateDeltaXY(v->direction);
    01639       SetRoadVehPosition(v, v->x_pos, v->y_pos);
    01640       /* Note, return here means that the frame counter is not incremented
    01641        * for vehicles changing direction in a road stop. This causes frames to
    01642        * be repeated. (XXX) Is this intended? */
    01643       return true;
    01644     }
    01645   }
    01646
    01647   /* If the vehicle is in a normal road stop and the frame equals the stop frame OR
    01648    * if the vehicle is in a drive-through road stop and this is the destination station
    01649    * and it's the correct type of stop (bus or truck) and the frame equals the stop frame...
    01650    * (the station test and stop type test ensure that other vehicles, using the road stop as
    01651    * a through route, do not stop) */
    01652   if (IsRoadVehFront(v) && ((IsInsideMM(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) &&
    01653       _road_veh_data_1[v->u.road.state - RVSB_IN_ROAD_STOP + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)] == v->u.road.frame) ||
    01654       (IsInsideMM(v->u.road.state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
    01655       v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
    01656       v->owner == GetTileOwner(v->tile) &&
    01657       GetRoadStopType(v->tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? ROADSTOP_BUS : ROADSTOP_TRUCK) &&
    01658       v->u.road.frame == RVC_DRIVE_THROUGH_STOP_FRAME))) {
    01659
    01660     RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile));
    01661     Station *st = GetStationByTile(v->tile);
    01662
    01663     /* Vehicle is at the stop position (at a bay) in a road stop.
    01664      * Note, if vehicle is loading/unloading it has already been handled,
    01665      * so if we get here the vehicle has just arrived or is just ready to leave. */
    01666     if (!v->current_order.IsType(OT_LEAVESTATION)) {
    01667       /* Vehicle has arrived at a bay in a road stop */
    01668
    01669       if (IsDriveThroughStopTile(v->tile)) {
    01670         TileIndex next_tile = TILE_ADD(v->tile, TileOffsByDir(v->direction));
    01671         RoadStopType type = IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? ROADSTOP_BUS : ROADSTOP_TRUCK;
    01672
    01673         /* Check if next inline bay is free */
    01674         if (IsDriveThroughStopTile(next_tile) && (GetRoadStopType(next_tile) == type) && GetStationIndex(v->tile) == GetStationIndex(next_tile)) {
    01675           RoadStop *rs_n = GetRoadStopByTile(next_tile, type);
    01676
    01677           if (rs_n->IsFreeBay(HasBit(v->u.road.state, RVS_USING_SECOND_BAY)) && rs_n->num_vehicles < RoadStop::MAX_VEHICLES) {
    01678             /* Bay in next stop along is free - use it */
    01679             ClearSlot(v);
    01680             rs_n->num_vehicles++;
    01681             v->u.road.slot = rs_n;
    01682             v->dest_tile = rs_n->xy;
    01683             v->u.road.slot_age = 14;
    01684
    01685             v->u.road.frame++;
    01686             RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y));
    01687             return true;
    01688           }
    01689         }
    01690       }
    01691
    01692       rs->SetEntranceBusy(false);
    01693
    01694       v->last_station_visited = st->index;
    01695
    01696       if (IsDriveThroughStopTile(v->tile) || (v->current_order.IsType(OT_GOTO_STATION) && v->current_order.GetDestination() == st->index)) {
    01697         RoadVehArrivesAt(v, st);
    01698         v->BeginLoading();
    01699         return false;
    01700       }
    01701     } else {
    01702       /* Vehicle is ready to leave a bay in a road stop */
    01703       if (rs->IsEntranceBusy()) {
    01704         /* Road stop entrance is busy, so wait as there is nowhere else to go */
    01705         v->cur_speed = 0;
    01706         return false;
    01707       }
    01708       v->current_order.Free();
    01709       ClearSlot(v);
    01710     }
    01711
    01712     if (IsStandardRoadStopTile(v->tile)) rs->SetEntranceBusy(true);
    01713
    01714     if (rs == v->u.road.slot) {
    01715       /* We are leaving the correct station */
    01716       ClearSlot(v);
    01717     } else if (v->u.road.slot != NULL) {
    01718       /* We are leaving the wrong station
    01719        * XXX The question is .. what to do? Actually we shouldn't be here
    01720        * but I guess we need to clear the slot */
    01721       DEBUG(ms, 0, "Vehicle %d (index %d) arrived at wrong stop", v->unitnumber, v->index);
    01722       if (v->tile != v->dest_tile) {
    01723         DEBUG(ms, 2, " current tile 0x%X is not destination tile 0x%X. Route problem", v->tile, v->dest_tile);
    01724       }
    01725       if (v->dest_tile != v->u.road.slot->xy) {
    01726         DEBUG(ms, 2, " stop tile 0x%X is not destination tile 0x%X. Multistop desync", v->u.road.slot->xy, v->dest_tile);
    01727       }
    01728       if (!v->current_order.IsType(OT_GOTO_STATION)) {
    01729         DEBUG(ms, 2, " current order type (%d) is not OT_GOTO_STATION", v->current_order.GetType());
    01730       } else {
    01731         if (v->current_order.GetDestination() != st->index)
    01732           DEBUG(ms, 2, " current station %d is not target station in current_order.station (%d)",
    01733               st->index, v->current_order.GetDestination());
    01734       }
    01735
    01736       DEBUG(ms, 2, " force a slot clearing");
    01737       ClearSlot(v);
    01738     }
    01739
    01740     StartRoadVehSound(v);
    01741     InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
    01742   }
    01743
    01744   /* Check tile position conditions - i.e. stop position in depot,
    01745    * entry onto bridge or into tunnel */
    01746   uint32 r = VehicleEnterTile(v, v->tile, x, y);
    01747   if (HasBit(r, VETS_CANNOT_ENTER)) {
    01748     v->cur_speed = 0;
    01749     return false;
    01750   }
    01751
    01752   if (v->current_order.IsType(OT_LEAVESTATION) && IsDriveThroughStopTile(v->tile)) {
    01753     v->current_order.Free();
    01754     ClearSlot(v);
    01755   }
    01756
    01757   /* Move to next frame unless vehicle arrived at a stop position
    01758    * in a depot or entered a tunnel/bridge */
    01759   if (!HasBit(r, VETS_ENTERED_WORMHOLE)) v->u.road.frame++;
    01760
    01761   v->UpdateDeltaXY(v->direction);
    01762   RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y));
    01763   return true;
    01764 }
    01765
    01766 static void RoadVehController(Vehicle *v)
    01767 {
    01768   /* decrease counters */
    01769   v->tick_counter++;
    01770   v->current_order_time++;
    01771   if (v->u.road.reverse_ctr != 0) v->u.road.reverse_ctr--;
    01772
    01773   /* handle crashed */
    01774   if (v->vehstatus & VS_CRASHED) {
    01775     RoadVehIsCrashed(v);
    01776     return;
    01777   }
    01778
    01779   RoadVehCheckTrainCrash(v);
    01780
    01781   /* road vehicle has broken down? */
    01782   if (v->breakdown_ctr != 0) {
    01783     if (v->breakdown_ctr <= 2) {
    01784       HandleBrokenRoadVeh(v);
    01785       return;
    01786     }
    01787     if (!v->current_order.IsType(OT_LOADING)) v->breakdown_ctr--;
    01788   }
    01789
    01790   if (v->vehstatus & VS_STOPPED) return;
    01791
    01792   ProcessOrders(v);
    01793   v->HandleLoading();
    01794
    01795   if (v->current_order.IsType(OT_LOADING)) return;
    01796
    01797   if (v->IsInDepot() && RoadVehLeaveDepot(v, true)) return;
    01798
    01799   /* Check how far the vehicle needs to proceed */
    01800   int j = RoadVehAccelerate(v);
    01801
    01802   int adv_spd = (v->direction & 1) ? 192 : 256;
    01803   while (j >= adv_spd) {
    01804     j -= adv_spd;
    01805
    01806     Vehicle *u = v;
    01807     for (Vehicle *prev = NULL; u != NULL; prev = u, u = u->Next()) {
    01808       if (!IndividualRoadVehicleController(u, prev)) break;
    01809     }
    01810
    01811     /* 192 spd used for going straight, 256 for going diagonally. */
    01812     adv_spd = (v->direction & 1) ? 192 : 256;
    01813
    01814     /* Test for a collision, but only if another movement will occur. */
    01815     if (j >= adv_spd && RoadVehCheckTrainCrash(v)) break;
    01816   }
    01817
    01818   for (Vehicle *u = v; u != NULL; u = u->Next()) {
    01819     if ((u->vehstatus & VS_HIDDEN) != 0) continue;
    01820
    01821     uint16 old_image = u->cur_image;
    01822     u->cur_image = u->GetImage(u->direction);
    01823     if (old_image != u->cur_image) VehicleMove(u, true);
    01824   }
    01825
    01826   if (v->progress == 0) v->progress = j;
    01827 }
    01828
    01829 static void AgeRoadVehCargo(Vehicle *v)
    01830 {
    01831   if (_age_cargo_skip_counter != 0) return;
    01832   v->cargo.AgeCargo();
    01833 }
    01834
    01835 void RoadVehicle::Tick()
    01836 {
    01837   AgeRoadVehCargo(this);
    01838
    01839   if (IsRoadVehFront(this)) {
    01840     if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
    01841     RoadVehController(this);
    01842   }
    01843 }
    01844
    01845 static void CheckIfRoadVehNeedsService(Vehicle *v)
    01846 {
    01847   /* If we already got a slot at a stop, use that FIRST, and go to a depot later */
    01848   if (v->u.road.slot != NULL || _settings_game.vehicle.servint_roadveh == 0 || !v->NeedsAutomaticServicing()) return;
    01849   if (v->IsInDepot()) {
    01850     VehicleServiceInDepot(v);
    01851     return;
    01852   }
    01853
    01854   /* XXX If we already have a depot order, WHY do we search over and over? */
    01855   const Depot *depot = FindClosestRoadDepot(v);
    01856
    01857   if (depot == NULL || DistanceManhattan(v->tile, depot->xy) > 12) {
    01858     if (v->current_order.IsType(OT_GOTO_DEPOT)) {
    01859       v->current_order.MakeDummy();
    01860       InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
    01861     }
    01862     return;
    01863   }
    01864
    01865   if (v->current_order.IsType(OT_GOTO_DEPOT) &&
    01866       v->current_order.GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS &&
    01867       !Chance16(1, 20)) {
    01868     return;
    01869   }
    01870
    01871   if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
    01872   ClearSlot(v);
    01873
    01874   v->current_order.MakeGoToDepot(depot->index, ODTFB_SERVICE);
    01875   v->dest_tile = depot->xy;
    01876   InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
    01877 }
    01878
    01879 void RoadVehicle::OnNewDay()
    01880 {
    01881   if (!IsRoadVehFront(this)) return;
    01882
    01883   if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
    01884   if (this->u.road.blocked_ctr == 0) CheckVehicleBreakdown(this);
    01885
    01886   AgeVehicle(this);
    01887   CheckIfRoadVehNeedsService(this);
    01888
    01889   CheckOrders(this);
    01890
    01891   /* Current slot has expired */
    01892   if (this->current_order.IsType(OT_GOTO_STATION) && this->u.road.slot != NULL && this->u.road.slot_age-- == 0) {
    01893     DEBUG(ms, 3, "Slot expired for vehicle %d (index %d) at stop 0x%X",
    01894       this->unitnumber, this->index, this->u.road.slot->xy);
    01895     ClearSlot(this);
    01896   }
    01897
    01898   /* update destination */
    01899   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)) {
    01900     Station *st = GetStation(this->current_order.GetDestination());
    01901     RoadStop *rs = st->GetPrimaryRoadStop(this);
    01902     RoadStop *best = NULL;
    01903
    01904     if (rs != NULL) {
    01905       /* We try to obtain a slot if:
    01906        * 1) we're reasonably close to the primary road stop
    01907        * or
    01908        * 2) we're somewhere close to the station rectangle (to make sure we do assign
    01909        *    slots even if the station and its road stops are incredibly spread out)
    01910        */
    01911       if (DistanceManhattan(this->tile, rs->xy) < 16 || st->rect.PtInExtendedRect(TileX(this->tile), TileY(this->tile), 2)) {
    01912         uint dist, badness;
    01913         uint minbadness = UINT_MAX;
    01914
    01915         DEBUG(ms, 2, "Attempting to obtain a slot for vehicle %d (index %d) at station %d (0x%X)",
    01916           this->unitnumber, this->index, st->index, st->xy
    01917         );
    01918         /* Now we find the nearest road stop that has a free slot */
    01919         for (; rs != NULL; rs = rs->GetNextRoadStop(this)) {
    01920           if (rs->num_vehicles >= RoadStop::MAX_VEHICLES) {
    01921             DEBUG(ms, 4, " stop 0x%X's queue is full, not treating further", rs->xy);
    01922             continue;
    01923           }
    01924           dist = RoadFindPathToStop(this, rs->xy);
    01925           if (dist == UINT_MAX) {
    01926             DEBUG(ms, 4, " stop 0x%X is unreachable, not treating further", rs->xy);
    01927             continue;
    01928           }
    01929           badness = (rs->num_vehicles + 1) * (rs->num_vehicles + 1) + dist;
    01930
    01931           DEBUG(ms, 4, " stop 0x%X has %d vehicle%s waiting", rs->xy, rs->num_vehicles, rs->num_vehicles == 1 ? "":"s");
    01932           DEBUG(ms, 4, " distance is %u", dist);
    01933           DEBUG(ms, 4, " badness %u", badness);
    01934
    01935           if (badness < minbadness) {
    01936             best = rs;
    01937             minbadness = badness;
    01938           }
    01939         }
    01940
    01941         if (best != NULL) {
    01942           best->num_vehicles++;
    01943           DEBUG(ms, 3, "Assigned to stop 0x%X", best->xy);
    01944
    01945           this->u.road.slot = best;
    01946           this->dest_tile = best->xy;
    01947           this->u.road.slot_age = 14;
    01948         } else {
    01949           DEBUG(ms, 3, "Could not find a suitable stop");
    01950         }
    01951       } else {
    01952         DEBUG(ms, 5, "Distance from station too far. Postponing slotting for vehicle %d (index %d) at station %d, (0x%X)",
    01953             this->unitnumber, this->index, st->index, st->xy);
    01954       }
    01955     } else {
    01956       DEBUG(ms, 4, "No road stop for vehicle %d (index %d) at station %d (0x%X)",
    01957           this->unitnumber, this->index, st->index, st->xy);
    01958     }
    01959   }
    01960
    01961   if (this->running_ticks == 0) return;
    01962
    01963   CommandCost cost(EXPENSES_ROADVEH_RUN, this->GetRunningCost() * this->running_ticks / (DAYS_IN_YEAR * DAY_TICKS));
    01964
    01965   this->profit_this_year -= cost.GetCost();
    01966   this->running_ticks = 0;
    01967
    01968   SubtractMoneyFromCompanyFract(this->owner, cost);
    01969
    01970   InvalidateWindow(WC_VEHICLE_DETAILS, this->index);
    01971   InvalidateWindowClasses(WC_ROADVEH_LIST);
    01972 }
    01973
    01984 CommandCost CmdRefitRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    01985 {
    01986   Vehicle *v;
    01987   CommandCost cost(EXPENSES_ROADVEH_RUN);
    01988   CargoID new_cid = GB(p2, 0, 8);
    01989   byte new_subtype = GB(p2, 8, 8);
    01990   bool only_this = HasBit(p2, 16);
    01991   uint16 capacity = CALLBACK_FAILED;
    01992   uint total_capacity = 0;
    01993
    01994   if (!IsValidVehicleID(p1)) return CMD_ERROR;
    01995
    01996   v = GetVehicle(p1);
    01997
    01998   if (v->type != VEH_ROAD || !CheckOwnership(v->owner)) return CMD_ERROR;
    01999   if (!v->IsStoppedInDepot()) return_cmd_error(STR_9013_MUST_BE_STOPPED_INSIDE);
    02000   if (v->vehstatus & VS_CRASHED) return_cmd_error(STR_CAN_T_REFIT_DESTROYED_VEHICLE);
    02001
    02002   if (new_cid >= NUM_CARGO) return CMD_ERROR;
    02003
    02004   for (; v != NULL; v = (only_this ? NULL : v->Next())) {
    02005     /* XXX: We refit all the attached wagons en-masse if they can be
    02006      * refitted. This is how TTDPatch does it.  TODO: Have some nice
    02007      * [Refit] button near each wagon. */
    02008     if (!CanRefitTo(v->engine_type, new_cid)) continue;
    02009
    02010     const Engine *e = GetEngine(v->engine_type);
    02011     if (!e->CanCarryCargo()) continue;
    02012
    02013     if (HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) {
    02014       /* Back up the cargo type */
    02015       CargoID temp_cid = v->cargo_type;
    02016       byte temp_subtype = v->cargo_subtype;
    02017       v->cargo_type = new_cid;
    02018       v->cargo_subtype = new_subtype;
    02019
    02020       /* Check the refit capacity callback */
    02021       capacity = GetVehicleCallback(CBID_VEHICLE_REFIT_CAPACITY, 0, 0, v->engine_type, v);
    02022
    02023       /* Restore the original cargo type */
    02024       v->cargo_type = temp_cid;
    02025       v->cargo_subtype = temp_subtype;
    02026     }
    02027
    02028     if (capacity == CALLBACK_FAILED) {
    02029       /* callback failed or not used, use default capacity */
    02030
    02031       CargoID old_cid = e->GetDefaultCargoType();
    02032       /* normally, the capacity depends on the cargo type, a vehicle can
    02033        * carry twice as much mail/goods as normal cargo, and four times as
    02034        * many passengers
    02035        */
    02036       capacity = GetVehicleProperty(v, 0x0F, e->u.road.capacity);
    02037       switch (old_cid) {
    02038         case CT_PASSENGERS: break;
    02039         case CT_MAIL:
    02040         case CT_GOODS: capacity *= 2; break;
    02041         default:       capacity *= 4; break;
    02042       }
    02043       switch (new_cid) {
    02044         case CT_PASSENGERS: break;
    02045         case CT_MAIL:
    02046         case CT_GOODS: capacity /= 2; break;
    02047         default:       capacity /= 4; break;
    02048       }
    02049     }
    02050
    02051     total_capacity += capacity;
    02052
    02053     if (new_cid != v->cargo_type) {
    02054       cost.AddCost(GetRefitCost(v->engine_type));
    02055     }
    02056
    02057     if (flags & DC_EXEC) {
    02058       v->cargo_cap = capacity;
    02059       v->cargo.Truncate((v->cargo_type == new_cid) ? capacity : 0);
    02060       v->cargo_type = new_cid;
    02061       v->cargo_subtype = new_subtype;
    02062       InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
    02063       InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
    02064       InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
    02065     }
    02066   }
    02067
    02068   if (flags & DC_EXEC) RoadVehUpdateCache(GetVehicle(p1)->First());
    02069
    02070   _returned_refit_capacity = total_capacity;
    02071
    02072   return cost;
    02073 }