roadveh_cmd.cpp

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

Generated on Sun Sep 13 08:19:18 2009 for OpenTTD by  doxygen 1.5.6