summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/roadveh_cmd.cpp28
-rw-r--r--src/station.cpp45
-rw-r--r--src/station.h26
-rw-r--r--src/station_cmd.cpp4
4 files changed, 73 insertions, 30 deletions
diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp
index ceb3d947d..d85203173 100644
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -794,24 +794,17 @@ static void ProcessRoadVehOrder(Vehicle *v)
switch (order->type) {
case OT_GOTO_STATION: {
- const RoadStop* rs;
-
if (order->dest == v->last_station_visited) {
v->last_station_visited = INVALID_STATION;
}
- rs = GetStation(order->dest)->GetPrimaryRoadStop(
- IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK
- );
+ const RoadStop *rs = GetStation(order->dest)->GetPrimaryRoadStop(v);
TileIndex dest = INVALID_TILE;
if (rs != NULL) {
uint mindist = MAX_UVALUE(uint);
- for (; rs != NULL; rs = rs->next) {
- /* The vehicle cannot go to this roadstop */
- if ((GetRoadTypes(rs->xy) & v->u.road.compatible_roadtypes) == ROADTYPES_NONE) continue;
-
+ for (; rs != NULL; rs = rs->GetNextRoadStop(v)) {
uint dist = DistanceManhattan(v->tile, rs->xy);
if (dist < mindist) {
@@ -1143,7 +1136,7 @@ static Trackdir RoadFindPathToDest(Vehicle* v, TileIndex tile, DiagDirection ent
FindRoadToChooseData frd;
Trackdir best_track;
- uint32 r = GetTileTrackStatus(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes);
+ uint32 r = GetTileTrackStatus(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes);
TrackdirBits signal = (TrackdirBits)GB(r, 16, 16);
TrackdirBits trackdirs = (TrackdirBits)GB(r, 0, 16);
@@ -1154,8 +1147,9 @@ static Trackdir RoadFindPathToDest(Vehicle* v, TileIndex tile, DiagDirection ent
}
} else if (IsTileType(tile, MP_STATION) && IsStandardRoadStopTile(tile)) {
/* Standard road stop (drive-through stops are treated as normal road) */
- if (!IsTileOwner(tile, v->owner) || GetRoadStopDir(tile) == enterdir) {
- /* different station owner or wrong orientation */
+
+ if (!IsTileOwner(tile, v->owner) || GetRoadStopDir(tile) == enterdir || RoadVehHasArticPart(v)) {
+ /* different station owner or wrong orientation or the vehicle has articulated parts */
trackdirs = TRACKDIR_BIT_NONE;
} else {
/* Our station */
@@ -1166,7 +1160,7 @@ static Trackdir RoadFindPathToDest(Vehicle* v, TileIndex tile, DiagDirection ent
trackdirs = TRACKDIR_BIT_NONE;
} else {
/* Proper station type, check if there is free loading bay */
- if (!_patches.roadveh_queue && IsStandardRoadStopTile(tile) &&
+ if (!_patches.roadveh_queue && IsStandardRoadStopTile(tile) &&
!GetRoadStopByTile(tile, rstype)->HasFreeBay()) {
/* Station is full and RV queuing is off */
trackdirs = TRACKDIR_BIT_NONE;
@@ -1922,9 +1916,9 @@ void OnNewDay_RoadVeh(Vehicle *v)
/* update destination */
if (v->current_order.type == OT_GOTO_STATION && v->u.road.slot == NULL && !(v->vehstatus & VS_CRASHED)) {
- Station* st = GetStation(v->current_order.dest);
- RoadStop* rs = st->GetPrimaryRoadStop(IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK);
- RoadStop* best = NULL;
+ Station *st = GetStation(v->current_order.dest);
+ RoadStop *rs = st->GetPrimaryRoadStop(v);
+ RoadStop *best = NULL;
if (rs != NULL) {
/* We try to obtain a slot if:
@@ -1941,7 +1935,7 @@ void OnNewDay_RoadVeh(Vehicle *v)
v->unitnumber, v->index, st->index, st->xy
);
/* Now we find the nearest road stop that has a free slot */
- for (; rs != NULL; rs = rs->next) {
+ for (; rs != NULL; rs = rs->GetNextRoadStop(v)) {
dist = RoadFindPathToStop(v, rs->xy);
if (dist == UINT_MAX) {
DEBUG(ms, 4, " stop 0x%X is unreachable, not treating further", rs->xy);
diff --git a/src/station.cpp b/src/station.cpp
index 16723fc68..6f0c12ce4 100644
--- a/src/station.cpp
+++ b/src/station.cpp
@@ -34,6 +34,8 @@
#include "yapf/yapf.h"
#include "date.h"
#include "helpers.hpp"
+#include "cargotype.h"
+#include "roadveh.h"
Station::Station(TileIndex tile)
{
@@ -92,6 +94,29 @@ Station::~Station()
}
}
+
+/**
+ * Get the primary road stop (the first road stop) that the given vehicle can load/unload.
+ * @param v the vehicle to get the first road stop for
+ * @return the first roadstop that this vehicle can load at
+ */
+RoadStop *Station::GetPrimaryRoadStop(const Vehicle *v) const
+{
+ RoadStop *rs = this->GetPrimaryRoadStop(IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK);
+
+ for (; rs != NULL; rs = rs->next) {
+ /* The vehicle cannot go to this roadstop (different roadtype) */
+ if ((GetRoadTypes(rs->xy) & v->u.road.compatible_roadtypes) == ROADTYPES_NONE) continue;
+ /* The vehicle is articulated and can therefor not go the a standard road stop */
+ if (IsStandardRoadStopTile(rs->xy) && RoadVehHasArticPart(v)) continue;
+
+ /* The vehicle can actually go to this road stop. So, return it! */
+ break;
+ }
+
+ return rs;
+}
+
/** Called when new facility is built on the station. If it is the first facility
* it initializes also 'xy' and 'random_bits' members */
void Station::AddFacility(byte new_facility_bit, TileIndex facil_xy)
@@ -480,3 +505,23 @@ void RoadStop::SetEntranceBusy(bool busy)
{
SB(status, 7, 1, busy);
}
+
+/**
+ * Get the next road stop accessible by this vehicle.
+ * @param v the vehicle to get the next road stop for.
+ * @return the next road stop accessible.
+ */
+RoadStop *RoadStop::GetNextRoadStop(const Vehicle *v) const
+{
+ for (RoadStop *rs = this->next; rs != NULL; rs = rs->next) {
+ /* The vehicle cannot go to this roadstop (different roadtype) */
+ if ((GetRoadTypes(rs->xy) & v->u.road.compatible_roadtypes) != ROADTYPES_NONE) continue;
+ /* The vehicle is articulated and can therefor not go the a standard road stop */
+ if (IsStandardRoadStopTile(rs->xy) && RoadVehHasArticPart(v)) continue;
+
+ /* The vehicle can actually go to this road stop. So, return it! */
+ return rs;
+ }
+
+ return NULL;
+}
diff --git a/src/station.h b/src/station.h
index 866375a42..5790c0c6a 100644
--- a/src/station.h
+++ b/src/station.h
@@ -70,6 +70,8 @@ struct RoadStop : PoolItem<RoadStop, RoadStopID, &_RoadStop_pool> {
void FreeBay(uint nr);
bool IsEntranceBusy() const;
void SetEntranceBusy(bool busy);
+
+ RoadStop *GetNextRoadStop(const Vehicle *v) const;
};
struct StationSpecList {
@@ -102,17 +104,19 @@ struct StationRect : public Rect {
};
struct Station : PoolItem<Station, StationID, &_Station_pool> {
- public:
- RoadStop *GetPrimaryRoadStop(RoadStop::Type type) const
- {
- return type == RoadStop::BUS ? bus_stops : truck_stops;
- }
-
- const AirportFTAClass *Airport() const
- {
- if (airport_tile == 0) return GetAirport(AT_DUMMY);
- return GetAirport(airport_type);
- }
+public:
+ RoadStop *GetPrimaryRoadStop(RoadStop::Type type) const
+ {
+ return type == RoadStop::BUS ? bus_stops : truck_stops;
+ }
+
+ RoadStop *GetPrimaryRoadStop(const Vehicle *v) const;
+
+ const AirportFTAClass *Airport() const
+ {
+ if (airport_tile == 0) return GetAirport(AT_DUMMY);
+ return GetAirport(airport_type);
+ }
TileIndex xy;
RoadStop *bus_stops;
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index d6b1d5e20..c01357948 100644
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -2343,8 +2343,8 @@ static uint32 VehicleEnter_Station(Vehicle *v, TileIndex tile, int x, int y)
}
/* For normal (non drive-through) road stops */
- /* Check if station is busy or if there are no free bays. */
- if (rs->IsEntranceBusy() || !rs->HasFreeBay()) return VETSB_CANNOT_ENTER;
+ /* Check if station is busy or if there are no free bays or whether it is a articulated vehicle. */
+ if (rs->IsEntranceBusy() || !rs->HasFreeBay() || RoadVehHasArticPart(v)) return VETSB_CANNOT_ENTER;
SETBIT(v->u.road.state, RVS_IN_ROAD_STOP);