diff --git a/src/pathfinder/yapf/yapf_road.cpp b/src/pathfinder/yapf/yapf_road.cpp --- a/src/pathfinder/yapf/yapf_road.cpp +++ b/src/pathfinder/yapf/yapf_road.cpp @@ -10,10 +10,9 @@ /** @file yapf_road.cpp The road pathfinding. */ #include "../../stdafx.h" -#include "../../roadstop_base.h" - #include "yapf.hpp" #include "yapf_node_road.hpp" +#include "../../roadstop_base.h" template diff --git a/src/roadstop.cpp b/src/roadstop.cpp --- a/src/roadstop.cpp +++ b/src/roadstop.cpp @@ -47,6 +47,63 @@ RoadStop *RoadStop::GetNextRoadStop(cons } /** + * Leave the road stop + * @param rv the vehicle that leaves the stop + */ +void RoadStop::Leave(RoadVehicle *rv) +{ + /* Vehicle is leaving a road stop tile, mark bay as free + * For drive-through stops, only do it if the vehicle stopped here */ + if (IsStandardRoadStopTile(rv->tile) || HasBit(rv->state, RVS_IS_STOPPING)) { + this->FreeBay(HasBit(rv->state, RVS_USING_SECOND_BAY)); + ClrBit(rv->state, RVS_IS_STOPPING); + } + if (IsStandardRoadStopTile(rv->tile)) this->SetEntranceBusy(false); +} + +/** + * Enter the road stop + * @param rv the vehicle that enters the stop + * @return whether the road stop could actually be entered + */ +bool RoadStop::Enter(RoadVehicle *rv) +{ + if (IsStandardRoadStopTile(this->xy)) { + /* For normal (non drive-through) road stops + * Check if station is busy or if there are no free bays or whether it is a articulated vehicle. */ + if (this->IsEntranceBusy() || !this->HasFreeBay() || rv->HasArticulatedPart()) return false; + + SetBit(rv->state, RVS_IN_ROAD_STOP); + + /* Allocate a bay and update the road state */ + uint bay_nr = this->AllocateBay(); + SB(rv->state, RVS_USING_SECOND_BAY, 1, bay_nr); + + /* Mark the station entrace as busy */ + this->SetEntranceBusy(true); + return true; + } + + /* Vehicles entering a drive-through stop from the 'normal' side use first bay (bay 0). */ + byte side = ((DirToDiagDir(rv->direction) == ReverseDiagDir(GetRoadStopDir(this->xy))) == (rv->overtaking == 0)) ? 0 : 1; + + if (!this->IsFreeBay(side)) return false; + + /* Check if the vehicle is stopping at this road stop */ + if (GetRoadStopType(this->xy) == (rv->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK) && + rv->current_order.ShouldStopAtStation(rv, GetStationIndex(this->xy))) { + SetBit(rv->state, RVS_IS_STOPPING); + this->AllocateDriveThroughBay(side); + } + + /* Indicate if vehicle is using second bay. */ + if (side == 1) SetBit(rv->state, RVS_USING_SECOND_BAY); + /* Indicate a drive-through stop */ + SetBit(rv->state, RVS_IN_DT_ROAD_STOP); + return true; +} + +/** * Find a roadstop at given tile * @param tile tile with roadstop * @param type roadstop type diff --git a/src/roadstop_base.h b/src/roadstop_base.h --- a/src/roadstop_base.h +++ b/src/roadstop_base.h @@ -63,6 +63,32 @@ struct RoadStop : RoadStopPool::PoolItem } /** + * Checks whether the entrance of the road stop is occupied by a vehicle + * @return is entrance busy? + */ + FORCEINLINE bool IsEntranceBusy() const + { + return HasBit(this->status, RSSFB_ENTRY_BUSY); + } + + /** + * Makes an entrance occupied or free + * @param busy if true, marks busy; free otherwise + */ + FORCEINLINE void SetEntranceBusy(bool busy) + { + SB(this->status, RSSFB_ENTRY_BUSY, 1, busy); + } + + void Leave(RoadVehicle *rv); + bool Enter(RoadVehicle *rv); + + RoadStop *GetNextRoadStop(const struct RoadVehicle *v) const; + + static RoadStop *GetByTile(TileIndex tile, RoadStopType type); + +private: + /** * Allocates a bay * @return the allocated bay number * @pre this->HasFreeBay() @@ -98,29 +124,6 @@ struct RoadStop : RoadStopPool::PoolItem assert(nr < RSSFB_BAY_COUNT); SetBit(this->status, nr); } - - - /** - * Checks whether the entrance of the road stop is occupied by a vehicle - * @return is entrance busy? - */ - FORCEINLINE bool IsEntranceBusy() const - { - return HasBit(this->status, RSSFB_ENTRY_BUSY); - } - - /** - * Makes an entrance occupied or free - * @param busy if true, marks busy; free otherwise - */ - FORCEINLINE void SetEntranceBusy(bool busy) - { - SB(this->status, RSSFB_ENTRY_BUSY, 1, busy); - } - - RoadStop *GetNextRoadStop(const struct RoadVehicle *v) const; - - static RoadStop *GetByTile(TileIndex tile, RoadStopType type); }; #define FOR_ALL_ROADSTOPS_FROM(var, start) FOR_ALL_ITEMS_FROM(RoadStop, roadstop_index, var, start) diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -465,13 +465,7 @@ void RoadVehicle::UpdateDeltaXY(Directio static void ClearCrashedStation(RoadVehicle *v) { - RoadStop *rs = RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile)); - - /* Mark the station entrance as not busy */ - rs->SetEntranceBusy(false); - - /* Free the parking bay */ - rs->FreeBay(HasBit(v->state, RVS_USING_SECOND_BAY)); + RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v); } static void DeleteLastRoadVeh(RoadVehicle *v) @@ -1317,17 +1311,7 @@ again: v->cur_speed = 0; return false; } - if (IsRoadStop(v->tile)) { - RoadStop *rs = RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile)); - - /* Vehicle is leaving a road stop tile, mark bay as free - * For drive-through stops, only do it if the vehicle stopped here */ - if (IsStandardRoadStopTile(v->tile) || HasBit(v->state, RVS_IS_STOPPING)) { - rs->FreeBay(HasBit(v->state, RVS_USING_SECOND_BAY)); - ClrBit(v->state, RVS_IS_STOPPING); - } - if (IsStandardRoadStopTile(v->tile)) rs->SetEntranceBusy(false); - } + if (IsRoadStop(v->tile)) RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v); } if (!HasBit(r, VETS_ENTERED_WORMHOLE)) { diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -12,7 +12,6 @@ #include "../stdafx.h" #include "../void_map.h" #include "../signs_base.h" -#include "../roadstop_base.h" #include "../depot_base.h" #include "../window_func.h" #include "../fios.h" @@ -33,6 +32,7 @@ #include "../train.h" #include "../station_base.h" #include "../waypoint_base.h" +#include "../roadstop_base.h" #include "../tunnelbridge_map.h" #include "../landscape.h" #include "../pathfinder/yapf/yapf_cache.h" diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2648,9 +2648,8 @@ static bool ClickTile_Station(TileIndex static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, int x, int y) { - StationID station_id = GetStationIndex(tile); - if (v->type == VEH_TRAIN) { + StationID station_id = GetStationIndex(tile); if (!v->current_order.ShouldStopAtStation(v, station_id)) return VETSB_CONTINUE; if (!IsRailStation(tile) || !Train::From(v)->IsFrontEngine()) return VETSB_CONTINUE; @@ -2688,42 +2687,7 @@ static VehicleEnterTileStatus VehicleEnt if (rv->state < RVSB_IN_ROAD_STOP && !IsReversingRoadTrackdir((Trackdir)rv->state) && rv->frame == 0) { if (IsRoadStop(tile) && rv->IsRoadVehFront()) { /* Attempt to allocate a parking bay in a road stop */ - RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile)); - - if (IsDriveThroughStopTile(tile)) { - if (!rv->current_order.ShouldStopAtStation(v, station_id)) return VETSB_CONTINUE; - - /* Vehicles entering a drive-through stop from the 'normal' side use first bay (bay 0). */ - byte side = ((DirToDiagDir(rv->direction) == ReverseDiagDir(GetRoadStopDir(tile))) == (rv->overtaking == 0)) ? 0 : 1; - - if (!rs->IsFreeBay(side)) return VETSB_CANNOT_ENTER; - - /* Check if the vehicle is stopping at this road stop */ - if (GetRoadStopType(tile) == (rv->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK) && - rv->current_order.GetDestination() == GetStationIndex(tile)) { - SetBit(rv->state, RVS_IS_STOPPING); - rs->AllocateDriveThroughBay(side); - } - - /* Indicate if vehicle is using second bay. */ - if (side == 1) SetBit(rv->state, RVS_USING_SECOND_BAY); - /* Indicate a drive-through stop */ - SetBit(rv->state, RVS_IN_DT_ROAD_STOP); - return VETSB_CONTINUE; - } - - /* For normal (non drive-through) road stops - * Check if station is busy or if there are no free bays or whether it is a articulated vehicle. */ - if (rs->IsEntranceBusy() || !rs->HasFreeBay() || rv->HasArticulatedPart()) return VETSB_CANNOT_ENTER; - - SetBit(rv->state, RVS_IN_ROAD_STOP); - - /* Allocate a bay and update the road state */ - uint bay_nr = rs->AllocateBay(); - SB(rv->state, RVS_USING_SECOND_BAY, 1, bay_nr); - - /* Mark the station entrace as busy */ - rs->SetEntranceBusy(true); + return RoadStop::GetByTile(tile, GetRoadStopType(tile))->Enter(rv) ? VETSB_CONTINUE : VETSB_CANNOT_ENTER; } } }