Handle predictable conditional orders in timetable window
This commit is contained in:
@@ -2700,7 +2700,7 @@ static bool CheckForValidOrders(const Vehicle *v)
|
|||||||
/**
|
/**
|
||||||
* Compare the variable and value based on the given comparator.
|
* Compare the variable and value based on the given comparator.
|
||||||
*/
|
*/
|
||||||
static bool OrderConditionCompare(OrderConditionComparator occ, int variable, int value)
|
bool OrderConditionCompare(OrderConditionComparator occ, int variable, int value)
|
||||||
{
|
{
|
||||||
switch (occ) {
|
switch (occ) {
|
||||||
case OCC_EQUALS: return variable == value;
|
case OCC_EQUALS: return variable == value;
|
||||||
|
@@ -32,5 +32,6 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
|
|||||||
#define MAX_SERVINT_DAYS 800
|
#define MAX_SERVINT_DAYS 800
|
||||||
|
|
||||||
uint16 GetServiceIntervalClamped(uint interval, bool ispercent);
|
uint16 GetServiceIntervalClamped(uint interval, bool ispercent);
|
||||||
|
bool OrderConditionCompare(OrderConditionComparator occ, int variable, int value);
|
||||||
|
|
||||||
#endif /* ORDER_FUNC_H */
|
#endif /* ORDER_FUNC_H */
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
#include "viewport_func.h"
|
#include "viewport_func.h"
|
||||||
#include "schdispatch.h"
|
#include "schdispatch.h"
|
||||||
#include "vehiclelist.h"
|
#include "vehiclelist.h"
|
||||||
|
#include "tracerestrict.h"
|
||||||
|
|
||||||
#include "widgets/timetable_widget.h"
|
#include "widgets/timetable_widget.h"
|
||||||
|
|
||||||
@@ -36,6 +37,9 @@
|
|||||||
enum TimetableArrivalDepartureFlags {
|
enum TimetableArrivalDepartureFlags {
|
||||||
TADF_ARRIVAL_PREDICTED,
|
TADF_ARRIVAL_PREDICTED,
|
||||||
TADF_DEPARTURE_PREDICTED,
|
TADF_DEPARTURE_PREDICTED,
|
||||||
|
TADF_ARRIVAL_NO_OFFSET,
|
||||||
|
TADF_DEPARTURE_NO_OFFSET,
|
||||||
|
TADF_REACHED,
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Container for the arrival/departure dates of a vehicle */
|
/** Container for the arrival/departure dates of a vehicle */
|
||||||
@@ -131,22 +135,65 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool predicted = false;
|
bool predicted = false;
|
||||||
|
bool no_offset = false;
|
||||||
|
bool skip_travel = false;
|
||||||
|
|
||||||
/* Cyclically loop over all orders until we reach the current one again.
|
/* Cyclically loop over all orders until we reach the current one again.
|
||||||
* As we may start at the current order, do a post-checking loop */
|
* As we may start at the current order, do a post-checking loop */
|
||||||
do {
|
do {
|
||||||
|
if (HasBit(table[i].flags, TADF_REACHED)) break;
|
||||||
|
SetBit(table[i].flags, TADF_REACHED);
|
||||||
|
|
||||||
|
bool skip = order->IsType(OT_IMPLICIT);
|
||||||
|
|
||||||
|
if (order->IsType(OT_CONDITIONAL)) {
|
||||||
|
bool jump = false;
|
||||||
|
switch (order->GetConditionVariable()) {
|
||||||
|
case OCV_UNCONDITIONALLY: {
|
||||||
|
jump = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case OCV_TIME_DATE: {
|
||||||
|
predicted = true;
|
||||||
|
DateTicksScaled time = _scaled_date_ticks + sum;
|
||||||
|
if (!no_offset) time -= v->lateness_counter;
|
||||||
|
int value = GetTraceRestrictTimeDateValueFromDate(static_cast<TraceRestrictTimeDateValueField>(order->GetConditionValue()), time);
|
||||||
|
jump = OrderConditionCompare(order->GetConditionComparator(), value, order->GetXData());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (jump) {
|
||||||
|
if (!order->IsWaitTimetabled()) return;
|
||||||
|
sum += order->GetTimetabledWait();
|
||||||
|
i = order->GetConditionSkipToOrder();
|
||||||
|
order = v->GetOrder(i);
|
||||||
|
skip_travel = true;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
skip = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Automatic orders don't influence the overall timetable;
|
/* Automatic orders don't influence the overall timetable;
|
||||||
* they just add some untimetabled entries, but the time till
|
* they just add some untimetabled entries, but the time till
|
||||||
* the next non-implicit order can still be known. */
|
* the next non-implicit order can still be known. */
|
||||||
if (!order->IsType(OT_IMPLICIT)) {
|
if (!skip) {
|
||||||
if (travelling || i != start) {
|
if (travelling || i != start) {
|
||||||
|
if (!skip_travel) {
|
||||||
if (!CanDetermineTimeTaken(order, true)) return;
|
if (!CanDetermineTimeTaken(order, true)) return;
|
||||||
sum += order->GetTimetabledTravel();
|
sum += order->GetTimetabledTravel();
|
||||||
|
}
|
||||||
table[i].arrival = sum;
|
table[i].arrival = sum;
|
||||||
if (predicted) SetBit(table[i].flags, TADF_ARRIVAL_PREDICTED);
|
if (predicted) SetBit(table[i].flags, TADF_ARRIVAL_PREDICTED);
|
||||||
|
if (no_offset) SetBit(table[i].flags, TADF_ARRIVAL_NO_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (order->IsScheduledDispatchOrder(true) && !(i == start && !travelling)) {
|
if (order->IsScheduledDispatchOrder(true) && !(i == start && !travelling)) {
|
||||||
|
if (!no_offset) sum -= v->lateness_counter;
|
||||||
extern DateTicksScaled GetScheduledDispatchTime(const DispatchSchedule &ds, DateTicksScaled leave_time);
|
extern DateTicksScaled GetScheduledDispatchTime(const DispatchSchedule &ds, DateTicksScaled leave_time);
|
||||||
DispatchSchedule &ds = v->orders.list->GetDispatchScheduleByIndex(order->GetDispatchScheduleIndex());
|
DispatchSchedule &ds = v->orders.list->GetDispatchScheduleByIndex(order->GetDispatchScheduleIndex());
|
||||||
DispatchSchedule predicted_ds;
|
DispatchSchedule predicted_ds;
|
||||||
@@ -157,14 +204,18 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
|
|||||||
if (slot <= -1) return;
|
if (slot <= -1) return;
|
||||||
sum = slot - _scaled_date_ticks;
|
sum = slot - _scaled_date_ticks;
|
||||||
predicted = true;
|
predicted = true;
|
||||||
|
no_offset = true;
|
||||||
} else {
|
} else {
|
||||||
if (!CanDetermineTimeTaken(order, false)) return;
|
if (!CanDetermineTimeTaken(order, false)) return;
|
||||||
sum += order->GetTimetabledWait();
|
sum += order->GetTimetabledWait();
|
||||||
}
|
}
|
||||||
table[i].departure = sum;
|
table[i].departure = sum;
|
||||||
if (predicted) SetBit(table[i].flags, TADF_DEPARTURE_PREDICTED);
|
if (predicted) SetBit(table[i].flags, TADF_DEPARTURE_PREDICTED);
|
||||||
|
if (predicted) SetBit(table[i].flags, TADF_DEPARTURE_NO_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skip_travel = false;
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
order = order->next;
|
order = order->next;
|
||||||
if (i >= v->GetNumOrders()) {
|
if (i >= v->GetNumOrders()) {
|
||||||
@@ -176,10 +227,12 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
|
|||||||
|
|
||||||
/* When loading at a scheduled station we still have to treat the
|
/* When loading at a scheduled station we still have to treat the
|
||||||
* travelling part of the first order. */
|
* travelling part of the first order. */
|
||||||
if (!travelling) {
|
if (!travelling && table[i].arrival == INVALID_TICKS) {
|
||||||
if (!CanDetermineTimeTaken(order, true)) return;
|
if (!CanDetermineTimeTaken(order, true)) return;
|
||||||
sum += order->GetTimetabledTravel();
|
sum += order->GetTimetabledTravel();
|
||||||
table[i].arrival = sum;
|
table[i].arrival = sum;
|
||||||
|
if (predicted) SetBit(table[i].flags, TADF_ARRIVAL_PREDICTED);
|
||||||
|
if (no_offset) SetBit(table[i].flags, TADF_ARRIVAL_NO_OFFSET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -722,7 +775,7 @@ struct TimetableWindow : GeneralVehicleWindow {
|
|||||||
SetDParam(0, _scaled_date_ticks + arr_dep[i / 2].arrival);
|
SetDParam(0, _scaled_date_ticks + arr_dep[i / 2].arrival);
|
||||||
DrawString(time_left, time_right, y, STR_JUST_DATE_WALLCLOCK_TINY, TC_GREEN);
|
DrawString(time_left, time_right, y, STR_JUST_DATE_WALLCLOCK_TINY, TC_GREEN);
|
||||||
} else {
|
} else {
|
||||||
SetDParam(0, _scaled_date_ticks + arr_dep[i / 2].arrival + (HasBit(arr_dep[i / 2].flags, TADF_ARRIVAL_PREDICTED) ? 0 : offset));
|
SetDParam(0, _scaled_date_ticks + arr_dep[i / 2].arrival + (HasBit(arr_dep[i / 2].flags, TADF_ARRIVAL_NO_OFFSET) ? 0 : offset));
|
||||||
DrawString(time_left, time_right, y, STR_JUST_DATE_WALLCLOCK_TINY,
|
DrawString(time_left, time_right, y, STR_JUST_DATE_WALLCLOCK_TINY,
|
||||||
HasBit(arr_dep[i / 2].flags, TADF_ARRIVAL_PREDICTED) ? (TextColour)(TC_IS_PALETTE_COLOUR | TC_NO_SHADE | 4) : (show_late ? TC_RED : i == selected ? TC_WHITE : TC_BLACK));
|
HasBit(arr_dep[i / 2].flags, TADF_ARRIVAL_PREDICTED) ? (TextColour)(TC_IS_PALETTE_COLOUR | TC_NO_SHADE | 4) : (show_late ? TC_RED : i == selected ? TC_WHITE : TC_BLACK));
|
||||||
}
|
}
|
||||||
@@ -730,7 +783,7 @@ struct TimetableWindow : GeneralVehicleWindow {
|
|||||||
} else {
|
} else {
|
||||||
if (arr_dep[i / 2].departure != INVALID_TICKS) {
|
if (arr_dep[i / 2].departure != INVALID_TICKS) {
|
||||||
DrawString(abbr_left, abbr_right, y, STR_TIMETABLE_DEPARTURE_ABBREVIATION, i == selected ? TC_WHITE : TC_BLACK);
|
DrawString(abbr_left, abbr_right, y, STR_TIMETABLE_DEPARTURE_ABBREVIATION, i == selected ? TC_WHITE : TC_BLACK);
|
||||||
SetDParam(0, _scaled_date_ticks + arr_dep[i/2].departure + (HasBit(arr_dep[i / 2].flags, TADF_DEPARTURE_PREDICTED) ? 0 : offset));
|
SetDParam(0, _scaled_date_ticks + arr_dep[i/2].departure + (HasBit(arr_dep[i / 2].flags, TADF_DEPARTURE_NO_OFFSET) ? 0 : offset));
|
||||||
DrawString(time_left, time_right, y, STR_JUST_DATE_WALLCLOCK_TINY,
|
DrawString(time_left, time_right, y, STR_JUST_DATE_WALLCLOCK_TINY,
|
||||||
HasBit(arr_dep[i / 2].flags, TADF_DEPARTURE_PREDICTED) ? (TextColour)(TC_IS_PALETTE_COLOUR | TC_NO_SHADE | 4) : (show_late ? TC_RED : i == selected ? TC_WHITE : TC_BLACK));
|
HasBit(arr_dep[i / 2].flags, TADF_DEPARTURE_PREDICTED) ? (TextColour)(TC_IS_PALETTE_COLOUR | TC_NO_SHADE | 4) : (show_late ? TC_RED : i == selected ? TC_WHITE : TC_BLACK));
|
||||||
}
|
}
|
||||||
|
@@ -1759,6 +1759,37 @@ int GetTraceRestrictTimeDateValue(TraceRestrictTimeDateValueField type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GetTraceRestrictTimeDateValueFromDate(TraceRestrictTimeDateValueField type, DateTicksScaled scaled_date_ticks)
|
||||||
|
{
|
||||||
|
Minutes minutes = (scaled_date_ticks / _settings_game.game_time.ticks_per_minute) + _settings_game.game_time.clock_offset;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case TRTDVF_MINUTE:
|
||||||
|
return MINUTES_MINUTE(minutes);
|
||||||
|
|
||||||
|
case TRTDVF_HOUR:
|
||||||
|
return MINUTES_HOUR(minutes);
|
||||||
|
|
||||||
|
case TRTDVF_HOUR_MINUTE:
|
||||||
|
return (MINUTES_HOUR(minutes) * 100) + MINUTES_MINUTE(minutes);
|
||||||
|
|
||||||
|
case TRTDVF_DAY: {
|
||||||
|
YearMonthDay ymd;
|
||||||
|
ConvertDateToYMD(scaled_date_ticks / (DAY_TICKS * _settings_game.economy.day_length_factor), &ymd);
|
||||||
|
return ymd.day;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TRTDVF_MONTH: {
|
||||||
|
YearMonthDay ymd;
|
||||||
|
ConvertDateToYMD(scaled_date_ticks / (DAY_TICKS * _settings_game.economy.day_length_factor), &ymd);
|
||||||
|
return ymd.month + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is called when a station, waypoint or depot is about to be deleted
|
* This is called when a station, waypoint or depot is about to be deleted
|
||||||
* Scan program pool and change any references to it to the invalid station ID, to avoid dangling references
|
* Scan program pool and change any references to it to the invalid station ID, to avoid dangling references
|
||||||
|
@@ -941,6 +941,7 @@ CommandCost TraceRestrictProgramMoveItemAt(std::vector<TraceRestrictItem> &items
|
|||||||
void ShowTraceRestrictProgramWindow(TileIndex tile, Track track);
|
void ShowTraceRestrictProgramWindow(TileIndex tile, Track track);
|
||||||
|
|
||||||
int GetTraceRestrictTimeDateValue(TraceRestrictTimeDateValueField type);
|
int GetTraceRestrictTimeDateValue(TraceRestrictTimeDateValueField type);
|
||||||
|
int GetTraceRestrictTimeDateValueFromDate(TraceRestrictTimeDateValueField type, DateTicksScaled scaled_date_ticks);
|
||||||
|
|
||||||
void TraceRestrictRemoveDestinationID(TraceRestrictOrderCondAuxField type, uint16 index);
|
void TraceRestrictRemoveDestinationID(TraceRestrictOrderCondAuxField type, uint16 index);
|
||||||
void TraceRestrictRemoveGroupID(GroupID index);
|
void TraceRestrictRemoveGroupID(GroupID index);
|
||||||
|
Reference in New Issue
Block a user