# roadveh_cmd.cpp

Go to the documentation of this file.

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