diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 2f49158eb9..4d6683192a 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -1362,6 +1362,11 @@ static void AircraftEventHandler_InHangar(Aircraft *v, const AirportFTAClass *ap return; } + if (v->current_order.IsWaitTimetabled()) + v->HandleWaiting(false); + if (v->current_order.IsType(OT_WAITING)) + return; + /* if we were sent to the depot, stay there */ if (v->current_order.IsType(OT_GOTO_DEPOT) && (v->vehstatus & VS_STOPPED)) { v->current_order.Free(); diff --git a/src/order_base.h b/src/order_base.h index a67cf69bb4..4f0d0b489a 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -78,6 +78,7 @@ public: void MakeDummy(); void MakeConditional(VehicleOrderID order); void MakeImplicit(StationID destination); + void MakeWaiting(); /** * Is this a 'goto' order with a real destination? diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 57b29f3f53..2dd2bc427b 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -158,6 +158,11 @@ void Order::MakeImplicit(StationID destination) this->dest = destination; } +void Order::MakeWaiting() +{ + this->type = OT_WAITING; +} + /** * Make this depot/station order also a refit order. * @param cargo the cargo type to change to. @@ -1155,6 +1160,7 @@ CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 if (flags & DC_EXEC) { if (v->current_order.IsType(OT_LOADING)) v->LeaveStation(); + if (v->current_order.IsType(OT_WAITING)) v->HandleWaiting(true); v->cur_implicit_order_index = v->cur_real_order_index = sel_ord; v->UpdateRealOrderIndex(); @@ -2165,6 +2171,9 @@ bool ProcessOrders(Vehicle *v) case OT_LOADING: return false; + case OT_WAITING: + return false; + case OT_LEAVESTATION: if (v->type != VEH_AIRCRAFT) return false; break; diff --git a/src/order_gui.cpp b/src/order_gui.cpp index d4feae35ca..e686aef725 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -312,6 +312,13 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int SetDParam(5, (order->GetDepotActionType() & ODATFB_HALT) ? STR_ORDER_REFIT_STOP_ORDER : STR_ORDER_REFIT_ORDER); SetDParam(6, CargoSpec::Get(order->GetRefitCargo())->name); } + + if (timetable) { + if (order->GetWaitTime() > 0) { + SetDParam(5, order->IsWaitTimetabled() ? STR_TIMETABLE_STAY_FOR : STR_TIMETABLE_STAY_FOR_ESTIMATED); + SetTimetableParams(6, 7, order->GetWaitTime()); + } + } break; case OT_GOTO_WAYPOINT: diff --git a/src/order_type.h b/src/order_type.h index d3a771ce8b..dba61c918c 100644 --- a/src/order_type.h +++ b/src/order_type.h @@ -45,6 +45,7 @@ enum OrderType { OT_GOTO_WAYPOINT = 6, OT_CONDITIONAL = 7, OT_IMPLICIT = 8, + OT_WAITING = 9, OT_END }; diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index b3310af107..8021cce0c0 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -1531,6 +1531,9 @@ static bool RoadVehController(RoadVehicle *v) if (v->current_order.IsType(OT_LOADING)) return true; + v->HandleWaiting(false); + if (v->current_order.IsType(OT_WAITING)) return true; + if (v->IsInDepot() && RoadVehLeaveDepot(v, true)) return true; v->ShowVisualEffect(); diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 4fcda7c270..a868863bf2 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -316,6 +316,11 @@ static bool CheckShipLeaveDepot(Ship *v) { if (!v->IsChainInDepot()) return false; + if (v->current_order.IsWaitTimetabled()) + v->HandleWaiting(false); + if (v->current_order.IsType(OT_WAITING)) + return true; + /* We are leaving a depot, but have to go to the exact same one; re-enter */ if (v->current_order.IsType(OT_GOTO_DEPOT) && IsShipDepotTile(v->tile) && GetDepotIndex(v->tile) == v->current_order.GetDestination()) { diff --git a/src/timetable_cmd.cpp b/src/timetable_cmd.cpp index c6eaf3da81..42566c376f 100644 --- a/src/timetable_cmd.cpp +++ b/src/timetable_cmd.cpp @@ -143,6 +143,9 @@ CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, u if (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) return_cmd_error(STR_ERROR_TIMETABLE_NOT_STOPPING_HERE); break; + case OT_GOTO_DEPOT: + break; + case OT_CONDITIONAL: break; diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp index ffea9a8642..f69e151ab3 100644 --- a/src/timetable_gui.cpp +++ b/src/timetable_gui.cpp @@ -181,7 +181,7 @@ struct TimetableWindow : Window { { assert(HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)); - bool travelling = (!v->current_order.IsType(OT_LOADING) || v->current_order.GetNonStopType() == ONSF_STOP_EVERYWHERE); + bool travelling = (!(v->current_order.IsType(OT_LOADING) || v->current_order.IsType(OT_WAITING)) || v->current_order.GetNonStopType() == ONSF_STOP_EVERYWHERE); Ticks start_time = _date_fract - v->current_order_time; FillTimetableArrivalDepartureTable(v, v->cur_real_order_index % v->GetNumOrders(), travelling, table, start_time); @@ -310,7 +310,7 @@ struct TimetableWindow : Window { if (selected % 2 == 1) { disable = order != NULL && (order->IsType(OT_CONDITIONAL) || order->IsType(OT_IMPLICIT)); } else { - disable = order == NULL || ((!order->IsType(OT_GOTO_STATION) || (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) && !order->IsType(OT_CONDITIONAL)); + disable = order == NULL || ((!(order->IsType(OT_GOTO_STATION) || (order->IsType(OT_GOTO_DEPOT) && !(order->GetDepotActionType() & ODATFB_HALT))) || (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) && !order->IsType(OT_CONDITIONAL)); } } bool disable_speed = disable || selected % 2 != 1 || v->type == VEH_AIRCRAFT; diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 30ec1143de..e9e8bc4089 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -2131,6 +2131,11 @@ static bool CheckTrainStayInDepot(Train *v) return true; } + if (v->current_order.IsWaitTimetabled()) + v->HandleWaiting(false); + if (v->current_order.IsType(OT_WAITING)) + return true; + SigSegState seg_state; if (v->force_proceed == TFP_NONE) { diff --git a/src/vehicle.cpp b/src/vehicle.cpp index e7c26aa50d..6b353d8b6a 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1437,12 +1437,21 @@ void VehicleEnterDepot(Vehicle *v) } } + /* Handle the ODTFB_PART_OF_ORDERS case. If there is a timetabled wait time, hold the train, otherwise skip to the next order. + Note that if there is a only a travel_time, but no wait_time defined for the order, and the train arrives to the depot sooner as scheduled, + he doesn't wait in it, as it would in stations. Thus, the original behaviour is maintained if there's no defined wait_time.*/ if (v->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) { - /* Part of orders */ v->DeleteUnreachedImplicitOrders(); UpdateVehicleTimetable(v, true); - v->IncrementImplicitOrderIndex(); + if (v->current_order.IsWaitTimetabled()) { + v->current_order.MakeWaiting(); + v->current_order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION); + return; + } else { + v->IncrementImplicitOrderIndex(); + } } + if (v->current_order.GetDepotActionType() & ODATFB_HALT) { /* Vehicles are always stopped on entering depots. Do not restart this one. */ _vehicles_to_autoreplace[v] = false; @@ -2167,6 +2176,33 @@ void Vehicle::HandleLoading(bool mode) this->IncrementImplicitOrderIndex(); } +/** + * Handle the waiting time everywhere else as in stations (basically in depot but, eventually, also elsewhere ?) + * Function is called when order's wait_time is defined. + * @param stop_waiting should we stop waiting (or definitely avoid) even if there is still time left to wait ? + */ +void Vehicle::HandleWaiting(bool stop_waiting) +{ + switch (this->current_order.GetType()) { + case OT_WAITING: { + uint wait_time = max(this->current_order.GetTimetabledWait() - this->lateness_counter, 0); + /* Vehicles holds on until waiting Timetabled time expires. */ + if (!stop_waiting && this->current_order_time < wait_time) { + return; + } + + /* When wait_time is expired, we move on. */ + UpdateVehicleTimetable(this, false); + this->IncrementImplicitOrderIndex(); + this->current_order.MakeDummy(); + + break; + } + + default: return; + } +} + /** * Get a map of cargoes and free capacities in the consist. * @param capacities Map to be filled with cargoes and capacities. diff --git a/src/vehicle_base.h b/src/vehicle_base.h index 261b8ed035..004132718e 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -279,6 +279,8 @@ public: void HandleLoading(bool mode = false); + void HandleWaiting(bool stop_waiting = false); + void GetConsistFreeCapacities(SmallMap &capacities) const; uint GetConsistTotalCapacity() const;