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 }

Generated on Tue Jan 5 21:02:57 2010 for OpenTTD by  doxygen 1.5.6