roadveh_cmd.cpp

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

Generated on Mon Mar 9 23:33:50 2009 for openttd by  doxygen 1.5.6