Fix unnecessary braking when leaving station with order without non-stop flag

This commit is contained in:
Jonathan G Rennison
2021-03-17 18:00:12 +00:00
parent fb64e29c6c
commit f7dcd66f08
3 changed files with 34 additions and 14 deletions

View File

@@ -495,6 +495,7 @@ public:
*/ */
inline void SetOccupancy(uint8 occupancy) { this->occupancy = occupancy; } inline void SetOccupancy(uint8 occupancy) { this->occupancy = occupancy; }
bool ShouldStopAtStation(StationID last_station_visited, StationID station, bool waypoint) const;
bool ShouldStopAtStation(const Vehicle *v, StationID station, bool waypoint) const; bool ShouldStopAtStation(const Vehicle *v, StationID station, bool waypoint) const;
bool CanLeaveWithCargo(bool has_cargo, CargoID cargo) const; bool CanLeaveWithCargo(bool has_cargo, CargoID cargo) const;

View File

@@ -3072,6 +3072,26 @@ bool ProcessOrders(Vehicle *v)
return UpdateOrderDest(v, order) && may_reverse; return UpdateOrderDest(v, order) && may_reverse;
} }
/**
* Check whether the given vehicle should stop at the given station
* based on this order and the non-stop settings.
* @param last_station_visited the last visited station.
* @param station the station to stop at.
* @param waypoint if station is a waypoint.
* @return true if the vehicle should stop.
*/
bool Order::ShouldStopAtStation(StationID last_station_visited, StationID station, bool waypoint) const
{
if (waypoint) return this->IsType(OT_GOTO_WAYPOINT) && this->dest == station && this->IsWaitTimetabled();
if (this->IsType(OT_LOADING_ADVANCE) && this->dest == station) return true;
bool is_dest_station = this->IsType(OT_GOTO_STATION) && this->dest == station;
return (!this->IsType(OT_GOTO_DEPOT) || (this->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0) &&
(last_station_visited != station) && // Do stop only when we've not just been there
/* Finally do stop when there is no non-stop flag set for this type of station. */
!(this->GetNonStopType() & (is_dest_station ? ONSF_NO_STOP_AT_DESTINATION_STATION : ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS));
}
/** /**
* Check whether the given vehicle should stop at the given station * Check whether the given vehicle should stop at the given station
* based on this order and the non-stop settings. * based on this order and the non-stop settings.
@@ -3082,14 +3102,7 @@ bool ProcessOrders(Vehicle *v)
*/ */
bool Order::ShouldStopAtStation(const Vehicle *v, StationID station, bool waypoint) const bool Order::ShouldStopAtStation(const Vehicle *v, StationID station, bool waypoint) const
{ {
if (waypoint) return this->IsType(OT_GOTO_WAYPOINT) && this->dest == station && this->IsWaitTimetabled(); return this->ShouldStopAtStation(v->last_station_visited, station, waypoint);
if (this->IsType(OT_LOADING_ADVANCE) && this->dest == station) return true;
bool is_dest_station = this->IsType(OT_GOTO_STATION) && this->dest == station;
return (!this->IsType(OT_GOTO_DEPOT) || (this->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0) &&
(v == nullptr || v->last_station_visited != station) && // Do stop only when we've not just been there
/* Finally do stop when there is no non-stop flag set for this type of station. */
!(this->GetNonStopType() & (is_dest_station ? ONSF_NO_STOP_AT_DESTINATION_STATION : ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS));
} }
/** /**

View File

@@ -827,7 +827,7 @@ static void LimitSpeedFromLookAhead(int &max_speed, const TrainDecelerationStats
} }
static void ApplyLookAheadItem(const Train *v, const TrainReservationLookAheadItem &item, int &max_speed, int &advisory_max_speed, static void ApplyLookAheadItem(const Train *v, const TrainReservationLookAheadItem &item, int &max_speed, int &advisory_max_speed,
VehicleOrderID &current_order_index, const Order *&order, const TrainDecelerationStats &stats, int current_position) VehicleOrderID &current_order_index, const Order *&order, StationID &last_station_visited, const TrainDecelerationStats &stats, int current_position)
{ {
auto limit_speed = [&](int position, int end_speed, int z) { auto limit_speed = [&](int position, int end_speed, int z) {
LimitSpeedFromLookAhead(max_speed, stats, current_position, position, end_speed, z - stats.z_pos); LimitSpeedFromLookAhead(max_speed, stats, current_position, position, end_speed, z - stats.z_pos);
@@ -839,10 +839,12 @@ static void ApplyLookAheadItem(const Train *v, const TrainReservationLookAheadIt
switch (item.type) { switch (item.type) {
case TRLIT_STATION: { case TRLIT_STATION: {
if (order->ShouldStopAtStation(nullptr, item.data_id, Waypoint::GetIfValid(item.data_id) != nullptr)) { if (order->ShouldStopAtStation(last_station_visited, item.data_id, Waypoint::GetIfValid(item.data_id) != nullptr)) {
limit_advisory_speed(item.start + PredictStationStoppingLocation(v, order, item.end - item.start, item.data_id), 0, item.z_pos); limit_advisory_speed(item.start + PredictStationStoppingLocation(v, order, item.end - item.start, item.data_id), 0, item.z_pos);
last_station_visited = item.data_id;
} else if (order->IsType(OT_GOTO_WAYPOINT) && order->GetDestination() == item.data_id && (order->GetWaypointFlags() & OWF_REVERSE)) { } else if (order->IsType(OT_GOTO_WAYPOINT) && order->GetDestination() == item.data_id && (order->GetWaypointFlags() & OWF_REVERSE)) {
limit_advisory_speed(item.start + v->gcache.cached_total_length, 0, item.z_pos); limit_advisory_speed(item.start + v->gcache.cached_total_length, 0, item.z_pos);
if (order->IsWaitTimetabled()) last_station_visited = item.data_id;
} }
if (order->IsBaseStationOrder() && order->GetDestination() == item.data_id && v->GetNumOrders() > 0) { if (order->IsBaseStationOrder() && order->GetDestination() == item.data_id && v->GetNumOrders() > 0) {
current_order_index++; current_order_index++;
@@ -1002,8 +1004,9 @@ Train::MaxSpeedInfo Train::GetCurrentMaxSpeedInfoInternal(bool update_state) con
} }
VehicleOrderID current_order_index = this->cur_real_order_index; VehicleOrderID current_order_index = this->cur_real_order_index;
const Order *order = &(this->current_order); const Order *order = &(this->current_order);
StationID last_station_visited = this->last_station_visited;
for (const TrainReservationLookAheadItem &item : this->lookahead->items) { for (const TrainReservationLookAheadItem &item : this->lookahead->items) {
ApplyLookAheadItem(this, item, max_speed, advisory_max_speed, current_order_index, order, stats, this->lookahead->current_position); ApplyLookAheadItem(this, item, max_speed, advisory_max_speed, current_order_index, order, last_station_visited, stats, this->lookahead->current_position);
} }
if (HasBit(this->lookahead->flags, TRLF_APPLY_ADVISORY)) { if (HasBit(this->lookahead->flags, TRLF_APPLY_ADVISORY)) {
max_speed = std::min(max_speed, advisory_max_speed); max_speed = std::min(max_speed, advisory_max_speed);
@@ -3697,8 +3700,9 @@ public:
HasStationTileRail(v->tile) && v->current_order.GetDestination() == GetStationIndex(v->tile) : HasStationTileRail(v->tile) && v->current_order.GetDestination() == GetStationIndex(v->tile) :
v->tile == v->dest_tile))) { v->tile == v->dest_tile))) {
if (_settings_game.vehicle.train_braking_model == TBM_REALISTIC && v->current_order.IsBaseStationOrder()) { if (_settings_game.vehicle.train_braking_model == TBM_REALISTIC && v->current_order.IsBaseStationOrder()) {
if (v->current_order.ShouldStopAtStation(nullptr, v->current_order.GetDestination(), v->current_order.IsType(OT_GOTO_WAYPOINT))) { if (v->current_order.ShouldStopAtStation(v, v->current_order.GetDestination(), v->current_order.IsType(OT_GOTO_WAYPOINT))) {
SetBit(state.flags, CTTLASF_STOP_FOUND); SetBit(state.flags, CTTLASF_STOP_FOUND);
v->last_station_visited = v->current_order.GetDestination();
} }
} }
if (v->current_order.IsAnyLoadingType()) SetBit(state.flags, CTTLASF_STOP_FOUND); if (v->current_order.IsAnyLoadingType()) SetBit(state.flags, CTTLASF_STOP_FOUND);
@@ -3717,12 +3721,14 @@ public:
case TRLIT_STATION: case TRLIT_STATION:
if (this->v->current_order.IsBaseStationOrder()) { if (this->v->current_order.IsBaseStationOrder()) {
/* we've already seen this station in the lookahead, advance current order */ /* we've already seen this station in the lookahead, advance current order */
if (this->v->current_order.ShouldStopAtStation(nullptr, item.data_id, Waypoint::GetIfValid(item.data_id) != nullptr)) { if (this->v->current_order.ShouldStopAtStation(this->v, item.data_id, Waypoint::GetIfValid(item.data_id) != nullptr)) {
SetBit(state.flags, CTTLASF_STOP_FOUND); SetBit(state.flags, CTTLASF_STOP_FOUND);
this->v->last_station_visited = item.data_id;
} else if (this->v->current_order.IsType(OT_GOTO_WAYPOINT) && this->v->current_order.GetDestination() == item.data_id && (this->v->current_order.GetWaypointFlags() & OWF_REVERSE)) { } else if (this->v->current_order.IsType(OT_GOTO_WAYPOINT) && this->v->current_order.GetDestination() == item.data_id && (this->v->current_order.GetWaypointFlags() & OWF_REVERSE)) {
if (!HasBit(state.flags, CTTLASF_REVERSE_FOUND)) { if (!HasBit(state.flags, CTTLASF_REVERSE_FOUND)) {
SetBit(state.flags, CTTLASF_REVERSE_FOUND); SetBit(state.flags, CTTLASF_REVERSE_FOUND);
state.reverse_dest = item.data_id; state.reverse_dest = item.data_id;
if (this->v->current_order.IsWaitTimetabled()) this->v->last_station_visited = item.data_id;
} }
} }
if (this->v->current_order.GetDestination() == item.data_id) { if (this->v->current_order.GetDestination() == item.data_id) {
@@ -4058,7 +4064,7 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
auto check_destination_seen = [&](TileIndex tile) { auto check_destination_seen = [&](TileIndex tile) {
if (_settings_game.vehicle.train_braking_model == TBM_REALISTIC && v->current_order.IsBaseStationOrder() && if (_settings_game.vehicle.train_braking_model == TBM_REALISTIC && v->current_order.IsBaseStationOrder() &&
HasStationTileRail(tile)) { HasStationTileRail(tile)) {
if (v->current_order.ShouldStopAtStation(nullptr, GetStationIndex(tile), IsRailWaypoint(tile))) { if (v->current_order.ShouldStopAtStation(v, GetStationIndex(tile), IsRailWaypoint(tile))) {
SetBit(lookahead_state.flags, CTTLASF_STOP_FOUND); SetBit(lookahead_state.flags, CTTLASF_STOP_FOUND);
} else if (v->current_order.IsType(OT_GOTO_WAYPOINT) && v->current_order.GetDestination() == GetStationIndex(tile) && (v->current_order.GetWaypointFlags() & OWF_REVERSE)) { } else if (v->current_order.IsType(OT_GOTO_WAYPOINT) && v->current_order.GetDestination() == GetStationIndex(tile) && (v->current_order.GetWaypointFlags() & OWF_REVERSE)) {
if (!HasBit(lookahead_state.flags, CTTLASF_REVERSE_FOUND)) { if (!HasBit(lookahead_state.flags, CTTLASF_REVERSE_FOUND)) {