summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/pathfinder/npf/npf.cpp36
-rw-r--r--src/pathfinder/npf/npf.h10
-rw-r--r--src/pathfinder/yapf/yapf_road.cpp33
3 files changed, 52 insertions, 27 deletions
diff --git a/src/pathfinder/npf/npf.cpp b/src/pathfinder/npf/npf.cpp
index d444d779b..9e6d0c2f3 100644
--- a/src/pathfinder/npf/npf.cpp
+++ b/src/pathfinder/npf/npf.cpp
@@ -21,6 +21,7 @@
#include "../../roadveh.h"
#include "../../ship.h"
#include "../../train.h"
+#include "../../roadstop_base.h"
#include "../pathfinder_func.h"
#include "../pathfinder_type.h"
#include "npf.h"
@@ -104,8 +105,8 @@ static int32 NPFCalcStationOrTileHeuristic(AyStar *as, AyStarNode *current, Open
uint dist;
/* for train-stations, we are going to aim for the closest station tile */
- if (as->user_data[NPF_TYPE] == TRANSPORT_RAIL && fstd->station_index != INVALID_STATION)
- to = CalcClosestStationTile(fstd->station_index, from, STATION_RAIL);
+ if (as->user_data[NPF_TYPE] != TRANSPORT_WATER && fstd->station_index != INVALID_STATION)
+ to = CalcClosestStationTile(fstd->station_index, from, fstd->station_type);
if (as->user_data[NPF_TYPE] == TRANSPORT_ROAD) {
/* Since roads only have diagonal pieces, we use manhattan distance here */
@@ -279,11 +280,13 @@ static int32 NPFRoadPathCost(AyStar *as, AyStarNode *current, OpenListNode *pare
if (IsLevelCrossing(tile)) cost += _settings_game.pf.npf.npf_crossing_penalty;
break;
- case MP_STATION:
+ case MP_STATION: {
cost = NPF_TILE_LENGTH;
/* Increase the cost for drive-through road stops */
if (IsDriveThroughStopTile(tile)) cost += _settings_game.pf.npf.npf_road_drive_through_penalty;
- break;
+ RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile));
+ cost += 8 * NPF_TILE_LENGTH * ((!rs->IsFreeBay(0)) + (!rs->IsFreeBay(1)));
+ } break;
default:
break;
@@ -447,16 +450,14 @@ static int32 NPFFindStationOrTile(AyStar *as, OpenListNode *current)
AyStarNode *node = &current->path.node;
TileIndex tile = node->tile;
- /* If GetNeighbours said we could get here, we assume the station type
- * is correct */
- if (
- (fstd->station_index == INVALID_STATION && tile == fstd->dest_coords) || // We've found the tile, or
- (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == fstd->station_index) // the station
- ) {
- return AYSTAR_FOUND_END_NODE;
- } else {
- return AYSTAR_DONE;
+ if (fstd->station_index == INVALID_STATION && tile == fstd->dest_coords) return AYSTAR_FOUND_END_NODE;
+
+ if (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == fstd->station_index) {
+ if (fstd->station_type == STATION_RAIL) return AYSTAR_FOUND_END_NODE;
+ /* Only if it is a valid station *and* we can stop there */
+ if (GetStationType(tile) == fstd->station_type && (fstd->not_articulated || IsDriveThroughStopTile(tile))) return AYSTAR_FOUND_END_NODE;
}
+ return AYSTAR_DONE;
}
/**
@@ -1086,10 +1087,13 @@ void NPFFillWithOrderData(NPFFindStationOrTileData *fstd, const Vehicle *v, bool
* dest_tile, not just any stop of that station.
* So only for train orders to stations we fill fstd->station_index, for all
* others only dest_coords */
- if (v->type == VEH_TRAIN && (v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_WAYPOINT))) {
+ if (v->type != VEH_SHIP && (v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_WAYPOINT))) {
+ assert(v->type == VEH_TRAIN || v->type == VEH_ROAD);
fstd->station_index = v->current_order.GetDestination();
- /* Let's take the closest tile of the station as our target for trains */
- fstd->dest_coords = CalcClosestStationTile(fstd->station_index, v->tile, STATION_RAIL);
+ fstd->station_type = (v->type == VEH_TRAIN) ? STATION_RAIL : (RoadVehicle::From(v)->IsBus() ? STATION_BUS : STATION_TRUCK);
+ fstd->not_articulated = v->type == VEH_ROAD && !RoadVehicle::From(v)->HasArticulatedPart();
+ /* Let's take the closest tile of the station as our target for vehicles */
+ fstd->dest_coords = CalcClosestStationTile(fstd->station_index, v->tile, fstd->station_type);
} else {
fstd->dest_coords = v->dest_tile;
fstd->station_index = INVALID_STATION;
diff --git a/src/pathfinder/npf/npf.h b/src/pathfinder/npf/npf.h
index 61a4409a1..bdffa164a 100644
--- a/src/pathfinder/npf/npf.h
+++ b/src/pathfinder/npf/npf.h
@@ -33,10 +33,12 @@ enum {
/* Meant to be stored in AyStar.targetdata */
struct NPFFindStationOrTileData {
- TileIndex dest_coords; ///< An indication of where the station is, for heuristic purposes, or the target tile
- StationID station_index; ///< station index we're heading for, or INVALID_STATION when we're heading for a tile
- bool reserve_path; ///< Indicates whether the found path should be reserved
- const Vehicle *v; ///< The vehicle we are pathfinding for
+ TileIndex dest_coords; ///< An indication of where the station is, for heuristic purposes, or the target tile
+ StationID station_index; ///< station index we're heading for, or INVALID_STATION when we're heading for a tile
+ bool reserve_path; ///< Indicates whether the found path should be reserved
+ StationType station_type; ///< The type of station we're heading for
+ bool not_articulated; ///< The (road) vehicle is not articulated
+ const Vehicle *v; ///< The vehicle we are pathfinding for
};
/* Indices into AyStar.userdata[] */
diff --git a/src/pathfinder/yapf/yapf_road.cpp b/src/pathfinder/yapf/yapf_road.cpp
index af4413111..5ca3b1441 100644
--- a/src/pathfinder/yapf/yapf_road.cpp
+++ b/src/pathfinder/yapf/yapf_road.cpp
@@ -66,11 +66,11 @@ protected:
}
break;
- case MP_STATION:
- if (IsDriveThroughStopTile(tile)) {
- cost += Yapf().PfGetSettings().road_stop_penalty;
- }
- break;
+ case MP_STATION: {
+ if (IsDriveThroughStopTile(tile)) cost += Yapf().PfGetSettings().road_stop_penalty;
+ RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile));
+ cost += 8 * YAPF_TILE_LENGTH * ((!rs->IsFreeBay(0)) + (!rs->IsFreeBay(1)));
+ } break;
default:
break;
@@ -268,12 +268,24 @@ public:
protected:
TileIndex m_destTile;
TrackdirBits m_destTrackdirs;
+ StationID m_dest_station;
+ bool m_bus;
+ bool m_non_artic;
public:
void SetDestination(const RoadVehicle *v)
{
- m_destTile = v->dest_tile;
- m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_ROAD, v->compatible_roadtypes));
+ if (v->current_order.IsType(OT_GOTO_STATION)) {
+ m_dest_station = v->current_order.GetDestination();
+ m_bus = v->IsBus();
+ m_destTile = CalcClosestStationTile(m_dest_station, v->tile, m_bus ? STATION_BUS : STATION_TRUCK);
+ m_non_artic = !v->HasArticulatedPart();
+ m_destTrackdirs = INVALID_TRACKDIR_BIT;
+ } else {
+ m_dest_station = INVALID_STATION;
+ m_destTile = v->dest_tile;
+ m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_ROAD, v->compatible_roadtypes));
+ }
}
protected:
@@ -292,6 +304,13 @@ public:
FORCEINLINE bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir)
{
+ if (m_dest_station != INVALID_STATION) {
+ return IsTileType(tile, MP_STATION) &&
+ GetStationIndex(tile) == m_dest_station &&
+ (m_bus ? IsBusStop(tile) : IsTruckStop(tile)) &&
+ (m_non_artic || IsDriveThroughStopTile(tile));
+ }
+
return tile == m_destTile && ((m_destTrackdirs & TrackdirToTrackdirBits(trackdir)) != TRACKDIR_BIT_NONE);
}