diff options
-rw-r--r-- | src/roadveh_cmd.cpp | 28 | ||||
-rw-r--r-- | src/station.cpp | 45 | ||||
-rw-r--r-- | src/station.h | 26 | ||||
-rw-r--r-- | src/station_cmd.cpp | 4 |
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); |