|
@@ -378,66 +378,74 @@ static bool EnumRoadSignalFindDepot(Tile
|
|
|
|
|
|
tile += TileOffsByDiagDir(_road_pf_directions[trackdir]);
|
|
|
|
|
|
if (IsRoadDepotTile(tile) &&
|
|
|
IsTileOwner(tile, rfdd->owner) &&
|
|
|
length < rfdd->best_length) {
|
|
|
rfdd->best_length = length;
|
|
|
rfdd->tile = tile;
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
static const Depot *FindClosestRoadDepot(const RoadVehicle *v)
|
|
|
static RoadFindDepotData FindClosestRoadDepot(const RoadVehicle *v, int max_distance)
|
|
|
{
|
|
|
RoadFindDepotData rfdd;
|
|
|
rfdd.owner = v->owner;
|
|
|
|
|
|
if (IsRoadDepotTile(v->tile)) {
|
|
|
rfdd.tile = v->tile;
|
|
|
rfdd.best_length = 0;
|
|
|
return rfdd;
|
|
|
}
|
|
|
|
|
|
rfdd.best_length = UINT_MAX;
|
|
|
|
|
|
switch (_settings_game.pf.pathfinder_for_roadvehs) {
|
|
|
case VPF_YAPF: // YAPF
|
|
|
return YapfFindNearestRoadDepot(v);
|
|
|
case VPF_YAPF: { // YAPF
|
|
|
bool found = YapfFindNearestRoadDepot(v, max_distance, &rfdd.tile);
|
|
|
rfdd.best_length = found ? max_distance / 2 : UINT_MAX; // some fake distance or NOT_FOUND
|
|
|
} break;
|
|
|
|
|
|
case VPF_NPF: { // NPF
|
|
|
/* See where we are now */
|
|
|
Trackdir trackdir = v->GetVehicleTrackdir();
|
|
|
|
|
|
NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, v->tile, ReverseTrackdir(trackdir), false, TRANSPORT_ROAD, v->compatible_roadtypes, v->owner, INVALID_RAILTYPES, 0);
|
|
|
|
|
|
if (ftd.best_bird_dist == 0) return Depot::GetByTile(ftd.node.tile); // Target found
|
|
|
if (ftd.best_bird_dist == 0) {
|
|
|
rfdd.tile = ftd.node.tile;
|
|
|
rfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH;
|
|
|
}
|
|
|
} break;
|
|
|
|
|
|
default:
|
|
|
case VPF_OPF: { // OPF
|
|
|
RoadFindDepotData rfdd;
|
|
|
|
|
|
rfdd.owner = v->owner;
|
|
|
rfdd.best_length = UINT_MAX;
|
|
|
|
|
|
case VPF_OPF: // OPF
|
|
|
/* search in all directions */
|
|
|
for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
|
|
|
FollowTrack(v->tile, PATHFIND_FLAGS_NONE, TRANSPORT_ROAD, v->compatible_roadtypes, d, EnumRoadSignalFindDepot, NULL, &rfdd);
|
|
|
}
|
|
|
|
|
|
if (rfdd.best_length != UINT_MAX) return Depot::GetByTile(rfdd.tile);
|
|
|
} break;
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
return NULL; // Target not found
|
|
|
return rfdd; // Target not found
|
|
|
}
|
|
|
|
|
|
bool RoadVehicle::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
|
|
|
{
|
|
|
const Depot *depot = FindClosestRoadDepot(this);
|
|
|
RoadFindDepotData rfdd = FindClosestRoadDepot(this, 0);
|
|
|
if (rfdd.best_length == UINT_MAX) return false;
|
|
|
|
|
|
if (depot == NULL) return false;
|
|
|
|
|
|
if (location != NULL) *location = depot->xy;
|
|
|
if (destination != NULL) *destination = depot->index;
|
|
|
if (location != NULL) *location = rfdd.tile;
|
|
|
if (destination != NULL) *destination = Depot::GetByTile(rfdd.tile)->index;
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/** Send a road vehicle to the depot.
|
|
|
* @param tile unused
|
|
|
* @param flags operation to perform
|
|
|
* @param p1 vehicle ID to send to the depot
|
|
|
* @param p2 various bitmasked elements
|
|
|
* - p2 bit 0-3 - DEPOT_ flags (see vehicle.h)
|
|
|
* - p2 bit 8-10 - VLW flag (for mass goto depot)
|
|
|
*/
|
|
@@ -1825,53 +1833,59 @@ static bool RoadVehController(RoadVehicl
|
|
|
bool RoadVehicle::Tick()
|
|
|
{
|
|
|
if (this->IsRoadVehFront()) {
|
|
|
if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
|
|
|
return RoadVehController(this);
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
static void CheckIfRoadVehNeedsService(RoadVehicle *v)
|
|
|
{
|
|
|
static const uint MAX_ACCEPTABLE_DEPOT_DIST = 16;
|
|
|
|
|
|
/* If we already got a slot at a stop, use that FIRST, and go to a depot later */
|
|
|
if (v->slot != NULL || Company::Get(v->owner)->settings.vehicle.servint_roadveh == 0 || !v->NeedsAutomaticServicing()) return;
|
|
|
if (v->IsInDepot()) {
|
|
|
VehicleServiceInDepot(v);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
/* XXX If we already have a depot order, WHY do we search over and over? */
|
|
|
const Depot *depot = FindClosestRoadDepot(v);
|
|
|
|
|
|
if (depot == NULL || DistanceManhattan(v->tile, depot->xy) > 12) {
|
|
|
RoadFindDepotData rfdd = FindClosestRoadDepot(v, MAX_ACCEPTABLE_DEPOT_DIST);
|
|
|
/* Only go to the depot if it is not too far out of our way. */
|
|
|
if (rfdd.best_length == UINT_MAX || rfdd.best_length > MAX_ACCEPTABLE_DEPOT_DIST) {
|
|
|
if (v->current_order.IsType(OT_GOTO_DEPOT)) {
|
|
|
/* If we were already heading for a depot but it has
|
|
|
* suddenly moved farther away, we continue our normal
|
|
|
* schedule? */
|
|
|
v->current_order.MakeDummy();
|
|
|
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
const Depot *depot = Depot::GetByTile(rfdd.tile);
|
|
|
|
|
|
if (v->current_order.IsType(OT_GOTO_DEPOT) &&
|
|
|
v->current_order.GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS &&
|
|
|
!Chance16(1, 20)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
|
|
|
ClearSlot(v);
|
|
|
|
|
|
v->current_order.MakeGoToDepot(depot->index, ODTFB_SERVICE);
|
|
|
v->dest_tile = depot->xy;
|
|
|
v->dest_tile = rfdd.tile;
|
|
|
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
|
|
|
}
|
|
|
|
|
|
void RoadVehicle::OnNewDay()
|
|
|
{
|
|
|
if (!this->IsRoadVehFront()) return;
|
|
|
|
|
|
if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
|
|
|
if (this->blocked_ctr == 0) CheckVehicleBreakdown(this);
|
|
|
|
|
|
AgeVehicle(this);
|
|
|
CheckIfRoadVehNeedsService(this);
|