Index: src/settings.cpp =================================================================== --- src/settings.cpp (revision 12913) +++ src/settings.cpp (working copy) @@ -1439,7 +1439,7 @@ SDT_BOOL(Patches, train_income_warn, S, 0, true, STR_CONFIG_PATCHES_WARN_INCOME_LESS, NULL), SDT_VAR(Patches, order_review_system,SLE_UINT8, S,MS, 2, 0, 2, 0, STR_CONFIG_PATCHES_ORDER_REVIEW, NULL), SDT_BOOL(Patches, never_expire_vehicles, 0,NN, false, STR_CONFIG_PATCHES_NEVER_EXPIRE_VEHICLES,NULL), - SDT_BOOL(Patches, lost_train_warn, S, 0, true, STR_CONFIG_PATCHES_WARN_LOST_TRAIN, NULL), + SDT_BOOL(Patches, lost_vehicle_warn, S, 0, true, STR_CONFIG_PATCHES_WARN_LOST_VEHICLE, NULL), SDT_BOOL(Patches, autorenew, S, 0, false, STR_CONFIG_PATCHES_AUTORENEW_VEHICLE, EngineRenewUpdate), SDT_VAR(Patches, autorenew_months, SLE_INT16, S, 0, 6, -12, 12, 0, STR_CONFIG_PATCHES_AUTORENEW_MONTHS, EngineRenewMonthsUpdate), SDT_VAR(Patches, autorenew_money, SLE_UINT, S,CR,100000, 0, 2000000, 0, STR_CONFIG_PATCHES_AUTORENEW_MONEY, EngineRenewMoneyUpdate), Index: src/lang/english.txt =================================================================== --- src/lang/english.txt (revision 12913) +++ src/lang/english.txt (working copy) @@ -985,6 +985,7 @@ STR_TRAIN_IS_LOST :{WHITE}Train {COMMA} is lost. STR_TRAIN_IS_UNPROFITABLE :{WHITE}Train {COMMA}'s profit last year was {CURRENCY} +STR_ROADVEHICLE_IS_LOST :{WHITE}Road Vehicle {COMMA} is lost. STR_EURO_INTRODUCE :{BLACK}{BIGFONT}European Monetary Union!{}{}The Euro is introduced as the sole currency for everyday transactions in your country! # Start of order review system. @@ -1057,7 +1058,7 @@ STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Always allow small airports: {ORANGE}{STRING1} -STR_CONFIG_PATCHES_WARN_LOST_TRAIN :{LTBLUE}Warn if train is lost: {ORANGE}{STRING1} +STR_CONFIG_PATCHES_WARN_LOST_VEHICLE :{LTBLUE}Warn if vehicle is lost: {ORANGE}{STRING1} STR_CONFIG_PATCHES_ORDER_REVIEW :{LTBLUE}Review vehicles' orders: {ORANGE}{STRING1} STR_CONFIG_PATCHES_ORDER_REVIEW_OFF :no STR_CONFIG_PATCHES_ORDER_REVIEW_EXDEPOT :yes, but exclude stopped vehicles Index: src/settings_gui.cpp =================================================================== --- src/settings_gui.cpp (revision 12913) +++ src/settings_gui.cpp (working copy) @@ -800,7 +800,7 @@ "train_income_warn", "order_review_system", "never_expire_vehicles", - "lost_train_warn", + "lost_vehicle_warn", "autorenew", "autorenew_months", "autorenew_money", Index: src/saveload.cpp =================================================================== --- src/saveload.cpp (revision 12913) +++ src/saveload.cpp (working copy) @@ -34,7 +34,7 @@ #include "table/strings.h" -extern const uint16 SAVEGAME_VERSION = 94; +extern const uint16 SAVEGAME_VERSION = 95; uint16 _sl_version; ///< the major savegame version identifier byte _sl_minor_version; ///< the minor savegame version, DO NOT USE! Index: src/train_cmd.cpp =================================================================== --- src/train_cmd.cpp (revision 12913) +++ src/train_cmd.cpp (working copy) @@ -2443,7 +2443,7 @@ /* it is first time the problem occurred, set the "path not found" flag */ SetBit(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION); /* and notify user about the event */ - if (_patches.lost_train_warn && v->owner == _local_player) { + if (_patches.lost_vehicle_warn && v->owner == _local_player) { SetDParam(0, v->unitnumber); AddNewsItem( STR_TRAIN_IS_LOST, @@ -2457,7 +2457,7 @@ if (HasBit(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION)) { /* clear the flag as the PF's problem was solved */ ClrBit(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION); - /* can we also delete the "News" item somehow? */ + DeleteVehicleNews(v->index, STR_TRAIN_IS_LOST); } } Index: src/settings_type.h =================================================================== --- src/settings_type.h (revision 12913) +++ src/settings_type.h (working copy) @@ -73,7 +73,7 @@ uint8 raw_industry_construction; ///< Type of (raw) industry construction (none, "normal", prospecting) bool multiple_industry_per_town; ///< allow many industries of the same type per town bool same_industry_close; ///< allow same type industries to be built close to each other - bool lost_train_warn; ///< if a train can't find its destination, show a warning + bool lost_vehicle_warn; ///< if a vehicle can't find its destination, show a warning uint8 order_review_system; bool train_income_warn; ///< if train is generating little income, show a warning bool status_long_date; ///< always show long date in status bar Index: src/yapf/yapf_road.cpp =================================================================== --- src/yapf/yapf_road.cpp (revision 12913) +++ src/yapf/yapf_road.cpp (working copy) @@ -253,13 +253,13 @@ /// return debug report character to identify the transportation type FORCEINLINE char TransportTypeChar() const {return 'r';} - static Trackdir stChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir) + static Trackdir stChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, bool *path_not_found) { Tpf pf; - return pf.ChooseRoadTrack(v, tile, enterdir); + return pf.ChooseRoadTrack(v, tile, enterdir, path_not_found); } - FORCEINLINE Trackdir ChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir) + FORCEINLINE Trackdir ChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, bool *path_not_found) { // handle special case - when next tile is destination tile if (tile == v->dest_tile) { @@ -282,7 +282,11 @@ Yapf().SetDestination(dest_tile, dest_trackdirs); // find the best path - Yapf().FindPath(v); + bool path_found = Yapf().FindPath(v); + if (path_not_found != NULL) { + // tell controller that the path was only 'guessed' + *path_not_found = !path_found; + } // if path not found - return INVALID_TRACKDIR Trackdir next_trackdir = INVALID_TRACKDIR; @@ -400,17 +404,17 @@ struct CYapfRoadAnyDepot2 : CYapfT > {}; -Trackdir YapfChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir) +Trackdir YapfChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, bool *path_not_found) { // default is YAPF type 2 - typedef Trackdir (*PfnChooseRoadTrack)(Vehicle*, TileIndex, DiagDirection); + typedef Trackdir (*PfnChooseRoadTrack)(Vehicle*, TileIndex, DiagDirection, bool*); PfnChooseRoadTrack pfnChooseRoadTrack = &CYapfRoad2::stChooseRoadTrack; // default: ExitDir, allow 90-deg // check if non-default YAPF type should be used if (_patches.yapf.disable_node_optimization) pfnChooseRoadTrack = &CYapfRoad1::stChooseRoadTrack; // Trackdir, allow 90-deg - Trackdir td_ret = pfnChooseRoadTrack(v, tile, enterdir); + Trackdir td_ret = pfnChooseRoadTrack(v, tile, enterdir, path_not_found); return td_ret; } Index: src/yapf/yapf.h =================================================================== --- src/yapf/yapf.h (revision 12913) +++ src/yapf/yapf.h (working copy) @@ -24,7 +24,7 @@ * @param enterdir diagonal direction which the RV will enter this new tile from * @return the best trackdir for next turn or INVALID_TRACKDIR if the path could not be found */ -Trackdir YapfChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir); +Trackdir YapfChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, bool *path_not_found); /** Finds the best path for given train. * @param v the train that needs to find a path Index: src/roadveh_cmd.cpp =================================================================== --- src/roadveh_cmd.cpp (revision 12913) +++ src/roadveh_cmd.cpp (working copy) @@ -1064,6 +1064,9 @@ TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes); TrackdirBits red_signals = TrackStatusToRedSignals(ts); // crossing TrackdirBits trackdirs = TrackStatusToTrackdirBits(ts); + + bool tried_pathfinding = false; + bool path_not_found = false; if (IsTileType(tile, MP_ROAD)) { if (IsRoadDepot(tile) && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir || (GetRoadTypes(tile) & v->u.road.compatible_roadtypes) == 0)) { @@ -1126,12 +1129,14 @@ switch (_patches.pathfinder_for_roadvehs) { case VPF_YAPF: { /* YAPF */ - Trackdir trackdir = YapfChooseRoadTrack(v, tile, enterdir); + tried_pathfinding = true; + Trackdir trackdir = YapfChooseRoadTrack(v, tile, enterdir, &path_not_found); if (trackdir != INVALID_TRACKDIR) return_track(trackdir); return_track(PickRandomBit(trackdirs)); } break; case VPF_NPF: { /* NPF */ + tried_pathfinding = true; NPFFindStationOrTileData fstd; NPFFillWithOrderData(&fstd, v); @@ -1149,6 +1154,7 @@ * the direction we need to take to get there, if ftd.best_bird_dist is not 0, * we did not find our target, but ftd.best_trackdir contains the direction leading * to the tile closest to our target. */ + if (ftd.best_bird_dist != 0) path_not_found = true; return_track(ftd.best_trackdir); } } break; @@ -1204,6 +1210,33 @@ found_best_track:; + /* handle "path not found" state */ + if (tried_pathfinding) { + if (path_not_found) { + /* PF didn't find the route */ + if (!HasBit(v->u.road.flags, VROF_NO_PATH_TO_DESTINATION)) { + /* it is first time the problem occurred, set the "path not found" flag */ + SetBit(v->u.road.flags, VROF_NO_PATH_TO_DESTINATION); + /* and notify user about the event */ + if (_patches.lost_vehicle_warn && v->owner == _local_player) { + SetDParam(0, v->unitnumber); + AddNewsItem( + STR_ROADVEHICLE_IS_LOST, + NM_SMALL, NF_VIEWPORT | NF_VEHICLE, NT_ADVICE, DNC_NONE, + v->index, + 0); + } + } + } else { + /* route found, is the vehicle marked with "path not found" flag? */ + if (HasBit(v->u.road.flags, VROF_NO_PATH_TO_DESTINATION)) { + /* clear the flag as the PF's problem was solved */ + ClrBit(v->u.road.flags, VROF_NO_PATH_TO_DESTINATION); + DeleteVehicleNews(v->index, STR_ROADVEHICLE_IS_LOST); + } + } + } + if (HasBit(red_signals, best_track)) return INVALID_TRACKDIR; return best_track; Index: src/vehicle.cpp =================================================================== --- src/vehicle.cpp (revision 12913) +++ src/vehicle.cpp (working copy) @@ -2316,6 +2316,7 @@ SLE_CONDREFX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRoad, slot), REF_ROADSTOPS, 6, SL_MAX_VERSION), SLE_CONDNULL(1, 6, SL_MAX_VERSION), SLE_CONDVARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRoad, slot_age), SLE_UINT8, 6, SL_MAX_VERSION), + SLE_CONDVARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRoad, flags), SLE_UINT8, 95, SL_MAX_VERSION), /* reserve extra space in savegame here. (currently 16 bytes) */ SLE_CONDNULL(16, 2, SL_MAX_VERSION), Index: src/vehicle_base.h =================================================================== --- src/vehicle_base.h (revision 12913) +++ src/vehicle_base.h (working copy) @@ -166,10 +166,15 @@ EngineID first_engine; byte cached_veh_length; + byte flags; RoadType roadtype; RoadTypes compatible_roadtypes; }; +enum VehicleRoadFlags { + VROF_NO_PATH_TO_DESTINATION = 0, +}; + struct VehicleEffect { uint16 animation_state; byte animation_substate;