From 0073c4e71eefa6ff499082ff1fc05d40c983f232 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 8 May 2017 21:54:15 +0100 Subject: [PATCH] Road vehicles may no longer be stopped on level crossings. --- src/roadveh.h | 16 +++++++++++++++- src/roadveh_cmd.cpp | 15 +++++++++++---- src/vehicle_cmd.cpp | 6 +++++- src/vehicle_gui.cpp | 9 ++++++++- 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/roadveh.h b/src/roadveh.h index 8a48c19837..a4e9fd5ea9 100644 --- a/src/roadveh.h +++ b/src/roadveh.h @@ -126,6 +126,20 @@ struct RoadVehicle FINAL : public GroundVehicle { int GetCurrentMaxSpeed() const; int UpdateSpeed(); + inline bool IsRoadVehicleOnLevelCrossing() const + { + for (const RoadVehicle *u = this; u != NULL; u = u->Next()) { + if (IsLevelCrossingTile(u->tile)) return true; + } + return false; + } + + inline bool IsRoadVehicleStopped() const + { + if (!(this->vehstatus & VS_STOPPED)) return false; + return !this->IsRoadVehicleOnLevelCrossing(); + } + protected: // These functions should not be called outside acceleration code. /** @@ -207,7 +221,7 @@ protected: // These functions should not be called outside acceleration code. */ inline AccelStatus GetAccelerationStatus() const { - return (this->vehstatus & VS_STOPPED) ? AS_BRAKE : AS_ACCEL; + return this->IsRoadVehicleStopped() ? AS_BRAKE : AS_ACCEL; } /** diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index cf6107aca4..ee5971bb54 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -680,7 +680,10 @@ static RoadVehicle *RoadVehFindCloseTo(RoadVehicle *v, int x, int y, Direction d if (update_blocked_ctr && ++front->blocked_ctr > 1480) return NULL; - return RoadVehicle::From(rvf.best); + RoadVehicle *rv = RoadVehicle::From(rvf.best); + if (rv != NULL && front->IsRoadVehicleOnLevelCrossing() && (rv->First()->cur_speed == 0 || rv->First()->IsRoadVehicleStopped())) return NULL; + + return rv; } /** @@ -851,7 +854,7 @@ static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u) /* When the vehicle in front of us is stopped we may only take * half the time to pass it than when the vehicle is moving. */ - v->overtaking_ctr = (od.u->cur_speed == 0 || (od.u->vehstatus & VS_STOPPED)) ? RV_OVERTAKE_TIMEOUT / 2 : 0; + v->overtaking_ctr = (od.u->cur_speed == 0 || od.u->IsRoadVehicleStopped()) ? RV_OVERTAKE_TIMEOUT / 2 : 0; v->overtaking = RVSB_DRIVE_SIDE; } @@ -1559,7 +1562,11 @@ static bool RoadVehController(RoadVehicle *v) /* road vehicle has broken down? */ if (v->HandleBreakdown()) return true; - if (v->vehstatus & VS_STOPPED) return true; + if (v->IsRoadVehicleStopped()) { + v->cur_speed = 0; + v->SetLastSpeed(); + return true; + } ProcessOrders(v); v->HandleLoading(); @@ -1629,7 +1636,7 @@ bool RoadVehicle::Tick() this->tick_counter++; if (this->IsFrontEngine()) { - if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++; + if (!(this->IsRoadVehicleStopped())) this->running_ticks++; return RoadVehController(this); } diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index e50ff5f713..d2b5ede764 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -643,7 +643,11 @@ CommandCost CmdStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, if (HasBit(v->vehicle_flags, VF_TIMETABLE_SEPARATION)) ClrBit(v->vehicle_flags, VF_TIMETABLE_STARTED); v->vehstatus ^= VS_STOPPED; - if (v->type != VEH_TRAIN) v->cur_speed = 0; // trains can stop 'slowly' + if (v->type == VEH_ROAD) { + if (!RoadVehicle::From(v)->IsRoadVehicleOnLevelCrossing()) v->cur_speed = 0; + } else if (v->type != VEH_TRAIN) { + v->cur_speed = 0; // trains can stop 'slowly' + } v->MarkDirty(); SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP); SetWindowDirty(WC_VEHICLE_DEPOT, v->tile); diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 50b735e7c4..ce74a3067d 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -3026,7 +3026,14 @@ public: SetDParam(0, v->GetDisplaySpeed()); str = STR_VEHICLE_STATUS_TRAIN_STOPPING_VEL; } - } else { // no train + } else if (v->type == VEH_ROAD) { + if (RoadVehicle::From(v)->IsRoadVehicleStopped()) { + str = STR_VEHICLE_STATUS_STOPPED; + } else { + SetDParam(0, v->GetDisplaySpeed()); + str = STR_VEHICLE_STATUS_TRAIN_STOPPING_VEL; + } + } else { // no train/RV str = STR_VEHICLE_STATUS_STOPPED; } } else if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_TRAIN_STUCK) && !v->current_order.IsType(OT_LOADING)) {