diff --git a/src/departures.cpp b/src/departures.cpp index ffc6570527..5a8cd23b37 100644 --- a/src/departures.cpp +++ b/src/departures.cpp @@ -106,6 +106,7 @@ static inline bool VehicleSetNextDepartureTime(DateTicks *previous_departure, ui /* Find next available slots */ for (auto current_offset : v->orders.list->GetScheduledDispatch()) { + if (current_offset >= dispatch_duration) continue; DateTicksScaled current_departure = begin_time + current_offset; while (current_departure <= earliest_departure) { current_departure += dispatch_duration; diff --git a/src/lang/english.txt b/src/lang/english.txt index c52fae2259..c1aac3e0c4 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -6224,6 +6224,8 @@ STR_SCHDISPATCH_SUMMARY_L2 :{BLACK}This sch STR_SCHDISPATCH_SUMMARY_L3 :{BLACK}Maximum delay of {STRING3} is allowed before the slot is skipped. STR_SCHDISPATCH_SUMMARY_NOT_ENABLED :{BLACK}This schedule is not active. +STR_SCHDISPATCH_SLOT_OUTSIDE_SCHEDULE :{BLACK}One or more departure slots are outside the schedule duration. + # Modifier key toggle window STR_MODIFIER_KEY_TOGGLE_CAPTION :{WHITE}Modifier keys STR_SHIFT_KEY_NAME :{BLACK}Shift diff --git a/src/schdispatch_gui.cpp b/src/schdispatch_gui.cpp index 0d55797259..14b45b3ee5 100644 --- a/src/schdispatch_gui.cpp +++ b/src/schdispatch_gui.cpp @@ -127,10 +127,12 @@ static int CalculateMaxRequiredVehicle(Ticks timetable_duration, uint32 schedule std::vector> indices; for (int i = 0; i < required_loop; i++) { for (uint32 offset : offsets) { + if (offset >= schedule_duration) continue; indices.push_back(std::make_pair(i * schedule_duration + offset, 1)); indices.push_back(std::make_pair(i * schedule_duration + offset + timetable_duration, -1)); } } + if (indices.empty()) return -1; std::sort(indices.begin(), indices.end()); int current_count = 0; int vehicle_count = 0; @@ -149,6 +151,7 @@ struct SchdispatchWindow : Window { uint item_count = 0; ///< Number of scheduled item bool last_departure_future; ///< True if last departure is currently displayed in the future + uint warning_count = 0; SchdispatchWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc), @@ -201,6 +204,10 @@ struct SchdispatchWindow : Window { case WID_SCHDISPATCH_SUMMARY_PANEL: size->height = WD_FRAMERECT_TOP + 4 * FONT_HEIGHT_NORMAL + WD_FRAMERECT_BOTTOM; + if (warning_count > 0) { + const Dimension warning_dimensions = GetSpriteSize(SPR_WARNING_SIGN); + size->height += warning_count * max(warning_dimensions.height, FONT_HEIGHT_NORMAL); + } break; } } @@ -373,6 +380,39 @@ struct SchdispatchWindow : Window { SetTimetableParams(0, v->orders.list->GetScheduledDispatchDelay()); DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_SCHDISPATCH_SUMMARY_L3); + y += FONT_HEIGHT_NORMAL; + + uint warnings = 0; + auto draw_warning = [&](StringID text) { + const Dimension warning_dimensions = GetSpriteSize(SPR_WARNING_SIGN); + int step_height = max(warning_dimensions.height, FONT_HEIGHT_NORMAL); + int left = r.left + WD_FRAMERECT_LEFT; + int right = r.right - WD_FRAMERECT_RIGHT; + const bool rtl = (_current_text_dir == TD_RTL); + DrawSprite(SPR_WARNING_SIGN, 0, rtl ? right - warning_dimensions.width - 5 : left + 5, y + (step_height - warning_dimensions.height) / 2); + if (rtl) { + right -= (warning_dimensions.width + 10); + } else { + left += (warning_dimensions.width + 10); + } + DrawString(left, right, y + (step_height - FONT_HEIGHT_NORMAL) / 2, text); + y += step_height; + warnings++; + }; + + uint32 duration = v->orders.list->GetScheduledDispatchDuration(); + for (uint32 slot : v->orders.list->GetScheduledDispatch()) { + if (slot >= duration) { + draw_warning(STR_SCHDISPATCH_SLOT_OUTSIDE_SCHEDULE); + break; + } + } + + if (warnings != this->warning_count) { + SchdispatchWindow *mutable_this = const_cast(this); + mutable_this->warning_count = warnings; + mutable_this->ReInit(); + } } break; diff --git a/src/timetable_cmd.cpp b/src/timetable_cmd.cpp index 983003c76a..d61cecdb80 100644 --- a/src/timetable_cmd.cpp +++ b/src/timetable_cmd.cpp @@ -737,6 +737,7 @@ static DateTicksScaled GetScheduledDispatchTime(Vehicle *v, int wait_offset) /* Find next available slots */ for (auto current_offset : v->orders.list->GetScheduledDispatch()) { + if (current_offset >= dispatch_duration) continue; if (int32(current_offset) <= last_dispatched_offset) { current_offset += dispatch_duration * ((last_dispatched_offset + dispatch_duration - current_offset) / dispatch_duration); }