roadveh_cmd.cpp

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

Generated on Mon Feb 16 23:12:09 2009 for openttd by  doxygen 1.5.6