# roadveh_cmd.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #include "stdafx.h"
    00013 #include "landscape.h"
    00014 #include "roadveh.h"
    00015 #include "command_func.h"
    00016 #include "news_func.h"
    00017 #include "pathfinder/npf/npf_func.h"
    00018 #include "station_base.h"
    00019 #include "company_func.h"
    00020 #include "vehicle_gui.h"
    00021 #include "articulated_vehicles.h"
    00022 #include "newgrf_engine.h"
    00023 #include "newgrf_sound.h"
    00024 #include "pathfinder/yapf/yapf.h"
    00025 #include "strings_func.h"
    00026 #include "tunnelbridge_map.h"
    00027 #include "functions.h"
    00028 #include "window_func.h"
    00029 #include "date_func.h"
    00030 #include "vehicle_func.h"
    00031 #include "sound_func.h"
    00032 #include "autoreplace_gui.h"
    00033 #include "gfx_func.h"
    00034 #include "ai/ai.hpp"
    00035 #include "depot_map.h"
    00036 #include "effectvehicle_func.h"
    00037 #include "roadstop_base.h"
    00038 #include "cargotype.h"
    00039 #include "spritecache.h"
    00040 #include "debug.h"
    00041 #include "infrastructure_func.h"
    00042
    00043 #include "table/strings.h"
    00044 #include "table/sprites.h"
    00045
    00046 static const uint16 _roadveh_images[63] = {
    00047   0xCD4, 0xCDC, 0xCE4, 0xCEC, 0xCF4, 0xCFC, 0xD0C, 0xD14,
    00048   0xD24, 0xD1C, 0xD2C, 0xD04, 0xD1C, 0xD24, 0xD6C, 0xD74,
    00049   0xD7C, 0xC14, 0xC1C, 0xC24, 0xC2C, 0xC34, 0xC3C, 0xC4C,
    00050   0xC54, 0xC64, 0xC5C, 0xC6C, 0xC44, 0xC5C, 0xC64, 0xCAC,
    00051   0xCB4, 0xCBC, 0xD94, 0xD9C, 0xDA4, 0xDAC, 0xDB4, 0xDBC,
    00052   0xDCC, 0xDD4, 0xDE4, 0xDDC, 0xDEC, 0xDC4, 0xDDC, 0xDE4,
    00053   0xE2C, 0xE34, 0xE3C, 0xC14, 0xC1C, 0xC2C, 0xC3C, 0xC4C,
    00054   0xC5C, 0xC64, 0xC6C, 0xC74, 0xC84, 0xC94, 0xCA4
    00055 };
    00056
    00057 static const uint16 _roadveh_full_adder[63] = {
    00058    0,  88,   0,   0,   0,   0,  48,  48,
    00059   48,  48,   0,   0,  64,  64,   0,  16,
    00060   16,   0,  88,   0,   0,   0,   0,  48,
    00061   48,  48,  48,   0,   0,  64,  64,   0,
    00062   16,  16,   0,  88,   0,   0,   0,   0,
    00063   48,  48,  48,  48,   0,   0,  64,  64,
    00064    0,  16,  16,   0,   8,   8,   8,   8,
    00065    0,   0,   0,   8,   8,   8,   8
    00066 };
    00067
    00069 static const TrackdirBits _road_enter_dir_to_reachable_trackdirs[DIAGDIR_END] = {
    00070   TRACKDIR_BIT_LEFT_N  | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_X_NE,    // Enter from north east
    00071   TRACKDIR_BIT_LEFT_S  | TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_Y_SE,    // Enter from south east
    00072   TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_X_SW    | TRACKDIR_BIT_RIGHT_S, // Enter from south west
    00073   TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_Y_NW     // Enter from north west
    00074 };
    00075
    00076 static const Trackdir _road_reverse_table[DIAGDIR_END] = {
    00077   TRACKDIR_RVREV_NE, TRACKDIR_RVREV_SE, TRACKDIR_RVREV_SW, TRACKDIR_RVREV_NW
    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
    00090 bool RoadVehicle::IsBus() const
    00091 {
    00092   assert(this->IsRoadVehFront());
    00093   return IsCargoInClass(this->cargo_type, CC_PASSENGERS);
    00094 }
    00095
    00101 int RoadVehicle::GetDisplayImageWidth(Point *offset) const
    00102 {
    00103   int reference_width = ROADVEHINFO_DEFAULT_VEHICLE_WIDTH;
    00104
    00105   if (offset != NULL) {
    00106     offset->x = reference_width / 2;
    00107     offset->y = 0;
    00108   }
    00109   return this->rcache.cached_veh_length * reference_width / 8;
    00110 }
    00111
    00112 static SpriteID GetRoadVehIcon(EngineID engine)
    00113 {
    00114   const Engine *e = Engine::Get(engine);
    00115   uint8 spritenum = e->u.road.image_index;
    00116
    00117   if (is_custom_sprite(spritenum)) {
    00118     SpriteID sprite = GetCustomVehicleIcon(engine, DIR_W);
    00119     if (sprite != 0) return sprite;
    00120
    00121     spritenum = e->original_image_index;
    00122   }
    00123
    00124   return DIR_W + _roadveh_images[spritenum];
    00125 }
    00126
    00127 SpriteID RoadVehicle::GetImage(Direction direction) const
    00128 {
    00129   uint8 spritenum = this->spritenum;
    00130   SpriteID sprite;
    00131
    00132   if (is_custom_sprite(spritenum)) {
    00133     sprite = GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)));
    00134     if (sprite != 0) return sprite;
    00135
    00136     spritenum = Engine::Get(this->engine_type)->original_image_index;
    00137   }
    00138
    00139   sprite = direction + _roadveh_images[spritenum];
    00140
    00141   if (this->cargo.Count() >= this->cargo_cap / 2U) sprite += _roadveh_full_adder[spritenum];
    00142
    00143   return sprite;
    00144 }
    00145
    00146 void DrawRoadVehEngine(int left, int right, int preferred_x, int y, EngineID engine, SpriteID pal)
    00147 {
    00148   SpriteID sprite = GetRoadVehIcon(engine);
    00149   const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
    00150   preferred_x = Clamp(preferred_x, left - real_sprite->x_offs, right - real_sprite->width - real_sprite->x_offs);
    00151   DrawSprite(sprite, pal, preferred_x, y);
    00152 }
    00153
    00154 static uint GetRoadVehLength(const RoadVehicle *v)
    00155 {
    00156   uint length = 8;
    00157
    00158   uint16 veh_len = GetVehicleCallback(CBID_VEHICLE_LENGTH, 0, 0, v->engine_type, v);
    00159   if (veh_len != CALLBACK_FAILED) {
    00160     length -= Clamp(veh_len, 0, 7);
    00161   }
    00162
    00163   return length;
    00164 }
    00165
    00166 void RoadVehUpdateCache(RoadVehicle *v)
    00167 {
    00168   assert(v->type == VEH_ROAD);
    00169   assert(v->IsRoadVehFront());
    00170
    00171   v->InvalidateNewGRFCacheOfChain();
    00172
    00173   v->rcache.cached_total_length = 0;
    00174
    00175   for (RoadVehicle *u = v; u != NULL; u = u->Next()) {
    00176     /* Check the v->first cache. */
    00177     assert(u->First() == v);
    00178
    00179     /* Update the 'first engine' */
    00180     u->rcache.first_engine = (v == u) ? INVALID_ENGINE : v->engine_type;
    00181
    00182     /* Update the length of the vehicle. */
    00183     u->rcache.cached_veh_length = GetRoadVehLength(u);
    00184     v->rcache.cached_total_length += u->rcache.cached_veh_length;
    00185
    00186     /* Invalidate the vehicle colour map */
    00187     u->colourmap = PAL_NONE;
    00188   }
    00189 }
    00190
    00199 CommandCost CmdBuildRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    00200 {
    00201   if (!IsEngineBuildable(p1, VEH_ROAD, _current_company)) return_cmd_error(STR_ERROR_ROAD_VEHICLE_NOT_AVAILABLE);
    00202
    00203   const Engine *e = Engine::Get(p1);
    00204   /* Engines without valid cargo should not be available */
    00205   if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR;
    00206
    00207   CommandCost cost(EXPENSES_NEW_VEHICLES, e->GetCost());
    00208   if (flags & DC_QUERY_COST) return cost;
    00209
    00210   /* The ai_new queries the vehicle cost before building the route,
    00211    * so we must check against cheaters no sooner than now. --pasky */
    00212   if (!IsRoadDepotTile(tile)) return CMD_ERROR;
    00213   if (!CheckInfraUsageAllowed(GetTileOwner(tile), VEH_ROAD)) return CMD_ERROR;
    00214
    00215   if (HasTileRoadType(tile, ROADTYPE_TRAM) != HasBit(e->info.misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_ERROR_DEPOT_WRONG_DEPOT_TYPE);
    00216
    00217   uint num_vehicles = 1 + CountArticulatedParts(p1, false);
    00218
    00219   /* Allow for the front and the articulated parts */
    00220   if (!Vehicle::CanAllocateItem(num_vehicles)) {
    00221     return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
    00222   }
    00223
    00224   /* find the first free roadveh id */
    00225   UnitID unit_num = (flags & DC_AUTOREPLACE) ? 0 : GetFreeUnitNumber(VEH_ROAD);
    00226   if (unit_num > _settings_game.vehicle.max_roadveh) {
    00227     return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
    00228   }
    00229
    00230   if (flags & DC_EXEC) {
    00231     const RoadVehicleInfo *rvi = &e->u.road;
    00232
    00233     RoadVehicle *v = new RoadVehicle();
    00234     v->unitnumber = unit_num;
    00235     v->direction = DiagDirToDir(GetRoadDepotDirection(tile));
    00236     v->owner = _current_company;
    00237
    00238     v->tile = tile;
    00239     int x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2;
    00240     int y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2;
    00241     v->x_pos = x;
    00242     v->y_pos = y;
    00243     v->z_pos = GetSlopeZ(x, y);
    00244
    00245 //    v->running_ticks = 0;
    00246
    00247     v->state = RVSB_IN_DEPOT;
    00248     v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
    00249
    00250     v->spritenum = rvi->image_index;
    00251     v->cargo_type = e->GetDefaultCargoType();
    00252 //    v->cargo_subtype = 0;
    00253     v->cargo_cap = rvi->capacity;
    00254 //    v->cargo_count = 0;
    00255     v->value = cost.GetCost();
    00256 //    v->day_counter = 0;
    00257 //    v->next_order_param = v->next_order = 0;
    00258 //    v->time_counter = 0;
    00259 //    v->progress = 0;
    00260
    00261 //    v->overtaking = 0;
    00262
    00263     v->last_station_visited = INVALID_STATION;
    00264     v->max_speed = rvi->max_speed;
    00265     v->engine_type = (EngineID)p1;
    00266     v->rcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
    00267
    00268     v->reliability = e->reliability;
    00269     v->reliability_spd_dec = e->reliability_spd_dec;
    00270     v->max_age = e->GetLifeLengthInDays();
    00271     _new_vehicle_id = v->index;
    00272
    00273     v->name = NULL;
    00274
    00275     v->service_interval = Company::Get(v->owner)->settings.vehicle.servint_roadveh;
    00276
    00277     v->date_of_last_service = _date;
    00278     v->build_year = _cur_year;
    00279
    00280     v->cur_image = SPR_IMG_QUERY;
    00281     v->random_bits = VehicleRandomBits();
    00282     v->SetRoadVehFront();
    00283
    00284     v->roadtype = HasBit(e->info.misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
    00285     v->compatible_roadtypes = RoadTypeToRoadTypes(v->roadtype);
    00286     v->rcache.cached_veh_length = 8;
    00287
    00288     v->vehicle_flags = 0;
    00289     if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
    00290
    00291     AddArticulatedParts(v);
    00292     v->InvalidateNewGRFCacheOfChain();
    00293
    00294     /* Call various callbacks after the whole consist has been constructed */
    00295     for (RoadVehicle *u = v; u != NULL; u = u->Next()) {
    00296       u->cargo_cap = GetVehicleCapacity(u);
    00297       v->InvalidateNewGRFCache();
    00298       u->InvalidateNewGRFCache();
    00299     }
    00300     RoadVehUpdateCache(v);
    00301
    00302     VehicleMove(v, false);
    00303
    00304     InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
    00305     InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
    00306     SetWindowDirty(WC_COMPANY, v->owner);
    00307     if (IsLocalCompany()) {
    00308       InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Road window
    00309     }
    00310
    00311     Company::Get(_current_company)->num_engines[p1]++;
    00312
    00313     CheckConsistencyOfArticulatedVehicle(v);
    00314   }
    00315
    00316   return cost;
    00317 }
    00318
    00319 bool RoadVehicle::IsStoppedInDepot() const
    00320 {
    00321   TileIndex tile = this->tile;
    00322
    00323   if (!IsRoadDepotTile(tile)) return false;
    00324   if (this->IsRoadVehFront() && !(this->vehstatus & VS_STOPPED)) return false;
    00325
    00326   for (const RoadVehicle *v = this; v != NULL; v = v->Next()) {
    00327     if (v->state != RVSB_IN_DEPOT || v->tile != tile) return false;
    00328   }
    00329   return true;
    00330 }
    00331
    00340 CommandCost CmdSellRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    00341 {
    00342   RoadVehicle *v = RoadVehicle::GetIfValid(p1);
    00343   if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR;
    00344
    00345   if (v->vehstatus & VS_CRASHED) return_cmd_error(STR_ERROR_CAN_T_SELL_DESTROYED_VEHICLE);
    00346
    00347   if (!v->IsStoppedInDepot()) {
    00348     return_cmd_error(STR_ERROR_ROAD_VEHICLE_MUST_BE_STOPPED_INSIDE_DEPOT);
    00349   }
    00350
    00351   CommandCost ret(EXPENSES_NEW_VEHICLES, -v->value);
    00352
    00353   if (flags & DC_EXEC) {
    00354     delete v;
    00355   }
    00356
    00357   return ret;
    00358 }
    00359
    00360 static FindDepotData FindClosestRoadDepot(const RoadVehicle *v, int max_distance)
    00361 {
    00362   if (IsRoadDepotTile(v->tile)) return FindDepotData(v->tile, 0);
    00363
    00364   switch (_settings_game.pf.pathfinder_for_roadvehs) {
    00365     case VPF_NPF: return NPFRoadVehicleFindNearestDepot(v, max_distance);
    00366     case VPF_YAPF: return YapfRoadVehicleFindNearestDepot(v, max_distance);
    00367
    00368     default: NOT_REACHED();
    00369   }
    00370 }
    00371
    00372 bool RoadVehicle::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
    00373 {
    00374   FindDepotData rfdd = FindClosestRoadDepot(this, 0);
    00375   if (rfdd.best_length == UINT_MAX) return false;
    00376
    00377   if (location    != NULL) *location    = rfdd.tile;
    00378   if (destination != NULL) *destination = GetDepotIndex(rfdd.tile);
    00379
    00380   return true;
    00381 }
    00382
    00393 CommandCost CmdSendRoadVehToDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    00394 {
    00395   if (p2 & DEPOT_MASS_SEND) {
    00396     /* Mass goto depot requested */
    00397     if (!ValidVLWFlags(p2 & VLW_MASK)) return CMD_ERROR;
    00398     return SendAllVehiclesToDepot(VEH_ROAD, flags, p2 & DEPOT_SERVICE, _current_company, (p2 & VLW_MASK), p1);
    00399   }
    00400
    00401   RoadVehicle *v = RoadVehicle::GetIfValid(p1);
    00402   if (v == NULL) return CMD_ERROR;
    00403
    00404   return v->SendToDepot(flags, (DepotCommand)(p2 & DEPOT_COMMAND_MASK));
    00405 }
    00406
    00415 CommandCost CmdTurnRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    00416 {
    00417   RoadVehicle *v = RoadVehicle::GetIfValid(p1);
    00418   if (v == NULL || !CheckVehicleControlAllowed(v)) return CMD_ERROR;
    00419
    00420   if ((v->vehstatus & VS_STOPPED) ||
    00421       (v->vehstatus & VS_CRASHED) ||
    00422       v->breakdown_ctr != 0 ||
    00423       v->overtaking != 0 ||
    00424       v->state == RVSB_WORMHOLE ||
    00425       v->IsInDepot() ||
    00426       v->cur_speed < 5) {
    00427     return CMD_ERROR;
    00428   }
    00429
    00430   if (IsNormalRoadTile(v->tile) && GetDisallowedRoadDirections(v->tile) != DRD_NONE) return CMD_ERROR;
    00431
    00432   if (IsTileType(v->tile, MP_TUNNELBRIDGE) && DirToDiagDir(v->direction) == GetTunnelBridgeDirection(v->tile)) return CMD_ERROR;
    00433
    00434   if (flags & DC_EXEC) v->reverse_ctr = 180;
    00435
    00436   return CommandCost();
    00437 }
    00438
    00439
    00440 void RoadVehicle::MarkDirty()
    00441 {
    00442   for (Vehicle *v = this; v != NULL; v = v->Next()) {
    00443     v->UpdateViewport(false, false);
    00444   }
    00445 }
    00446
    00447 void RoadVehicle::UpdateDeltaXY(Direction direction)
    00448 {
    00449 #define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0)
    00450   static const uint32 _delta_xy_table[8] = {
    00451     MKIT(3, 3, -1, -1),
    00452     MKIT(3, 7, -1, -3),
    00453     MKIT(3, 3, -1, -1),
    00454     MKIT(7, 3, -3, -1),
    00455     MKIT(3, 3, -1, -1),
    00456     MKIT(3, 7, -1, -3),
    00457     MKIT(3, 3, -1, -1),
    00458     MKIT(7, 3, -3, -1),
    00459   };
    00460 #undef MKIT
    00461
    00462   uint32 x = _delta_xy_table[direction];
    00463   this->x_offs        = GB(x,  0, 8);
    00464   this->y_offs        = GB(x,  8, 8);
    00465   this->x_extent      = GB(x, 16, 8);
    00466   this->y_extent      = GB(x, 24, 8);
    00467   this->z_extent      = 6;
    00468 }
    00469
    00470 static void DeleteLastRoadVeh(RoadVehicle *v)
    00471 {
    00472   Vehicle *u = v;
    00473   for (; v->Next() != NULL; v = v->Next()) u = v;
    00474   u->SetNext(NULL);
    00475
    00476   /* Only leave the road stop when we're really gone. */
    00477   if (IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v);
    00478
    00479   delete v;
    00480 }
    00481
    00482 static byte SetRoadVehPosition(RoadVehicle *v, int x, int y, bool turned)
    00483 {
    00484   byte new_z, old_z;
    00485
    00486   /* need this hint so it returns the right z coordinate on bridges. */
    00487   v->x_pos = x;
    00488   v->y_pos = y;
    00489   new_z = GetSlopeZ(x, y);
    00490
    00491   old_z = v->z_pos;
    00492   v->z_pos = new_z;
    00493
    00494   v->UpdateViewport(true, turned);
    00495   return old_z;
    00496 }
    00497
    00498 static void RoadVehSetRandomDirection(RoadVehicle *v)
    00499 {
    00500   static const DirDiff delta[] = {
    00501     DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT
    00502   };
    00503
    00504   do {
    00505     uint32 r = Random();
    00506
    00507     v->direction = ChangeDir(v->direction, delta[r & 3]);
    00508     SetRoadVehPosition(v, v->x_pos, v->y_pos, true);
    00509   } while ((v = v->Next()) != NULL);
    00510 }
    00511
    00512 static bool RoadVehIsCrashed(RoadVehicle *v)
    00513 {
    00514   v->crashed_ctr++;
    00515   if (v->crashed_ctr == 2) {
    00516     CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
    00517   } else if (v->crashed_ctr <= 45) {
    00518     if ((v->tick_counter & 7) == 0) RoadVehSetRandomDirection(v);
    00519   } else if (v->crashed_ctr >= 2220 && !(v->tick_counter & 0x1F)) {
    00520     bool ret = v->Next() != NULL;
    00521     DeleteLastRoadVeh(v);
    00522     return ret;
    00523   }
    00524
    00525   return true;
    00526 }
    00527
    00528 static Vehicle *EnumCheckRoadVehCrashTrain(Vehicle *v, void *data)
    00529 {
    00530   const Vehicle *u = (Vehicle*)data;
    00531
    00532   return
    00533     v->type == VEH_TRAIN &&
    00534     abs(v->z_pos - u->z_pos) <= 6 &&
    00535     abs(v->x_pos - u->x_pos) <= 4 &&
    00536     abs(v->y_pos - u->y_pos) <= 4 ?
    00537       v : NULL;
    00538 }
    00539
    00540 uint RoadVehicle::Crash(bool flooded)
    00541 {
    00542   uint pass = Vehicle::Crash(flooded);
    00543   if (this->IsRoadVehFront()) {
    00544     pass += 1; // driver
    00545
    00546     /* If we're in a drive through road stop we ought to leave it */
    00547     if (IsInsideMM(this->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END)) {
    00548       RoadStop::GetByTile(this->tile, GetRoadStopType(this->tile))->Leave(this);
    00549     }
    00550   }
    00551   this->crashed_ctr = flooded ? 2000 : 1; // max 2220, disappear pretty fast when flooded
    00552   return pass;
    00553 }
    00554
    00555 static void RoadVehCrash(RoadVehicle *v)
    00556 {
    00557   uint pass = v->Crash();
    00558
    00559   AI::NewEvent(v->owner, new AIEventVehicleCrashed(v->index, v->tile, AIEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING));
    00560
    00561   SetDParam(0, pass);
    00562   AddVehicleNewsItem(
    00563     (pass == 1) ?
    00564       STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER : STR_NEWS_ROAD_VEHICLE_CRASH,
    00565     NS_ACCIDENT,
    00566     v->index
    00567   );
    00568
    00569   ModifyStationRatingAround(v->tile, v->owner, -160, 22);
    00570   SndPlayVehicleFx(SND_12_EXPLOSION, v);
    00571 }
    00572
    00573 static bool RoadVehCheckTrainCrash(RoadVehicle *v)
    00574 {
    00575   for (RoadVehicle *u = v; u != NULL; u = u->Next()) {
    00576     if (u->state == RVSB_WORMHOLE) continue;
    00577
    00578     TileIndex tile = u->tile;
    00579
    00580     if (!IsLevelCrossingTile(tile)) continue;
    00581
    00582     if (HasVehicleOnPosXY(v->x_pos, v->y_pos, u, EnumCheckRoadVehCrashTrain)) {
    00583       RoadVehCrash(v);
    00584       return true;
    00585     }
    00586   }
    00587
    00588   return false;
    00589 }
    00590
    00591 static void HandleBrokenRoadVeh(RoadVehicle *v)
    00592 {
    00593   if (v->breakdown_ctr != 1) {
    00594     v->breakdown_ctr = 1;
    00595     v->cur_speed = 0;
    00596
    00597     if (v->breakdowns_since_last_service != 255)
    00598       v->breakdowns_since_last_service++;
    00599
    00600     v->MarkDirty();
    00601     SetWindowDirty(WC_VEHICLE_VIEW, v->index);
    00602     SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
    00603
    00604     if (!PlayVehicleSound(v, VSE_BREAKDOWN)) {
    00605       SndPlayVehicleFx((_settings_game.game_creation.landscape != LT_TOYLAND) ?
    00606         SND_0F_VEHICLE_BREAKDOWN : SND_35_COMEDY_BREAKDOWN, v);
    00607     }
    00608
    00609     if (!(v->vehstatus & VS_HIDDEN)) {
    00610       EffectVehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE);
    00611       if (u != NULL) u->animation_state = v->breakdown_delay * 2;
    00612     }
    00613   }
    00614
    00615   if ((v->tick_counter & 1) == 0) {
    00616     if (--v->breakdown_delay == 0) {
    00617       v->breakdown_ctr = 0;
    00618       v->MarkDirty();
    00619       SetWindowDirty(WC_VEHICLE_VIEW, v->index);
    00620     }
    00621   }
    00622 }
    00623
    00624 TileIndex RoadVehicle::GetOrderStationLocation(StationID station)
    00625 {
    00626   if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
    00627
    00628   const Station *st = Station::Get(station);
    00629   if (!CanVehicleUseStation(this, st)) {
    00630     /* There is no stop left at the station, so don't even TRY to go there */
    00631     this->IncrementOrderIndex();
    00632     return 0;
    00633   }
    00634
    00635   return st->xy;
    00636 }
    00637
    00638 static void StartRoadVehSound(const RoadVehicle *v)
    00639 {
    00640   if (!PlayVehicleSound(v, VSE_START)) {
    00641     SoundID s = RoadVehInfo(v->engine_type)->sfx;
    00642     if (s == SND_19_BUS_START_PULL_AWAY && (v->tick_counter & 3) == 0)
    00643       s = SND_1A_BUS_START_PULL_AWAY_WITH_HORN;
    00644     SndPlayVehicleFx(s, v);
    00645   }
    00646 }
    00647
    00648 struct RoadVehFindData {
    00649   int x;
    00650   int y;
    00651   const Vehicle *veh;
    00652   Vehicle *best;
    00653   uint best_diff;
    00654   Direction dir;
    00655 };
    00656
    00657 static Vehicle *EnumCheckRoadVehClose(Vehicle *v, void *data)
    00658 {
    00659   static const int8 dist_x[] = { -4, -8, -4, -1, 4, 8, 4, 1 };
    00660   static const int8 dist_y[] = { -4, -1, 4, 8, 4, 1, -4, -8 };
    00661
    00662   RoadVehFindData *rvf = (RoadVehFindData*)data;
    00663
    00664   short x_diff = v->x_pos - rvf->x;
    00665   short y_diff = v->y_pos - rvf->y;
    00666
    00667   if (v->type == VEH_ROAD &&
    00668       !v->IsInDepot() &&
    00669       abs(v->z_pos - rvf->veh->z_pos) < 6 &&
    00670       v->direction == rvf->dir &&
    00671       rvf->veh->First() != v->First() &&
    00672       (dist_x[v->direction] >= 0 || (x_diff > dist_x[v->direction] && x_diff <= 0)) &&
    00673       (dist_x[v->direction] <= 0 || (x_diff < dist_x[v->direction] && x_diff >= 0)) &&
    00674       (dist_y[v->direction] >= 0 || (y_diff > dist_y[v->direction] && y_diff <= 0)) &&
    00675       (dist_y[v->direction] <= 0 || (y_diff < dist_y[v->direction] && y_diff >= 0))) {
    00676     uint diff = abs(x_diff) + abs(y_diff);
    00677
    00678     if (diff < rvf->best_diff || (diff == rvf->best_diff && v->index < rvf->best->index)) {
    00679       rvf->best = v;
    00680       rvf->best_diff = diff;
    00681     }
    00682   }
    00683
    00684   return NULL;
    00685 }
    00686
    00687 static RoadVehicle *RoadVehFindCloseTo(RoadVehicle *v, int x, int y, Direction dir, bool update_blocked_ctr = true)
    00688 {
    00689   RoadVehFindData rvf;
    00690   RoadVehicle *front = v->First();
    00691
    00692   if (front->reverse_ctr != 0) return NULL;
    00693
    00694   rvf.x = x;
    00695   rvf.y = y;
    00696   rvf.dir = dir;
    00697   rvf.veh = v;
    00698   rvf.best_diff = UINT_MAX;
    00699
    00700   if (front->state == RVSB_WORMHOLE) {
    00701     FindVehicleOnPos(v->tile, &rvf, EnumCheckRoadVehClose);
    00702     FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), &rvf, EnumCheckRoadVehClose);
    00703   } else {
    00704     FindVehicleOnPosXY(x, y, &rvf, EnumCheckRoadVehClose);
    00705   }
    00706
    00707   /* This code protects a roadvehicle from being blocked for ever
    00708    * If more than 1480 / 74 days a road vehicle is blocked, it will
    00709    * drive just through it. The ultimate backup-code of TTD.
    00710    * It can be disabled. */
    00711   if (rvf.best_diff == UINT_MAX) {
    00712     front->blocked_ctr = 0;
    00713     return NULL;
    00714   }
    00715
    00716   if (update_blocked_ctr && ++front->blocked_ctr > 1480) return NULL;
    00717
    00718   return RoadVehicle::From(rvf.best);
    00719 }
    00720
    00721 static void RoadVehArrivesAt(const RoadVehicle *v, Station *st)
    00722 {
    00723   if (v->IsBus()) {
    00724     /* Check if station was ever visited before */
    00725     if (!(st->had_vehicle_of_type & HVOT_BUS)) {
    00726       st->had_vehicle_of_type |= HVOT_BUS;
    00727       SetDParam(0, st->index);
    00728       AddVehicleNewsItem(
    00729         v->roadtype == ROADTYPE_ROAD ? STR_NEWS_FIRST_BUS_ARRIVAL : STR_NEWS_FIRST_PASSENGER_TRAM_ARRIVAL,
    00730         (v->owner == _local_company) ? NS_ARRIVAL_COMPANY : NS_ARRIVAL_OTHER,
    00731         v->index,
    00732         st->index
    00733       );
    00734       AI::NewEvent(v->owner, new AIEventStationFirstVehicle(st->index, v->index));
    00735     }
    00736   } else {
    00737     /* Check if station was ever visited before */
    00738     if (!(st->had_vehicle_of_type & HVOT_TRUCK)) {
    00739       st->had_vehicle_of_type |= HVOT_TRUCK;
    00740       SetDParam(0, st->index);
    00741       AddVehicleNewsItem(
    00742         v->roadtype == ROADTYPE_ROAD ? STR_NEWS_FIRST_TRUCK_ARRIVAL : STR_NEWS_FIRST_CARGO_TRAM_ARRIVAL,
    00743         (v->owner == _local_company) ? NS_ARRIVAL_COMPANY : NS_ARRIVAL_OTHER,
    00744         v->index,
    00745         st->index
    00746       );
    00747       AI::NewEvent(v->owner, new AIEventStationFirstVehicle(st->index, v->index));
    00748     }
    00749   }
    00750 }
    00751
    00752 static int RoadVehAccelerate(RoadVehicle *v)
    00753 {
    00754   uint oldspeed = v->cur_speed;
    00755   uint accel = 256 + (v->overtaking != 0 ? 256 : 0);
    00756   uint spd = v->subspeed + accel;
    00757
    00758   v->subspeed = (uint8)spd;
    00759
    00760   int tempmax = v->max_speed;
    00761   if (v->cur_speed > v->max_speed) {
    00762     tempmax = v->cur_speed - (v->cur_speed / 10) - 1;
    00763   }
    00764
    00765   v->cur_speed = spd = Clamp(v->cur_speed + ((int)spd >> 8), 0, tempmax);
    00766
    00767   /* Apply bridge speed limit */
    00768   if (v->state == RVSB_WORMHOLE && !(v->vehstatus & VS_HIDDEN)) {
    00769     v->cur_speed = min(v->cur_speed, GetBridgeSpec(GetBridgeType(v->tile))->speed * 2);
    00770   }
    00771
    00772   /* Update statusbar only if speed has changed to save CPU time */
    00773   if (oldspeed != v->cur_speed) {
    00774     if (_settings_client.gui.vehicle_speed) {
    00775       SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
    00776     }
    00777   }
    00778
    00779   /* Speed is scaled in the same manner as for trains. @see train_cmd.cpp */
    00780   int scaled_spd = spd * 3 >> 2;
    00781
    00782   scaled_spd += v->progress;
    00783   v->progress = 0;
    00784   return scaled_spd;
    00785 }
    00786
    00787 static Direction RoadVehGetNewDirection(const RoadVehicle *v, int x, int y)
    00788 {
    00789   static const Direction _roadveh_new_dir[] = {
    00790     DIR_N , DIR_NW, DIR_W , INVALID_DIR,
    00791     DIR_NE, DIR_N , DIR_SW, INVALID_DIR,
    00792     DIR_E , DIR_SE, DIR_S
    00793   };
    00794
    00795   x = x - v->x_pos + 1;
    00796   y = y - v->y_pos + 1;
    00797
    00798   if ((uint)x > 2 || (uint)y > 2) return v->direction;
    00799   return _roadveh_new_dir[y * 4 + x];
    00800 }
    00801
    00802 static Direction RoadVehGetSlidingDirection(const RoadVehicle *v, int x, int y)
    00803 {
    00804   Direction new_dir = RoadVehGetNewDirection(v, x, y);
    00805   Direction old_dir = v->direction;
    00806   DirDiff delta;
    00807
    00808   if (new_dir == old_dir) return old_dir;
    00809   delta = (DirDifference(new_dir, old_dir) > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT);
    00810   return ChangeDir(old_dir, delta);
    00811 }
    00812
    00813 struct OvertakeData {
    00814   const RoadVehicle *u;
    00815   const RoadVehicle *v;
    00816   TileIndex tile;
    00817   Trackdir trackdir;
    00818 };
    00819
    00820 static Vehicle *EnumFindVehBlockingOvertake(Vehicle *v, void *data)
    00821 {
    00822   const OvertakeData *od = (OvertakeData*)data;
    00823
    00824   return
    00825     v->type == VEH_ROAD && v->First() == v && v != od->u && v != od->v ?
    00826       v : NULL;
    00827 }
    00828
    00835 static bool CheckRoadBlockedForOvertaking(OvertakeData *od)
    00836 {
    00837   TrackStatus ts = GetTileTrackStatus(od->tile, TRANSPORT_ROAD, od->v->compatible_roadtypes);
    00838   TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts);
    00839   TrackdirBits red_signals = TrackStatusToRedSignals(ts); // barred level crossing
    00840   TrackBits trackbits = TrackdirBitsToTrackBits(trackdirbits);
    00841
    00842   /* Track does not continue along overtaking direction || track has junction || levelcrossing is barred */
    00843   if (!HasBit(trackdirbits, od->trackdir) || (trackbits & ~TRACK_BIT_CROSS) || (red_signals != TRACKDIR_BIT_NONE)) return true;
    00844
    00845   /* Are there more vehicles on the tile except the two vehicles involved in overtaking */
    00846   return HasVehicleOnPos(od->tile, od, EnumFindVehBlockingOvertake);
    00847 }
    00848
    00849 static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u)
    00850 {
    00851   OvertakeData od;
    00852
    00853   od.v = v;
    00854   od.u = u;
    00855
    00856   if (u->max_speed >= v->max_speed &&
    00857       !(u->vehstatus & VS_STOPPED) &&
    00858       u->cur_speed != 0) {
    00859     return;
    00860   }
    00861
    00862   /* Trams can't overtake other trams */
    00863   if (v->roadtype == ROADTYPE_TRAM) return;
    00864
    00865   /* Don't overtake in stations */
    00866   if (IsTileType(v->tile, MP_STATION) || IsTileType(u->tile, MP_STATION)) return;
    00867
    00868   /* For now, articulated road vehicles can't overtake anything. */
    00869   if (v->HasArticulatedPart()) return;
    00870
    00871   /* Vehicles are not driving in same direction || direction is not a diagonal direction */
    00872   if (v->direction != u->direction || !(v->direction & 1)) return;
    00873
    00874   /* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */
    00875   if (v->state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->state & RVSB_TRACKDIR_MASK))) return;
    00876
    00877   od.trackdir = DiagDirToDiagTrackdir(DirToDiagDir(v->direction));
    00878
    00879   /* Are the current and the next tile suitable for overtaking?
    00880    *  - Does the track continue along od.trackdir
    00881    *  - No junctions
    00882    *  - No barred levelcrossing
    00883    *  - No other vehicles in the way
    00884    */
    00885   od.tile = v->tile;
    00886   if (CheckRoadBlockedForOvertaking(&od)) return;
    00887
    00888   od.tile = v->tile + TileOffsByDiagDir(DirToDiagDir(v->direction));
    00889   if (CheckRoadBlockedForOvertaking(&od)) return;
    00890
    00891   if (od.u->cur_speed == 0 || (od.u->vehstatus & VS_STOPPED)) {
    00892     v->overtaking_ctr = 0x11;
    00893     v->overtaking = 0x10;
    00894   } else {
    00895 //    if (CheckRoadBlockedForOvertaking(&od)) return;
    00896     v->overtaking_ctr = 0;
    00897     v->overtaking = 0x10;
    00898   }
    00899 }
    00900
    00901 static void RoadZPosAffectSpeed(RoadVehicle *v, byte old_z)
    00902 {
    00903   if (old_z == v->z_pos) return;
    00904
    00905   if (old_z < v->z_pos) {
    00906     v->cur_speed = v->cur_speed * 232 / 256; // slow down by ~10%
    00907   } else {
    00908     uint16 spd = v->cur_speed + 2;
    00909     if (spd <= v->max_speed) v->cur_speed = spd;
    00910   }
    00911 }
    00912
    00913 static int PickRandomBit(uint bits)
    00914 {
    00915   uint i;
    00916   uint num = RandomRange(CountBits(bits));
    00917
    00918   for (i = 0; !(bits & 1) || (int)--num >= 0; bits >>= 1, i++) {}
    00919   return i;
    00920 }
    00921
    00930 static Trackdir RoadFindPathToDest(RoadVehicle *v, TileIndex tile, DiagDirection enterdir)
    00931 {
    00932 #define return_track(x) { best_track = (Trackdir)x; goto found_best_track; }
    00933
    00934   TileIndex desttile;
    00935   Trackdir best_track;
    00936
    00937   TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_ROAD, v->compatible_roadtypes);
    00938   TrackdirBits red_signals = TrackStatusToRedSignals(ts); // crossing
    00939   TrackdirBits trackdirs = TrackStatusToTrackdirBits(ts);
    00940
    00941   if (IsTileType(tile, MP_ROAD)) {
    00942     if (IsRoadDepot(tile) && (!IsInfraTileUsageAllowed(tile, v->owner, VEH_ROAD) || GetRoadDepotDirection(tile) == enterdir || (GetRoadTypes(tile) & v->compatible_roadtypes) == 0)) {
    00943       /* Road depot owned by another company or with the wrong orientation */
    00944       trackdirs = TRACKDIR_BIT_NONE;
    00945     }
    00946   } else if (IsTileType(tile, MP_STATION) && IsStandardRoadStopTile(tile)) {
    00947     /* Standard road stop (drive-through stops are treated as normal road) */
    00948
    00949     if (!IsInfraTileUsageAllowed(tile, v->owner, VEH_ROAD) || GetRoadStopDir(tile) == enterdir || v->HasArticulatedPart()) {
    00950       /* different station owner or wrong orientation or the vehicle has articulated parts */
    00951       trackdirs = TRACKDIR_BIT_NONE;
    00952     } else {
    00953       /* Our station */
    00954       RoadStopType rstype = v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK;
    00955
    00956       if (GetRoadStopType(tile) != rstype) {
    00957         /* Wrong station type */
    00958         trackdirs = TRACKDIR_BIT_NONE;
    00959       } else {
    00960         /* Proper station type, check if there is free loading bay */
    00961         if (!_settings_game.pf.roadveh_queue && IsStandardRoadStopTile(tile) &&
    00962             !RoadStop::GetByTile(tile, rstype)->HasFreeBay()) {
    00963           /* Station is full and RV queuing is off */
    00964           trackdirs = TRACKDIR_BIT_NONE;
    00965         }
    00966       }
    00967     }
    00968   }
    00969   /* The above lookups should be moved to GetTileTrackStatus in the
    00970    * future, but that requires more changes to the pathfinder and other
    00971    * stuff, probably even more arguments to GTTS.
    00972    */
    00973
    00974   /* Remove tracks unreachable from the enter dir */
    00975   trackdirs &= _road_enter_dir_to_reachable_trackdirs[enterdir];
    00976   if (trackdirs == TRACKDIR_BIT_NONE) {
    00977     /* No reachable tracks, so we'll reverse */
    00978     return_track(_road_reverse_table[enterdir]);
    00979   }
    00980
    00981   if (v->reverse_ctr != 0) {
    00982     bool reverse = true;
    00983     if (v->roadtype == ROADTYPE_TRAM) {
    00984       /* Trams may only reverse on a tile if it contains at least the straight
    00985        * trackbits or when it is a valid turning tile (i.e. one roadbit) */
    00986       RoadBits rb = GetAnyRoadBits(tile, ROADTYPE_TRAM);
    00987       RoadBits straight = AxisToRoadBits(DiagDirToAxis(enterdir));
    00988       reverse = ((rb & straight) == straight) ||
    00989                 (rb == DiagDirToRoadBits(enterdir));
    00990     }
    00991     if (reverse) {
    00992       v->reverse_ctr = 0;
    00993       if (v->tile != tile) {
    00994         return_track(_road_reverse_table[enterdir]);
    00995       }
    00996     }
    00997   }
    00998
    00999   desttile = v->dest_tile;
    01000   if (desttile == 0) {
    01001     /* We've got no destination, pick a random track */
    01002     return_track(PickRandomBit(trackdirs));
    01003   }
    01004
    01005   /* Only one track to choose between? */
    01006   if (KillFirstBit(trackdirs) == TRACKDIR_BIT_NONE) {
    01007     return_track(FindFirstBit2x64(trackdirs));
    01008   }
    01009
    01010   switch (_settings_game.pf.pathfinder_for_roadvehs) {
    01011     case VPF_NPF: return_track(NPFRoadVehicleChooseTrack(v, tile, enterdir, trackdirs));
    01012     case VPF_YAPF: return_track(YapfRoadVehicleChooseTrack(v, tile, enterdir, trackdirs));
    01013
    01014     default: NOT_REACHED();
    01015   }
    01016
    01017 found_best_track:;
    01018
    01019   if (HasBit(red_signals, best_track)) return INVALID_TRACKDIR;
    01020
    01021   return best_track;
    01022 }
    01023
    01024 struct RoadDriveEntry {
    01025   byte x, y;
    01026 };
    01027
    01028 #include "table/roadveh_movement.h"
    01029
    01030 static const byte _road_veh_data_1[] = {
    01031   20, 20, 16, 16, 0, 0, 0, 0,
    01032   19, 19, 15, 15, 0, 0, 0, 0,
    01033   16, 16, 12, 12, 0, 0, 0, 0,
    01034   15, 15, 11, 11
    01035 };
    01036
    01037 static bool RoadVehLeaveDepot(RoadVehicle *v, bool first)
    01038 {
    01039   /* Don't leave if not all the wagons are in the depot. */
    01040   for (const RoadVehicle *u = v; u != NULL; u = u->Next()) {
    01041     if (u->state != RVSB_IN_DEPOT || u->tile != v->tile) return false;
    01042   }
    01043
    01044   DiagDirection dir = GetRoadDepotDirection(v->tile);
    01045   v->direction = DiagDirToDir(dir);
    01046
    01047   Trackdir tdir = _roadveh_depot_exit_trackdir[dir];
    01048   const RoadDriveEntry *rdp = _road_drive_data[v->roadtype][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + tdir];
    01049
    01050   int x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF);
    01051   int y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF);
    01052
    01053   if (first) {
    01054     if (RoadVehFindCloseTo(v, x, y, v->direction, false) != NULL) return true;
    01055
    01056     VehicleServiceInDepot(v);
    01057
    01058     StartRoadVehSound(v);
    01059
    01060     /* Vehicle is about to leave a depot */
    01061     v->cur_speed = 0;
    01062   }
    01063
    01064   v->vehstatus &= ~VS_HIDDEN;
    01065   v->state = tdir;
    01066   v->frame = RVC_DEPOT_START_FRAME;
    01067
    01068   SetRoadVehPosition(v, x, y, true);
    01069
    01070   InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
    01071
    01072   return true;
    01073 }
    01074
    01075 static Trackdir FollowPreviousRoadVehicle(const RoadVehicle *v, const RoadVehicle *prev, TileIndex tile, DiagDirection entry_dir, bool already_reversed)
    01076 {
    01077   if (prev->tile == v->tile && !already_reversed) {
    01078     /* If the previous vehicle is on the same tile as this vehicle is
    01079      * then it must have reversed. */
    01080     return _road_reverse_table[entry_dir];
    01081   }
    01082
    01083   byte prev_state = prev->state;
    01084   Trackdir dir;
    01085
    01086   if (prev_state == RVSB_WORMHOLE || prev_state == RVSB_IN_DEPOT) {
    01087     DiagDirection diag_dir = INVALID_DIAGDIR;
    01088
    01089     if (IsTileType(tile, MP_TUNNELBRIDGE)) {
    01090       diag_dir = GetTunnelBridgeDirection(tile);
    01091     } else if (IsRoadDepotTile(tile)) {
    01092       diag_dir = ReverseDiagDir(GetRoadDepotDirection(tile));
    01093     }
    01094
    01095     if (diag_dir == INVALID_DIAGDIR) return INVALID_TRACKDIR;
    01096     dir = DiagDirToDiagTrackdir(diag_dir);
    01097   } else {
    01098     if (already_reversed && prev->tile != tile) {
    01099       /*
    01100        * The vehicle has reversed, but did not go straight back.
    01101        * It immediatelly turn onto another tile. This means that
    01102        * the roadstate of the previous vehicle cannot be used
    01103        * as the direction we have to go with this vehicle.
    01104        *
    01105        * Next table is build in the following way:
    01106        *  - first row for when the vehicle in front went to the northern or
    01107        *    western tile, second for southern and eastern.
    01108        *  - columns represent the entry direction.
    01109        *  - cell values are determined by the Trackdir one has to take from
    01110        *    the entry dir (column) to the tile in north or south by only
    01111        *    going over the trackdirs used for turning 90 degrees, i.e.
    01112        *    TRACKDIR_{UPPER,RIGHT,LOWER,LEFT}_{N,E,S,W}.
    01113        */
    01114       static const Trackdir reversed_turn_lookup[2][DIAGDIR_END] = {
    01115         { TRACKDIR_UPPER_W, TRACKDIR_RIGHT_N, TRACKDIR_LEFT_N,  TRACKDIR_UPPER_E },
    01116         { TRACKDIR_RIGHT_S, TRACKDIR_LOWER_W, TRACKDIR_LOWER_E, TRACKDIR_LEFT_S  }};
    01117       dir = reversed_turn_lookup[prev->tile < tile ? 0 : 1][ReverseDiagDir(entry_dir)];
    01118     } else if (HasBit(prev_state, RVS_IN_DT_ROAD_STOP)) {
    01119       dir = (Trackdir)(prev_state & RVSB_ROAD_STOP_TRACKDIR_MASK);
    01120     } else if (prev_state < TRACKDIR_END) {
    01121       dir = (Trackdir)prev_state;
    01122     } else {
    01123       return INVALID_TRACKDIR;
    01124     }
    01125   }
    01126
    01127   /* Do some sanity checking. */
    01128   static const RoadBits required_roadbits[] = {
    01129     ROAD_X,            ROAD_Y,            ROAD_NW | ROAD_NE, ROAD_SW | ROAD_SE,
    01130     ROAD_NW | ROAD_SW, ROAD_NE | ROAD_SE, ROAD_X,            ROAD_Y
    01131   };
    01132   RoadBits required = required_roadbits[dir & 0x07];
    01133
    01134   if ((required & GetAnyRoadBits(tile, v->roadtype, true)) == ROAD_NONE) {
    01135     dir = INVALID_TRACKDIR;
    01136   }
    01137
    01138   return dir;
    01139 }
    01140
    01148 static bool CanBuildTramTrackOnTile(CompanyID c, TileIndex t, RoadBits r)
    01149 {
    01150   /* The 'current' company is not necessarily the owner of the vehicle. */
    01151   CompanyID original_company = _current_company;
    01152   _current_company = c;
    01153
    01154   CommandCost ret = DoCommand(t, ROADTYPE_TRAM << 4 | r, 0, DC_NONE, CMD_BUILD_ROAD);
    01155
    01156   _current_company = original_company;
    01157   return CmdSucceeded(ret);
    01158 }
    01159
    01160 static bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev)
    01161 {
    01162   if (v->overtaking != 0)  {
    01163     if (IsTileType(v->tile, MP_STATION)) {
    01164       /* Force us to be not overtaking! */
    01165       v->overtaking = 0;
    01166     } else if (++v->overtaking_ctr >= 35) {
    01167       /* If overtaking just aborts at a random moment, we can have a out-of-bound problem,
    01168        *  if the vehicle started a corner. To protect that, only allow an abort of
    01169        *  overtake if we are on straight roads */
    01170       if (v->state < RVSB_IN_ROAD_STOP && IsStraightRoadTrackdir((Trackdir)v->state)) {
    01171         v->overtaking = 0;
    01172       }
    01173     }
    01174   }
    01175
    01176   /* If this vehicle is in a depot and we've reached this point it must be
    01177    * one of the articulated parts. It will stay in the depot until activated
    01178    * by the previous vehicle in the chain when it gets to the right place. */
    01179   if (v->IsInDepot()) return true;
    01180
    01181   if (v->state == RVSB_WORMHOLE) {
    01182     /* Vehicle is entering a depot or is on a bridge or in a tunnel */
    01183     GetNewVehiclePosResult gp = GetNewVehiclePos(v);
    01184
    01185     if (v->IsRoadVehFront()) {
    01186       const Vehicle *u = RoadVehFindCloseTo(v, gp.x, gp.y, v->direction);
    01187       if (u != NULL) {
    01188         v->cur_speed = u->First()->cur_speed;
    01189         return false;
    01190       }
    01191     }
    01192
    01193     if (IsTileType(gp.new_tile, MP_TUNNELBRIDGE) && HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
    01194       /* Vehicle has just entered a bridge or tunnel */
    01195       SetRoadVehPosition(v, gp.x, gp.y, true);
    01196       return true;
    01197     }
    01198
    01199     v->x_pos = gp.x;
    01200     v->y_pos = gp.y;
    01201     VehicleMove(v, !(v->vehstatus & VS_HIDDEN));
    01202     return true;
    01203   }
    01204
    01205   /* Get move position data for next frame.
    01206    * For a drive-through road stop use 'straight road' move data.
    01207    * In this case v->state is masked to give the road stop entry direction. */
    01208   RoadDriveEntry rd = _road_drive_data[v->roadtype][(
    01209     (HasBit(v->state, RVS_IN_DT_ROAD_STOP) ? v->state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->state) +
    01210     (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->overtaking][v->frame + 1];
    01211
    01212   if (rd.x & RDE_NEXT_TILE) {
    01213     TileIndex tile = v->tile + TileOffsByDiagDir((DiagDirection)(rd.x & 3));
    01214     Trackdir dir;
    01215
    01216     if (v->IsRoadVehFront()) {
    01217       /* If this is the front engine, look for the right path. */
    01218       dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3));
    01219     } else {
    01220       dir = FollowPreviousRoadVehicle(v, prev, tile, (DiagDirection)(rd.x & 3), false);
    01221     }
    01222
    01223     if (dir == INVALID_TRACKDIR) {
    01224       if (!v->IsRoadVehFront()) error("Disconnecting road vehicle.");
    01225       v->cur_speed = 0;
    01226       return false;
    01227     }
    01228
    01229 again:
    01230     uint start_frame = RVC_DEFAULT_START_FRAME;
    01231     if (IsReversingRoadTrackdir(dir)) {
    01232       /* Turning around */
    01233       if (v->roadtype == ROADTYPE_TRAM) {
    01234         /* Determine the road bits the tram needs to be able to turn around
    01235          * using the 'big' corner loop. */
    01236         RoadBits needed;
    01237         switch (dir) {
    01238           default: NOT_REACHED();
    01239           case TRACKDIR_RVREV_NE: needed = ROAD_SW; break;
    01240           case TRACKDIR_RVREV_SE: needed = ROAD_NW; break;
    01241           case TRACKDIR_RVREV_SW: needed = ROAD_NE; break;
    01242           case TRACKDIR_RVREV_NW: needed = ROAD_SE; break;
    01243         }
    01244         if ((v->Previous() != NULL && v->Previous()->tile == tile) ||
    01245             (v->IsRoadVehFront() && IsNormalRoadTile(tile) && !HasRoadWorks(tile) &&
    01246               (needed & GetRoadBits(tile, ROADTYPE_TRAM)) != ROAD_NONE)) {
    01247           /*
    01248            * Taking the 'big' corner for trams only happens when:
    01249            * - The previous vehicle in this (articulated) tram chain is
    01250            *   already on the 'next' tile, we just follow them regardless of
    01251            *   anything. When it is NOT on the 'next' tile, the tram started
    01252            *   doing a reversing turn when the piece of tram track on the next
    01253            *   tile did not exist yet. Do not use the big tram loop as that is
    01254            *   going to cause the tram to split up.
    01255            * - Or the front of the tram can drive over the next tile.
    01256            */
    01257         } else if (!v->IsRoadVehFront() || !CanBuildTramTrackOnTile(v->owner, tile, needed) || ((~needed & GetAnyRoadBits(v->tile, ROADTYPE_TRAM, false)) == ROAD_NONE)) {
    01258           /*
    01259            * Taking the 'small' corner for trams only happens when:
    01260            * - We are not the from vehicle of an articulated tram.
    01261            * - Or when the company cannot build on the next tile.
    01262            *
    01263            * The 'small' corner means that the vehicle is on the end of a
    01264            * tram track and needs to start turning there. To do this properly
    01265            * the tram needs to start at an offset in the tram turning 'code'
    01266            * for 'big' corners. It furthermore does not go to the next tile,
    01267            * so that needs to be fixed too.
    01268            */
    01269           tile = v->tile;
    01270           start_frame = RVC_TURN_AROUND_START_FRAME_SHORT_TRAM;
    01271         } else {
    01272           /* The company can build on the next tile, so wait till (s)he does. */
    01273           v->cur_speed = 0;
    01274           return false;
    01275         }
    01276       } else if (IsNormalRoadTile(v->tile) && GetDisallowedRoadDirections(v->tile) != DRD_NONE) {
    01277         v->cur_speed = 0;
    01278         return false;
    01279       } else {
    01280         tile = v->tile;
    01281       }
    01282     }
    01283
    01284     /* Get position data for first frame on the new tile */
    01285     const RoadDriveEntry *rdp = _road_drive_data[v->roadtype][(dir + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->overtaking];
    01286
    01287     int x = TileX(tile) * TILE_SIZE + rdp[start_frame].x;
    01288     int y = TileY(tile) * TILE_SIZE + rdp[start_frame].y;
    01289
    01290     Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
    01291     if (v->IsRoadVehFront()) {
    01292       Vehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
    01293       if (u != NULL) {
    01294         v->cur_speed = u->First()->cur_speed;
    01295         return false;
    01296       }
    01297     }
    01298
    01299     uint32 r = VehicleEnterTile(v, tile, x, y);
    01300     if (HasBit(r, VETS_CANNOT_ENTER)) {
    01301       if (!IsTileType(tile, MP_TUNNELBRIDGE)) {
    01302         v->cur_speed = 0;
    01303         return false;
    01304       }
    01305       /* Try an about turn to re-enter the previous tile */
    01306       dir = _road_reverse_table[rd.x & 3];
    01307       goto again;
    01308     }
    01309
    01310     if (IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) && IsTileType(v->tile, MP_STATION)) {
    01311       if (IsReversingRoadTrackdir(dir) && IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
    01312         /* New direction is trying to turn vehicle around.
    01313          * We can't turn at the exit of a road stop so wait.*/
    01314         v->cur_speed = 0;
    01315         return false;
    01316       }
    01317
    01318       /* If we are a drive through road stop and the next tile is of
    01319        * the same road stop and the next tile isn't this one (i.e. we
    01320        * are not reversing), then keep the reservation and state.
    01321        * This way we will not be shortly unregister from the road
    01322        * stop. It also makes it possible to load when on the edge of
    01323        * two road stops; otherwise you could get vehicles that should
    01324        * be loading but are not actually loading. */
    01325       if (IsDriveThroughStopTile(v->tile) &&
    01326           RoadStop::IsDriveThroughRoadStopContinuation(v->tile, tile) &&
    01327           v->tile != tile) {
    01328         /* So, keep 'our' state */
    01329         dir = (Trackdir)v->state;
    01330       } else if (IsRoadStop(v->tile)) {
    01331         /* We're not continuing our drive through road stop, so leave. */
    01332         RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v);
    01333       }
    01334     }
    01335
    01336     if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
    01337       v->tile = tile;
    01338       v->state = (byte)dir;
    01339       v->frame = start_frame;
    01340     }
    01341     if (new_dir != v->direction) {
    01342       v->direction = new_dir;
    01343       v->cur_speed -= v->cur_speed >> 2;
    01344     }
    01345
    01346     RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, true));
    01347     return true;
    01348   }
    01349
    01350   if (rd.x & RDE_TURNED) {
    01351     /* Vehicle has finished turning around, it will now head back onto the same tile */
    01352     Trackdir dir;
    01353     uint turn_around_start_frame = RVC_TURN_AROUND_START_FRAME;
    01354
    01355     RoadBits tram;
    01356     if (v->roadtype == ROADTYPE_TRAM && !IsRoadDepotTile(v->tile) && CountBits(tram = GetAnyRoadBits(v->tile, ROADTYPE_TRAM, true)) == 1) {
    01357       /*
    01358        * The tram is turning around with one tram 'roadbit'. This means that
    01359        * it is using the 'big' corner 'drive data'. However, to support the
    01360        * trams to take a small corner, there is a 'turned' marker in the middle
    01361        * of the turning 'drive data'. When the tram took the long corner, we
    01362        * will still use the 'big' corner drive data, but we advance it one
    01363        * frame. We furthermore set the driving direction so the turning is
    01364        * going to be properly shown.
    01365        */
    01366       turn_around_start_frame = RVC_START_FRAME_AFTER_LONG_TRAM;
    01367       switch (rd.x & 0x3) {
    01368         default: NOT_REACHED();
    01369         case DIAGDIR_NW: dir = TRACKDIR_RVREV_SE; break;
    01370         case DIAGDIR_NE: dir = TRACKDIR_RVREV_SW; break;
    01371         case DIAGDIR_SE: dir = TRACKDIR_RVREV_NW; break;
    01372         case DIAGDIR_SW: dir = TRACKDIR_RVREV_NE; break;
    01373       }
    01374     } else {
    01375       if (v->IsRoadVehFront()) {
    01376         /* If this is the front engine, look for the right path. */
    01377         dir = RoadFindPathToDest(v, v->tile, (DiagDirection)(rd.x & 3));
    01378       } else {
    01379         dir = FollowPreviousRoadVehicle(v, prev, v->tile, (DiagDirection)(rd.x & 3), true);
    01380       }
    01381     }
    01382
    01383     if (dir == INVALID_TRACKDIR) {
    01384       v->cur_speed = 0;
    01385       return false;
    01386     }
    01387
    01388     const RoadDriveEntry *rdp = _road_drive_data[v->roadtype][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + dir];
    01389
    01390     int x = TileX(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].x;
    01391     int y = TileY(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].y;
    01392
    01393     Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
    01394     if (v->IsRoadVehFront() && RoadVehFindCloseTo(v, x, y, new_dir) != NULL) return false;
    01395
    01396     uint32 r = VehicleEnterTile(v, v->tile, x, y);
    01397     if (HasBit(r, VETS_CANNOT_ENTER)) {
    01398       v->cur_speed = 0;
    01399       return false;
    01400     }
    01401
    01402     v->state = dir;
    01403     v->frame = turn_around_start_frame;
    01404
    01405     if (new_dir != v->direction) {
    01406       v->direction = new_dir;
    01407       v->cur_speed -= v->cur_speed >> 2;
    01408     }
    01409
    01410     RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, true));
    01411     return true;
    01412   }
    01413
    01414   /* This vehicle is not in a wormhole and it hasn't entered a new tile. If
    01415    * it's on a depot tile, check if it's time to activate the next vehicle in
    01416    * the chain yet. */
    01417   if (v->Next() != NULL && IsRoadDepotTile(v->tile)) {
    01418     if (v->frame == v->rcache.cached_veh_length + RVC_DEPOT_START_FRAME) {
    01419       RoadVehLeaveDepot(v->Next(), false);
    01420     }
    01421   }
    01422
    01423   /* Calculate new position for the vehicle */
    01424   int x = (v->x_pos & ~15) + (rd.x & 15);
    01425   int y = (v->y_pos & ~15) + (rd.y & 15);
    01426
    01427   Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
    01428
    01429   if (v->IsRoadVehFront() && !IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
    01430     /* Vehicle is not in a road stop.
    01431      * Check for another vehicle to overtake */
    01432     RoadVehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
    01433
    01434     if (u != NULL) {
    01435       u = u->First();
    01436       /* There is a vehicle in front overtake it if possible */
    01437       if (v->overtaking == 0) RoadVehCheckOvertake(v, u);
    01438       if (v->overtaking == 0) v->cur_speed = u->cur_speed;
    01439
    01440       /* In case an RV is stopped in a road stop, why not try to load? */
    01441       if (v->cur_speed == 0 && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
    01442           v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
    01443           IsInfraTileUsageAllowed(v->tile, v->owner, VEH_ROAD) && !v->current_order.IsType(OT_LEAVESTATION) &&
    01444           GetRoadStopType(v->tile) == (v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK)) {
    01445         Station *st = Station::GetByTile(v->tile);
    01446         v->last_station_visited = st->index;
    01447         RoadVehArrivesAt(v, st);
    01448         v->BeginLoading();
    01449       }
    01450       return false;
    01451     }
    01452   }
    01453
    01454   Direction old_dir = v->direction;
    01455   if (new_dir != old_dir) {
    01456     v->direction = new_dir;
    01457     v->cur_speed -= (v->cur_speed >> 2);
    01458     if (old_dir != v->state) {
    01459       /* The vehicle is in a road stop */
    01460       SetRoadVehPosition(v, v->x_pos, v->y_pos, true);
    01461       /* Note, return here means that the frame counter is not incremented
    01462        * for vehicles changing direction in a road stop. This causes frames to
    01463        * be repeated. (XXX) Is this intended? */
    01464       return true;
    01465     }
    01466   }
    01467
    01468   /* If the vehicle is in a normal road stop and the frame equals the stop frame OR
    01469    * if the vehicle is in a drive-through road stop and this is the destination station
    01470    * and it's the correct type of stop (bus or truck) and the frame equals the stop frame...
    01471    * (the station test and stop type test ensure that other vehicles, using the road stop as
    01472    * a through route, do not stop) */
    01473   if (v->IsRoadVehFront() && ((IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) &&
    01474       _road_veh_data_1[v->state - RVSB_IN_ROAD_STOP + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)] == v->frame) ||
    01475       (IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
    01476       v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
    01477       IsInfraTileUsageAllowed(v->tile, v->owner, VEH_ROAD) &&
    01478       GetRoadStopType(v->tile) == (v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK) &&
    01479       v->frame == RVC_DRIVE_THROUGH_STOP_FRAME))) {
    01480
    01481     RoadStop *rs = RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile));
    01482     Station *st = Station::GetByTile(v->tile);
    01483
    01484     /* Vehicle is at the stop position (at a bay) in a road stop.
    01485      * Note, if vehicle is loading/unloading it has already been handled,
    01486      * so if we get here the vehicle has just arrived or is just ready to leave. */
    01487     if (!v->current_order.IsType(OT_LEAVESTATION)) {
    01488       /* Vehicle has arrived at a bay in a road stop */
    01489
    01490       if (IsDriveThroughStopTile(v->tile)) {
    01491         TileIndex next_tile = TILE_ADD(v->tile, TileOffsByDir(v->direction));
    01492
    01493         /* Check if next inline bay is free and has compatible road. */
    01494         if (RoadStop::IsDriveThroughRoadStopContinuation(v->tile, next_tile) && (GetRoadTypes(next_tile) & v->compatible_roadtypes) != 0) {
    01495           v->frame++;
    01496           RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, false));
    01497           return true;
    01498         }
    01499       }
    01500
    01501       rs->SetEntranceBusy(false);
    01502
    01503       v->last_station_visited = st->index;
    01504
    01505       if (IsDriveThroughStopTile(v->tile) || (v->current_order.IsType(OT_GOTO_STATION) && v->current_order.GetDestination() == st->index)) {
    01506         RoadVehArrivesAt(v, st);
    01507         v->BeginLoading();
    01508         return false;
    01509       }
    01510     } else {
    01511       /* Vehicle is ready to leave a bay in a road stop */
    01512       if (rs->IsEntranceBusy()) {
    01513         /* Road stop entrance is busy, so wait as there is nowhere else to go */
    01514         v->cur_speed = 0;
    01515         return false;
    01516       }
    01517       v->current_order.Free();
    01518     }
    01519
    01520     if (IsStandardRoadStopTile(v->tile)) rs->SetEntranceBusy(true);
    01521
    01522     StartRoadVehSound(v);
    01523     SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
    01524   }
    01525
    01526   /* Check tile position conditions - i.e. stop position in depot,
    01527    * entry onto bridge or into tunnel */
    01528   uint32 r = VehicleEnterTile(v, v->tile, x, y);
    01529   if (HasBit(r, VETS_CANNOT_ENTER)) {
    01530     v->cur_speed = 0;
    01531     return false;
    01532   }
    01533
    01534   if (v->current_order.IsType(OT_LEAVESTATION) && IsDriveThroughStopTile(v->tile)) {
    01535     v->current_order.Free();
    01536   }
    01537
    01538   /* Move to next frame unless vehicle arrived at a stop position
    01539    * in a depot or entered a tunnel/bridge */
    01540   if (!HasBit(r, VETS_ENTERED_WORMHOLE)) v->frame++;
    01541
    01542   RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, true));
    01543   return true;
    01544 }
    01545
    01546 static bool RoadVehController(RoadVehicle *v)
    01547 {
    01548   /* decrease counters */
    01549   v->tick_counter++;
    01550   v->current_order_time++;
    01551   if (v->reverse_ctr != 0) v->reverse_ctr--;
    01552
    01553   /* handle crashed */
    01554   if (v->vehstatus & VS_CRASHED) {
    01555     return RoadVehIsCrashed(v);
    01556   }
    01557
    01558   RoadVehCheckTrainCrash(v);
    01559
    01560   /* road vehicle has broken down? */
    01561   if (v->breakdown_ctr != 0) {
    01562     if (v->breakdown_ctr <= 2) {
    01563       HandleBrokenRoadVeh(v);
    01564       return true;
    01565     }
    01566     if (!v->current_order.IsType(OT_LOADING)) v->breakdown_ctr--;
    01567   }
    01568
    01569   if (v->vehstatus & VS_STOPPED) return true;
    01570
    01571   ProcessOrders(v);
    01572   v->HandleLoading();
    01573
    01574   if (v->current_order.IsType(OT_LOADING)) return true;
    01575
    01576   if (v->IsInDepot() && RoadVehLeaveDepot(v, true)) return true;
    01577
    01578   /* Check how far the vehicle needs to proceed */
    01579   int j = RoadVehAccelerate(v);
    01580
    01581   int adv_spd = (v->direction & 1) ? 192 : 256;
    01582   while (j >= adv_spd) {
    01583     j -= adv_spd;
    01584
    01585     RoadVehicle *u = v;
    01586     for (RoadVehicle *prev = NULL; u != NULL; prev = u, u = u->Next()) {
    01587       if (!IndividualRoadVehicleController(u, prev)) break;
    01588     }
    01589
    01590     /* 192 spd used for going straight, 256 for going diagonally. */
    01591     adv_spd = (v->direction & 1) ? 192 : 256;
    01592
    01593     /* Test for a collision, but only if another movement will occur. */
    01594     if (j >= adv_spd && RoadVehCheckTrainCrash(v)) break;
    01595   }
    01596
    01597   for (RoadVehicle *u = v; u != NULL; u = u->Next()) {
    01598     if ((u->vehstatus & VS_HIDDEN) != 0) continue;
    01599
    01600     u->UpdateViewport(false, false);
    01601   }
    01602
    01603   if (v->progress == 0) v->progress = j;
    01604
    01605   return true;
    01606 }
    01607
    01608 Money RoadVehicle::GetRunningCost() const
    01609 {
    01610   const Engine *e = Engine::Get(this->engine_type);
    01611   if (e->u.road.running_cost_class == INVALID_PRICE) return 0;
    01612
    01613   uint cost_factor = GetVehicleProperty(this, PROP_ROADVEH_RUNNING_COST_FACTOR, e->u.road.running_cost);
    01614   if (cost_factor == 0) return 0;
    01615
    01616   return GetPrice(e->u.road.running_cost_class, cost_factor, e->grffile);
    01617 }
    01618
    01619 bool RoadVehicle::Tick()
    01620 {
    01621   if (this->IsRoadVehFront()) {
    01622     if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
    01623     return RoadVehController(this);
    01624   }
    01625
    01626   return true;
    01627 }
    01628
    01629 static void CheckIfRoadVehNeedsService(RoadVehicle *v)
    01630 {
    01631   /* If we already got a slot at a stop, use that FIRST, and go to a depot later */
    01632   if (Company::Get(v->owner)->settings.vehicle.servint_roadveh == 0 || !v->NeedsAutomaticServicing()) return;
    01633   if (v->IsInDepot()) {
    01634     VehicleServiceInDepot(v);
    01635     return;
    01636   }
    01637
    01638   uint max_penalty;
    01639   switch (_settings_game.pf.pathfinder_for_roadvehs) {
    01640     case VPF_NPF:  max_penalty = _settings_game.pf.npf.maximum_go_to_depot_penalty;  break;
    01641     case VPF_YAPF: max_penalty = _settings_game.pf.yapf.maximum_go_to_depot_penalty; break;
    01642     default: NOT_REACHED();
    01643   }
    01644
    01645   FindDepotData rfdd = FindClosestRoadDepot(v, max_penalty);
    01646   /* Only go to the depot if it is not too far out of our way. */
    01647   if (rfdd.best_length == UINT_MAX || rfdd.best_length > max_penalty) {
    01648     if (v->current_order.IsType(OT_GOTO_DEPOT)) {
    01649       /* If we were already heading for a depot but it has
    01650        * suddenly moved farther away, we continue our normal
    01651        * schedule? */
    01652       v->current_order.MakeDummy();
    01653       SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
    01654     }
    01655     return;
    01656   }
    01657
    01658   DepotID depot = GetDepotIndex(rfdd.tile);
    01659
    01660   if (v->current_order.IsType(OT_GOTO_DEPOT) &&
    01661       v->current_order.GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS &&
    01662       !Chance16(1, 20)) {
    01663     return;
    01664   }
    01665
    01666   if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
    01667
    01668   v->current_order.MakeGoToDepot(depot, ODTFB_SERVICE);
    01669   v->dest_tile = rfdd.tile;
    01670   SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
    01671 }
    01672
    01673 void RoadVehicle::OnNewDay()
    01674 {
    01675   if (!this->IsRoadVehFront()) return;
    01676
    01677   if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
    01678   if (this->blocked_ctr == 0) CheckVehicleBreakdown(this);
    01679
    01680   AgeVehicle(this);
    01681   CheckIfRoadVehNeedsService(this);
    01682
    01683   CheckOrders(this);
    01684
    01685   if (this->running_ticks == 0) return;
    01686
    01687   CommandCost cost(EXPENSES_ROADVEH_RUN, this->GetRunningCost() * this->running_ticks / (DAYS_IN_YEAR * DAY_TICKS));
    01688
    01689   this->profit_this_year -= cost.GetCost();
    01690   this->running_ticks = 0;
    01691
    01692   SubtractMoneyFromCompanyFract(this->owner, cost);
    01693
    01694   SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
    01695   SetWindowClassesDirty(WC_ROADVEH_LIST);
    01696 }
    01697
    01698 Trackdir RoadVehicle::GetVehicleTrackdir() const
    01699 {
    01700   if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
    01701
    01702   if (this->IsInDepot()) {
    01703     /* We'll assume the road vehicle is facing outwards */
    01704     return DiagDirToDiagTrackdir(GetRoadDepotDirection(this->tile));
    01705   }
    01706
    01707   if (IsStandardRoadStopTile(this->tile)) {
    01708     /* We'll assume the road vehicle is facing outwards */
    01709     return DiagDirToDiagTrackdir(GetRoadStopDir(this->tile)); // Road vehicle in a station
    01710   }
    01711
    01712   /* Drive through road stops / wormholes (tunnels) */
    01713   if (this->state > RVSB_TRACKDIR_MASK) return DiagDirToDiagTrackdir(DirToDiagDir(this->direction));
    01714
    01715   /* If vehicle's state is a valid track direction (vehicle is not turning around) return it,
    01716    * otherwise transform it into a valid track direction */
    01717   return (Trackdir)((IsReversingRoadTrackdir((Trackdir)this->state)) ? (this->state - 6) : this->state);
    01718 }
    01719
    01720
    01732 CommandCost CmdRefitRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    01733 {
    01734   CargoID new_cid = GB(p2, 0, 8);
    01735   byte new_subtype = GB(p2, 8, 8);
    01736   bool only_this = HasBit(p2, 16);
    01737
    01738   RoadVehicle *v = RoadVehicle::GetIfValid(p1);
    01739
    01740   if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR;
    01741   if (!v->IsStoppedInDepot()) return_cmd_error(STR_ERROR_ROAD_VEHICLE_MUST_BE_STOPPED_INSIDE_DEPOT);
    01742   if (v->vehstatus & VS_CRASHED) return_cmd_error(STR_ERROR_CAN_T_REFIT_DESTROYED_VEHICLE);
    01743
    01744   if (new_cid >= NUM_CARGO) return CMD_ERROR;
    01745
    01746   CommandCost cost = RefitVehicle(v, only_this, new_cid, new_subtype, flags);
    01747
    01748   if (flags & DC_EXEC) {
    01749     RoadVehicle *front = v->First();
    01750     RoadVehUpdateCache(front);
    01751     SetWindowDirty(WC_VEHICLE_DETAILS, front->index);
    01752     SetWindowDirty(WC_VEHICLE_DEPOT, front->tile);
    01753     InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
    01754   } else {
    01755     v->InvalidateNewGRFCacheOfChain(); // always invalidate; querycost might have filled it
    01756   }
    01757
    01758   return cost;
    01759 }