From 39d38ecf195c3a2df4f92ce14b60a7d2bd73952c Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sat, 18 Feb 2023 12:34:16 +0000 Subject: [PATCH] Fix incorrect handling of timetable operations on counter and release slot orders See: #485 --- src/order_base.h | 21 ++++++++++++++++++--- src/timetable_cmd.cpp | 6 +++++- src/timetable_gui.cpp | 4 ++-- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/order_base.h b/src/order_base.h index 067dd6949a..17913620e6 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -423,10 +423,21 @@ public: * autofilled we can be sure that any non-zero values for their wait_time and travel_time are * explicitly set (but travel_time is actually unused for conditionals). */ + /* Does this order not have any associated travel or wait times */ + inline bool HasNoTimetableTimes() const { return this->IsType(OT_COUNTER) || this->IsType(OT_RELEASE_SLOT); } + /** Does this order have an explicit wait time set? */ - inline bool IsWaitTimetabled() const { return this->IsType(OT_CONDITIONAL) ? HasBit(this->GetXFlags(), 0) : HasBit(this->flags, 3); } + inline bool IsWaitTimetabled() const + { + if (this->HasNoTimetableTimes()) return true; + return this->IsType(OT_CONDITIONAL) ? HasBit(this->GetXFlags(), 0) : HasBit(this->flags, 3); + } /** Does this order have an explicit travel time set? */ - inline bool IsTravelTimetabled() const { return this->IsType(OT_CONDITIONAL) ? this->travel_time > 0 : HasBit(this->flags, 7); } + inline bool IsTravelTimetabled() const + { + if (this->HasNoTimetableTimes()) return true; + return this->IsType(OT_CONDITIONAL) ? this->travel_time > 0 : HasBit(this->flags, 7); + } /** Get the time in ticks a vehicle should wait at the destination or 0 if it's not timetabled. */ inline TimetableTicks GetTimetabledWait() const { return this->IsWaitTimetabled() ? this->wait_time : 0; } @@ -447,6 +458,7 @@ public: /** Set if the wait time is explicitly timetabled (unless the order is conditional). */ inline void SetWaitTimetabled(bool timetabled) { + if (this->HasNoTimetableTimes()) return; if (this->IsType(OT_CONDITIONAL)) { SB(this->GetXFlagsRef(), 0, 1, timetabled ? 1 : 0); } else { @@ -455,7 +467,10 @@ public: } /** Set if the travel time is explicitly timetabled (unless the order is conditional). */ - inline void SetTravelTimetabled(bool timetabled) { if (!this->IsType(OT_CONDITIONAL)) SB(this->flags, 7, 1, timetabled ? 1 : 0); } + inline void SetTravelTimetabled(bool timetabled) + { + if (!this->IsType(OT_CONDITIONAL) && !this->HasNoTimetableTimes()) SB(this->flags, 7, 1, timetabled ? 1 : 0); + } /** * Set the time in ticks to wait at the destination. diff --git a/src/timetable_cmd.cpp b/src/timetable_cmd.cpp index d350f11a33..27cff41982 100644 --- a/src/timetable_cmd.cpp +++ b/src/timetable_cmd.cpp @@ -37,6 +37,8 @@ static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint32 val, { Order *order = v->GetOrder(order_number); assert(order != nullptr); + if (order->HasNoTimetableTimes()) return; + int total_delta = 0; int timetable_delta = 0; @@ -175,7 +177,7 @@ CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, u VehicleOrderID order_number = GB(p3, 0, 16); Order *order = v->GetOrder(order_number); - if (order == nullptr || order->IsType(OT_IMPLICIT)) return CMD_ERROR; + if (order == nullptr || order->IsType(OT_IMPLICIT) || order->HasNoTimetableTimes()) return CMD_ERROR; ModifyTimetableFlags mtf = Extract(p1); if (mtf >= MTF_END) return CMD_ERROR; @@ -661,6 +663,8 @@ CommandCost CmdTimetableSeparation(TileIndex tile, DoCommandFlag flags, uint32 p static inline bool IsOrderUsableForSeparation(const Order *order) { + if (order->HasNoTimetableTimes()) return true; + if (order->GetWaitTime() == 0 && order->IsType(OT_GOTO_STATION) && !(order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) { // non-station orders are permitted to have 0 wait times return false; diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp index 842aa677aa..93b8b5a61e 100644 --- a/src/timetable_gui.cpp +++ b/src/timetable_gui.cpp @@ -550,7 +550,7 @@ struct TimetableWindow : GeneralVehicleWindow { const Order *order = v->GetOrder(((selected + 1) / 2) % v->GetNumOrders()); if (selected % 2 != 0) { /* Travel time */ - disable = order != nullptr && (order->IsType(OT_CONDITIONAL) || order->IsType(OT_IMPLICIT)); + disable = order != nullptr && (order->IsType(OT_CONDITIONAL) || order->IsType(OT_IMPLICIT) || order->HasNoTimetableTimes()); disable_time = disable; wait_lockable = !disable; wait_locked = wait_lockable && order->IsTravelFixed(); @@ -699,7 +699,7 @@ struct TimetableWindow : GeneralVehicleWindow { } else { StringID string; TextColour colour = (i == selected) ? TC_WHITE : TC_BLACK; - if (order->IsType(OT_CONDITIONAL)) { + if (order->IsType(OT_CONDITIONAL) || order->HasNoTimetableTimes()) { string = STR_TIMETABLE_NO_TRAVEL; } else if (order->IsType(OT_IMPLICIT)) { string = STR_TIMETABLE_NOT_TIMETABLEABLE;