roadveh_cmd.cpp

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

Generated on Wed Oct 1 17:03:23 2008 for openttd by  doxygen 1.5.6