# 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 }