# roadveh_cmd.cpp

Go to the documentation of this file.

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