Fix incorrect handling of timetable operations on counter and release slot orders

See: #485
This commit is contained in:
Jonathan G Rennison
2023-02-18 12:34:16 +00:00
parent bf5a3e259a
commit 39d38ecf19
3 changed files with 25 additions and 6 deletions

View File

@@ -423,10 +423,21 @@ public:
* autofilled we can be sure that any non-zero values for their wait_time and travel_time are * 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). */ * 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? */ /** 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? */ /** 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. */ /** 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; } 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). */ /** Set if the wait time is explicitly timetabled (unless the order is conditional). */
inline void SetWaitTimetabled(bool timetabled) inline void SetWaitTimetabled(bool timetabled)
{ {
if (this->HasNoTimetableTimes()) return;
if (this->IsType(OT_CONDITIONAL)) { if (this->IsType(OT_CONDITIONAL)) {
SB(this->GetXFlagsRef(), 0, 1, timetabled ? 1 : 0); SB(this->GetXFlagsRef(), 0, 1, timetabled ? 1 : 0);
} else { } else {
@@ -455,7 +467,10 @@ public:
} }
/** Set if the travel time is explicitly timetabled (unless the order is conditional). */ /** 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. * Set the time in ticks to wait at the destination.

View File

@@ -37,6 +37,8 @@ static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint32 val,
{ {
Order *order = v->GetOrder(order_number); Order *order = v->GetOrder(order_number);
assert(order != nullptr); assert(order != nullptr);
if (order->HasNoTimetableTimes()) return;
int total_delta = 0; int total_delta = 0;
int timetable_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); VehicleOrderID order_number = GB(p3, 0, 16);
Order *order = v->GetOrder(order_number); 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<ModifyTimetableFlags, 28, 3>(p1); ModifyTimetableFlags mtf = Extract<ModifyTimetableFlags, 28, 3>(p1);
if (mtf >= MTF_END) return CMD_ERROR; 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) 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)) { 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 // non-station orders are permitted to have 0 wait times
return false; return false;

View File

@@ -550,7 +550,7 @@ struct TimetableWindow : GeneralVehicleWindow {
const Order *order = v->GetOrder(((selected + 1) / 2) % v->GetNumOrders()); const Order *order = v->GetOrder(((selected + 1) / 2) % v->GetNumOrders());
if (selected % 2 != 0) { if (selected % 2 != 0) {
/* Travel time */ /* 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; disable_time = disable;
wait_lockable = !disable; wait_lockable = !disable;
wait_locked = wait_lockable && order->IsTravelFixed(); wait_locked = wait_lockable && order->IsTravelFixed();
@@ -699,7 +699,7 @@ struct TimetableWindow : GeneralVehicleWindow {
} else { } else {
StringID string; StringID string;
TextColour colour = (i == selected) ? TC_WHITE : TC_BLACK; 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; string = STR_TIMETABLE_NO_TRAVEL;
} else if (order->IsType(OT_IMPLICIT)) { } else if (order->IsType(OT_IMPLICIT)) {
string = STR_TIMETABLE_NOT_TIMETABLEABLE; string = STR_TIMETABLE_NOT_TIMETABLEABLE;