diff --git a/src/lang/extra/english.txt b/src/lang/extra/english.txt index e1fbbe8c99..4ca1963599 100644 --- a/src/lang/extra/english.txt +++ b/src/lang/extra/english.txt @@ -2105,6 +2105,7 @@ STR_SCHDISPATCH_RENAME_SCHEDULE_CAPTION :{WHITE}Name sch STR_ERROR_CAN_T_RENAME_SCHEDULE :{WHITE}Can't name schedule... STR_SCHDISPATCH_MOVE_SCHEDULE :{BLACK}Change position of current schedule in schedule list +STR_SCHDISPATCH_SUMMARY_NO_LAST_DEPARTURE :{BLACK}No previous departures. STR_SCHDISPATCH_SUMMARY_LAST_DEPARTURE_PAST :{BLACK}Last departure at {DATE_WALLCLOCK_TINY}. STR_SCHDISPATCH_SUMMARY_LAST_DEPARTURE_FUTURE :{BLACK}Last departure has not left yet, it will depart at {DATE_WALLCLOCK_TINY}. STR_SCHDISPATCH_SUMMARY_L1 :{BLACK}This schedule requires {COMMA} vehicle{P "" s}. diff --git a/src/order_base.h b/src/order_base.h index c449f0df77..546837e31d 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -723,7 +723,7 @@ private: uint32_t scheduled_dispatch_duration = 0; ///< Scheduled dispatch duration DateTicksScaled scheduled_dispatch_start_tick = -1; ///< Scheduled dispatch start tick /// this counts to (DAY_TICK * _settings_game.economy.day_length_factor) - int32_t scheduled_dispatch_last_dispatch = 0; ///< Last vehicle dispatched offset + int32_t scheduled_dispatch_last_dispatch = INVALID_SCHEDULED_DISPATCH_OFFSET; ///< Last vehicle dispatched offset int32_t scheduled_dispatch_max_delay = 0; ///< Maximum allowed delay uint8_t scheduled_dispatch_flags = 0; ///< Flags diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 88e15a0c54..7af5a754fa 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -3053,6 +3053,10 @@ bool EvaluateDispatchSlotConditionalOrder(const Order *order, const Vehicle *v, int32_t offset; if (order->GetConditionValue() & 2) { int32_t last = sched.GetScheduledDispatchLastDispatch(); + if (last == INVALID_SCHEDULED_DISPATCH_OFFSET) { + /* No last dispatched */ + return OrderConditionCompare(order->GetConditionComparator(), 0, 0); + } if (last < 0) { last += sched.GetScheduledDispatchDuration() * (1 + (-last / sched.GetScheduledDispatchDuration())); } @@ -3069,7 +3073,7 @@ bool EvaluateDispatchSlotConditionalOrder(const Order *order, const Vehicle *v, value = (offset == (int)sched.GetScheduledDispatch().front()); } - return OrderConditionCompare(order->GetConditionComparator(), value, 0); + return OrderConditionCompare(order->GetConditionComparator(), value ? 1 : 0, 0); } static std::vector _pco_deferred_slot_acquires; diff --git a/src/order_type.h b/src/order_type.h index 37e2003e98..ca2acd7d91 100644 --- a/src/order_type.h +++ b/src/order_type.h @@ -32,6 +32,9 @@ static const OrderID INVALID_ORDER = 0xFFFFFF; */ static const uint IMPLICIT_ORDER_ONLY_CAP = 32; +/** Invalid scheduled dispatch offset from current schedule */ +static const int32_t INVALID_SCHEDULED_DISPATCH_OFFSET = INT32_MIN; + /** Order types. It needs to be 8bits, because we save and load it as such */ enum OrderType : byte { OT_BEGIN = 0, diff --git a/src/schdispatch_cmd.cpp b/src/schdispatch_cmd.cpp index d41a4dbda6..7441ec1d7f 100644 --- a/src/schdispatch_cmd.cpp +++ b/src/schdispatch_cmd.cpp @@ -307,7 +307,7 @@ CommandCost CmdScheduledDispatchResetLastDispatch(TileIndex tile, DoCommandFlag if (schedule_index >= v->orders->GetScheduledDispatchScheduleCount()) return CMD_ERROR; if (flags & DC_EXEC) { - v->orders->GetDispatchScheduleByIndex(schedule_index).SetScheduledDispatchLastDispatch(0); + v->orders->GetDispatchScheduleByIndex(schedule_index).SetScheduledDispatchLastDispatch(INVALID_SCHEDULED_DISPATCH_OFFSET); SetTimetableWindowsDirty(v, STWDF_SCHEDULED_DISPATCH); } @@ -506,7 +506,7 @@ CommandCost CmdScheduledDispatchDuplicateSchedule(TileIndex tile, DoCommandFlag if (flags & DC_EXEC) { DispatchSchedule &ds = v->orders->GetScheduledDispatchScheduleSet().emplace_back(v->orders->GetDispatchScheduleByIndex(schedule_index)); - ds.SetScheduledDispatchLastDispatch(0); + ds.SetScheduledDispatchLastDispatch(INVALID_SCHEDULED_DISPATCH_OFFSET); ds.UpdateScheduledDispatch(nullptr); SetTimetableWindowsDirty(v, STWDF_SCHEDULED_DISPATCH); } @@ -545,7 +545,7 @@ CommandCost CmdScheduledDispatchAppendVehicleSchedules(TileIndex tile, DoCommand if (flags & DC_EXEC) { for (uint i = 0; i < v2->orders->GetScheduledDispatchScheduleCount(); i++) { DispatchSchedule &ds = v1->orders->GetScheduledDispatchScheduleSet().emplace_back(v2->orders->GetDispatchScheduleByIndex(i)); - ds.SetScheduledDispatchLastDispatch(0); + ds.SetScheduledDispatchLastDispatch(INVALID_SCHEDULED_DISPATCH_OFFSET); ds.UpdateScheduledDispatch(nullptr); } SetTimetableWindowsDirty(v1, STWDF_SCHEDULED_DISPATCH); @@ -721,16 +721,20 @@ bool DispatchSchedule::UpdateScheduledDispatchToDate(DateTicksScaled now) /* Most of the time this loop does not run. It makes sure start date in in past */ while (this->GetScheduledDispatchStartTick() > now) { OverflowSafeInt32 last_dispatch = this->scheduled_dispatch_last_dispatch; - last_dispatch += this->GetScheduledDispatchDuration(); - this->scheduled_dispatch_last_dispatch = last_dispatch; + if (last_dispatch != INVALID_SCHEDULED_DISPATCH_OFFSET) { + last_dispatch += this->GetScheduledDispatchDuration(); + this->scheduled_dispatch_last_dispatch = last_dispatch; + } this->SetScheduledDispatchStartTick(this->GetScheduledDispatchStartTick() - this->GetScheduledDispatchDuration()); update_windows = true; } /* Most of the time this loop runs once. It makes sure the start date is as close to current time as possible. */ while (this->GetScheduledDispatchStartTick() + this->GetScheduledDispatchDuration() <= now) { OverflowSafeInt32 last_dispatch = this->scheduled_dispatch_last_dispatch; - last_dispatch -= this->GetScheduledDispatchDuration(); - this->scheduled_dispatch_last_dispatch = last_dispatch; + if (last_dispatch != INVALID_SCHEDULED_DISPATCH_OFFSET) { + last_dispatch -= this->GetScheduledDispatchDuration(); + this->scheduled_dispatch_last_dispatch = last_dispatch; + } this->SetScheduledDispatchStartTick(this->GetScheduledDispatchStartTick() + this->GetScheduledDispatchDuration()); update_windows = true; } diff --git a/src/schdispatch_gui.cpp b/src/schdispatch_gui.cpp index 257262caf5..5a752999c0 100644 --- a/src/schdispatch_gui.cpp +++ b/src/schdispatch_gui.cpp @@ -585,7 +585,9 @@ struct SchdispatchWindow : GeneralVehicleWindow { const DateTicksScaled last_departure = ds.GetScheduledDispatchStartTick() + ds.GetScheduledDispatchLastDispatch(); StringID str; - if (_scaled_date_ticks < last_departure) { + if (last_departure == INVALID_SCHEDULED_DISPATCH_OFFSET) { + str = STR_SCHDISPATCH_SUMMARY_NO_LAST_DEPARTURE; + } else if (_scaled_date_ticks < last_departure) { str = STR_SCHDISPATCH_SUMMARY_LAST_DEPARTURE_FUTURE; set_next_departure_update(last_departure); } else { @@ -595,7 +597,9 @@ struct SchdispatchWindow : GeneralVehicleWindow { DrawString(ir.left, ir.right, y, str); y += GetCharacterHeight(FS_NORMAL); - departure_time_warnings(last_departure); + if (last_departure != INVALID_SCHEDULED_DISPATCH_OFFSET) { + departure_time_warnings(last_departure); + } const DateTicksScaled next_departure = GetScheduledDispatchTime(ds, _scaled_date_ticks); set_next_departure_update(next_departure + ds.GetScheduledDispatchDelay()); diff --git a/src/timetable_cmd.cpp b/src/timetable_cmd.cpp index 4eef2d3c35..f5975ce7bd 100644 --- a/src/timetable_cmd.cpp +++ b/src/timetable_cmd.cpp @@ -789,12 +789,22 @@ void UpdateSeparationOrder(Vehicle *v_start) DateTicksScaled GetScheduledDispatchTime(const DispatchSchedule &ds, DateTicksScaled leave_time) { - DateTicksScaled first_slot = -1; - const DateTicksScaled begin_time = ds.GetScheduledDispatchStartTick() - (ds.GetScheduledDispatchReuseSlots() ? ds.GetScheduledDispatchDuration() : 0); - const int32_t last_dispatched_offset = ds.GetScheduledDispatchReuseSlots() ? -1 : ds.GetScheduledDispatchLastDispatch(); - const uint32_t dispatch_duration = ds.GetScheduledDispatchDuration(); - const int32_t max_delay = ds.GetScheduledDispatchDelay(); - const DateTicksScaled minimum = leave_time - max_delay; + const uint32_t dispatch_duration = ds.GetScheduledDispatchDuration(); + const int32_t max_delay = ds.GetScheduledDispatchDelay(); + const DateTicksScaled minimum = leave_time - max_delay; + DateTicksScaled begin_time = ds.GetScheduledDispatchStartTick(); + if (ds.GetScheduledDispatchReuseSlots()) { + begin_time -= dispatch_duration; + } + + int32_t last_dispatched_offset; + if (ds.GetScheduledDispatchLastDispatch() == INVALID_SCHEDULED_DISPATCH_OFFSET || ds.GetScheduledDispatchReuseSlots()) { + last_dispatched_offset = -1; + } else { + last_dispatched_offset = ds.GetScheduledDispatchLastDispatch(); + } + + DateTicksScaled first_slot = -1; /* Find next available slots */ for (auto current_offset : ds.GetScheduledDispatch()) {