diff --git a/src/command.cpp b/src/command.cpp index c19cd48830..59def71475 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -298,6 +298,7 @@ CommandProc CmdScheduledDispatchRemoveSchedule; CommandProc CmdScheduledDispatchRenameSchedule; CommandProc CmdScheduledDispatchDuplicateSchedule; CommandProc CmdScheduledDispatchAppendVehicleSchedules; +CommandProc CmdScheduledDispatchAdjust; CommandProc CmdAddPlan; CommandProcEx CmdAddPlanLine; @@ -557,6 +558,7 @@ static const Command _command_proc_table[] = { DEF_CMD(CmdScheduledDispatchRenameSchedule, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_SCHEDULED_DISPATCH_RENAME_SCHEDULE DEF_CMD(CmdScheduledDispatchDuplicateSchedule, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_SCHEDULED_DISPATCH_DUPLICATE_SCHEDULE DEF_CMD(CmdScheduledDispatchAppendVehicleSchedules, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_SCHEDULED_DISPATCH_APPEND_VEHICLE_SCHEDULE + DEF_CMD(CmdScheduledDispatchAdjust, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_SCHEDULED_DISPATCH_ADJUST DEF_CMD(CmdAddPlan, CMD_NO_TEST, CMDT_OTHER_MANAGEMENT ), // CMD_ADD_PLAN DEF_CMD(CmdAddPlanLine, CMD_NO_TEST, CMDT_OTHER_MANAGEMENT ), // CMD_ADD_PLAN_LINE diff --git a/src/command_type.h b/src/command_type.h index a1b7fdb77f..5850800837 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -520,6 +520,7 @@ enum Commands { CMD_SCHEDULED_DISPATCH_RENAME_SCHEDULE, ///< scheduled dispatch rename schedule CMD_SCHEDULED_DISPATCH_DUPLICATE_SCHEDULE, ///< scheduled dispatch duplicate schedule CMD_SCHEDULED_DISPATCH_APPEND_VEHICLE_SCHEDULE, ///< scheduled dispatch append schedules from another vehicle + CMD_SCHEDULED_DISPATCH_ADJUST, ///< scheduled dispatch adjust time offsets in schedule CMD_ADD_PLAN, CMD_ADD_PLAN_LINE, diff --git a/src/lang/extra/english.txt b/src/lang/extra/english.txt index 87ab841440..74ea637be3 100644 --- a/src/lang/extra/english.txt +++ b/src/lang/extra/english.txt @@ -2005,6 +2005,11 @@ STR_SCHDISPATCH_DELAY_TOOLTIP :{BLACK}Set maxi STR_SCHDISPATCH_DELAY_CAPTION_MINUTE :{BLACK}Delay (minutes) STR_SCHDISPATCH_DELAY_CAPTION_DAY :{BLACK}Delay (days) STR_SCHDISPATCH_DELAY_CAPTION_TICKS :{BLACK}Delay (ticks) +STR_SCHDISPATCH_ADJUST :{BLACK}Adjust Departure Slots +STR_SCHDISPATCH_ADJUST_TOOLTIP :{BLACK}Adjust all departure slots in this schedule. +STR_SCHDISPATCH_ADJUST_CAPTION_MINUTE :{BLACK}Adjustment to add (minutes) +STR_SCHDISPATCH_ADJUST_CAPTION_DAY :{BLACK}Adjustment to add (days) +STR_SCHDISPATCH_ADJUST_CAPTION_TICKS :{BLACK}Adjustment to add (ticks) STR_SCHDISPATCH_RESET_LAST_DISPATCH :{BLACK}Reset Last Dispatched STR_SCHDISPATCH_RESET_LAST_DISPATCH_TOOLTIP :{BLACK}Reset when a vehicle was last dispatched from the schedule. STR_SCHDISPATCH_CLEAR :{BLACK}Clear Departure Slots @@ -2054,6 +2059,7 @@ STR_SCHDISPATCH_QUERY_REMOVE_SCHEDULE_CAPTION :{WHITE}Delete S STR_SCHDISPATCH_QUERY_REMOVE_SCHEDULE_TEXT :{WHITE}Are you sure you want to delete this schedule (containing {NUM} departure slot{P "" s})? STR_ERROR_SCHDISPATCH_TRIED_TO_ADD_TOO_MANY_SLOTS :{WHITE}Tried to add too many departure slots at once +STR_ERROR_SCHDISPATCH_ADJUSTMENT_TOO_LARGE :{WHITE}Departure slot adjustment is too large # Modifier key toggle window STR_MODIFIER_KEY_TOGGLE_CAPTION :{WHITE}Modifier keys diff --git a/src/order_base.h b/src/order_base.h index 3fc1c005bd..d6d219d333 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -723,6 +723,7 @@ public: void SetScheduledDispatch(std::vector dispatch_list); void AddScheduledDispatch(uint32 offset); void RemoveScheduledDispatch(uint32 offset); + void AdjustScheduledDispatch(int32 adjust); void ClearScheduledDispatch() { this->scheduled_dispatch.clear(); } bool UpdateScheduledDispatchToDate(DateTicksScaled now); void UpdateScheduledDispatch(const Vehicle *v); diff --git a/src/schdispatch_cmd.cpp b/src/schdispatch_cmd.cpp index b6a8547ddc..450b0281e8 100644 --- a/src/schdispatch_cmd.cpp +++ b/src/schdispatch_cmd.cpp @@ -530,6 +530,45 @@ CommandCost CmdScheduledDispatchAppendVehicleSchedules(TileIndex tile, DoCommand return CommandCost(); } +/** + * Adjust scheduled dispatch time offsets + * + * @param tile Not used. + * @param flags Operation to perform. + * @param p1 Vehicle index + * @param p2 Signed adjustment + * @param text name + * @return the cost of this operation or an error + */ +CommandCost CmdScheduledDispatchAdjust(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +{ + VehicleID veh = GB(p1, 0, 20); + uint schedule_index = GB(p1, 20, 12); + int32 adjustment = p2; + + Vehicle *v = Vehicle::GetIfValid(veh); + if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR; + + CommandCost ret = CheckOwnership(v->owner); + if (ret.Failed()) return ret; + + if (v->orders == nullptr) return CMD_ERROR; + if (v->orders->GetScheduledDispatchScheduleCount() >= 4096) return CMD_ERROR; + + if (schedule_index >= v->orders->GetScheduledDispatchScheduleCount()) return CMD_ERROR; + + DispatchSchedule &ds = v->orders->GetDispatchScheduleByIndex(schedule_index); + if (abs(adjustment) >= (int)ds.GetScheduledDispatchDuration()) return CommandCost(STR_ERROR_SCHDISPATCH_ADJUSTMENT_TOO_LARGE); + + if (flags & DC_EXEC) { + ds.AdjustScheduledDispatch(adjustment); + ds.UpdateScheduledDispatch(nullptr); + SetTimetableWindowsDirty(v, true); + } + + return CommandCost(); +} + /** * Set scheduled dispatch slot list. * @param dispatch_list The offset time list, must be correctly sorted. @@ -570,6 +609,21 @@ void DispatchSchedule::RemoveScheduledDispatch(uint32 offset) this->scheduled_dispatch.erase(erase_position); } +/** + * Adjust all scheduled dispatch slots by time adjustment. + * @param adjust The time adjustment to add to each time slot. + */ +void DispatchSchedule::AdjustScheduledDispatch(int32 adjust) +{ + for (uint32 &time : this->scheduled_dispatch) { + int32 t = (int32)time + adjust; + if (t < 0) t += GetScheduledDispatchDuration(); + if (t >= (int32)GetScheduledDispatchDuration()) t -= (int32)GetScheduledDispatchDuration(); + time = (uint32)t; + } + std::sort(this->scheduled_dispatch.begin(), this->scheduled_dispatch.end()); +} + bool DispatchSchedule::UpdateScheduledDispatchToDate(DateTicksScaled now) { bool update_windows = false; diff --git a/src/schdispatch_gui.cpp b/src/schdispatch_gui.cpp index 6d1998a59f..77718f0247 100644 --- a/src/schdispatch_gui.cpp +++ b/src/schdispatch_gui.cpp @@ -53,8 +53,9 @@ enum SchdispatchWidgets { WID_SCHDISPATCH_ADD, ///< Add Departure Time button WID_SCHDISPATCH_SET_DURATION, ///< Duration button WID_SCHDISPATCH_SET_START_DATE, ///< Start Date button - WID_SCHDISPATCH_SET_DELAY, ///< Delat button + WID_SCHDISPATCH_SET_DELAY, ///< Delay button WID_SCHDISPATCH_MANAGEMENT, ///< Management button + WID_SCHDISPATCH_ADJUST, ///< Adjust departure times }; /** @@ -338,6 +339,7 @@ struct SchdispatchWindow : GeneralVehicleWindow { this->SetWidgetDisabledState(WID_SCHDISPATCH_SET_START_DATE, disabled); this->SetWidgetDisabledState(WID_SCHDISPATCH_SET_DELAY, disabled); this->SetWidgetDisabledState(WID_SCHDISPATCH_MANAGEMENT, disabled); + this->SetWidgetDisabledState(WID_SCHDISPATCH_ADJUST, disabled || this->GetSelectedSchedule().GetScheduledDispatch().empty()); this->vscroll->SetCount(CeilDiv(this->item_count, this->num_columns)); @@ -764,6 +766,12 @@ struct SchdispatchWindow : GeneralVehicleWindow { ShowQueryString(STR_JUST_RAW_STRING, STR_SCHDISPATCH_RENAME_SCHEDULE_CAPTION, MAX_LENGTH_VEHICLE_NAME_CHARS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT | QSF_LEN_IN_CHARS); break; + + case WID_SCHDISPATCH_ADJUST: + if (!this->IsScheduleSelected()) break; + SetDParam(0, 0); + ShowQueryString(STR_JUST_INT, STR_SCHDISPATCH_ADJUST_CAPTION_MINUTE + this->GetQueryStringCaptionOffset(), 31, this, CS_NUMERAL_SIGNED, QSF_NONE); + break; } this->SetDirty(); @@ -908,6 +916,18 @@ struct SchdispatchWindow : GeneralVehicleWindow { DoCommandP(0, v->index | (this->schedule_index << 20), 0, CMD_SCHEDULED_DISPATCH_RENAME_SCHEDULE | CMD_MSG(STR_ERROR_CAN_T_RENAME_SCHEDULE), nullptr, str); break; } + + case WID_SCHDISPATCH_ADJUST: { + if (!this->IsScheduleSelected()) break; + int32 val = StrEmpty(str) ? 0 : strtol(str, nullptr, 10); + + if (val != 0) { + if (!_settings_client.gui.timetable_in_ticks) val *= DATE_UNIT_SIZE; + + DoCommandP(0, v->index | (this->schedule_index << 20), val, CMD_SCHEDULED_DISPATCH_ADJUST | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE)); + } + break; + } } this->SetDirty(); @@ -998,10 +1018,10 @@ static const NWidgetPart _nested_schdispatch_widgets[] = { NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), NWidget(NWID_VERTICAL, NC_EQUALSIZE), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCHDISPATCH_ADD), SetDataTip(STR_SCHDISPATCH_ADD, STR_SCHDISPATCH_ADD_TOOLTIP), SetFill(1, 1), SetResize(1, 0), - NWidget(NWID_SPACER), SetFill(1, 1), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCHDISPATCH_ADJUST), SetDataTip(STR_SCHDISPATCH_ADJUST, STR_SCHDISPATCH_ADJUST_TOOLTIP), SetFill(1, 1), SetResize(1, 0), EndContainer(), NWidget(NWID_VERTICAL, NC_EQUALSIZE), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCHDISPATCH_SET_DURATION), SetDataTip(STR_SCHDISPATCH_DURATION, STR_SCHDISPATCH_DURATION_TOOLTIP), SetFill(1, 1), SetResize(1, 0), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCHDISPATCH_SET_DURATION), SetDataTip(STR_SCHDISPATCH_DURATION, STR_SCHDISPATCH_DURATION_TOOLTIP), SetFill(1, 1), SetResize(1, 0), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCHDISPATCH_SET_START_DATE), SetDataTip(STR_SCHDISPATCH_START, STR_SCHDISPATCH_START_TOOLTIP), SetFill(1, 1), SetResize(1, 0), EndContainer(), NWidget(NWID_VERTICAL, NC_EQUALSIZE),