roadveh_cmd.cpp

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

Generated on Tue Jul 21 18:48:26 2009 for OpenTTD by  doxygen 1.5.6