Add tracerestrict feature reverse behind signal
This commit is contained in:
@@ -2689,6 +2689,7 @@ STR_TRACE_RESTRICT_DIRECTION_NW :north-west
|
||||
STR_TRACE_RESTRICT_COMPANY :Company
|
||||
STR_TRACE_RESTRICT_UNDEFINED_COMPANY :Undefined company
|
||||
STR_TRACE_RESTRICT_SLOT_OP :Slot operation
|
||||
STR_TRACE_RESTRICT_REVERSE :Reverse
|
||||
STR_TRACE_RESTRICT_SLOT_ACQUIRE_WAIT :Acquire or wait
|
||||
STR_TRACE_RESTRICT_SLOT_TRY_ACQUIRE :Try to acquire
|
||||
STR_TRACE_RESTRICT_SLOT_RELEASE_FRONT :Release (front)
|
||||
@@ -2717,6 +2718,8 @@ STR_TRACE_RESTRICT_TRAIN_STATUS_LOADING :loading
|
||||
STR_TRACE_RESTRICT_TRAIN_STATUS_WAITING :waiting
|
||||
STR_TRACE_RESTRICT_TRAIN_STATUS_LOST :lost
|
||||
STR_TRACE_RESTRICT_TRAIN_STATUS_REQUIRES_SERVICE :requires service
|
||||
STR_TRACE_RESTRICT_REVERSE_SIG :Reverse behind signal
|
||||
STR_TRACE_RESTRICT_REVERSE_SIG_CANCEL :Cancel reverse behind signal
|
||||
STR_TRACE_RESTRICT_VALUE_CAPTION :{WHITE}Value
|
||||
STR_TRACE_RESTRICT_CAPTION :{WHITE}Routefinding restriction
|
||||
STR_TRACE_RESTRICT_CAPTION_SHARED :{WHITE}Routefinding restriction - shared by {COMMA} signals
|
||||
|
@@ -208,17 +208,25 @@ public:
|
||||
}
|
||||
|
||||
/** add multiple nodes - direct children of the given node */
|
||||
inline void AddMultipleNodes(Node *parent, const TrackFollower &tf)
|
||||
template <class TNodeFunc>
|
||||
inline void AddMultipleNodes(Node *parent, const TrackFollower &tf, TNodeFunc node_func)
|
||||
{
|
||||
bool is_choice = (KillFirstBit(tf.m_new_td_bits) != TRACKDIR_BIT_NONE);
|
||||
for (TrackdirBits rtds = tf.m_new_td_bits; rtds != TRACKDIR_BIT_NONE; rtds = KillFirstBit(rtds)) {
|
||||
Trackdir td = (Trackdir)FindFirstBit2x64(rtds);
|
||||
Node &n = Yapf().CreateNewNode();
|
||||
n.Set(parent, tf.m_new_tile, td, is_choice);
|
||||
node_func(n);
|
||||
Yapf().AddNewNode(n, tf);
|
||||
}
|
||||
}
|
||||
|
||||
/** add multiple nodes - direct children of the given node */
|
||||
inline void AddMultipleNodes(Node *parent, const TrackFollower &tf)
|
||||
{
|
||||
AddMultipleNodes(parent, tf, [&](Node &n) {});
|
||||
}
|
||||
|
||||
/**
|
||||
* In some cases an intermediate node branch should be pruned.
|
||||
* The most prominent case is when a red EOL signal is encountered, but
|
||||
|
@@ -273,6 +273,9 @@ private:
|
||||
*is_res_through = false;
|
||||
flags_to_check |= TRPAUF_RESERVE_THROUGH;
|
||||
}
|
||||
if (GetSignalType(tile, TrackdirToTrack(trackdir)) == SIGTYPE_PBS && !HasSignalOnTrackdir(tile, trackdir)) {
|
||||
flags_to_check |= TRPAUF_REVERSE;
|
||||
}
|
||||
if (prog && prog->actions_used_flags & flags_to_check) {
|
||||
prog->Execute(Yapf().GetVehicle(), TraceRestrictProgramInput(tile, trackdir, &TraceRestrictPreviousSignalCallback, &n), out);
|
||||
if (out.flags & TRPRF_RESERVE_THROUGH && is_res_through != NULL) {
|
||||
@@ -282,6 +285,10 @@ private:
|
||||
n.m_segment->m_end_segment_reason |= ESRB_DEAD_END;
|
||||
return true;
|
||||
}
|
||||
if (out.flags & TRPRF_REVERSE && flags_to_check & TRPAUF_REVERSE && !n.flags_u.flags_s.m_reverse_pending) {
|
||||
n.flags_u.flags_s.m_reverse_pending = true;
|
||||
n.m_segment->m_end_segment_reason |= ESRB_REVERSE;
|
||||
}
|
||||
cost += out.penalty;
|
||||
}
|
||||
return false;
|
||||
@@ -478,6 +485,17 @@ public:
|
||||
assert(!is_cached_segment);
|
||||
/* Skip the first transition cost calculation. */
|
||||
goto no_entry_cost;
|
||||
} else if (n.flags_u.flags_s.m_teleport) {
|
||||
int x1 = 2 * TileX(prev.tile);
|
||||
int y1 = 2 * TileY(prev.tile);
|
||||
int x2 = 2 * TileX(cur.tile);
|
||||
int y2 = 2 * TileY(cur.tile);
|
||||
int dx = abs(x1 - x2);
|
||||
int dy = abs(y1 - y2);
|
||||
int dmin = min(dx, dy);
|
||||
int dxy = abs(dx - dy);
|
||||
segment_entry_cost += dmin * YAPF_TILE_CORNER_LENGTH + (dxy - 1) * (YAPF_TILE_LENGTH / 2);
|
||||
goto no_entry_cost;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
@@ -723,9 +741,11 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
|
||||
|
||||
/* Do we have an excuse why not to continue pathfinding in this direction? */
|
||||
if (!target_seen && (end_segment_reason & ESRB_ABORT_PF_MASK) != ESRB_NONE) {
|
||||
if (likely(!n.flags_u.flags_s.m_reverse_pending || (end_segment_reason & ESRB_ABORT_PF_MASK_PENDING_REVERSE) != ESRB_NONE)) {
|
||||
/* Reason to not continue. Stop this PF branch. */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special costs for the case we have reached our target. */
|
||||
if (target_seen) {
|
||||
|
@@ -137,6 +137,8 @@ struct CYapfRailNodeT
|
||||
bool m_targed_seen : 1;
|
||||
bool m_choice_seen : 1;
|
||||
bool m_last_signal_was_red : 1;
|
||||
bool m_reverse_pending : 1;
|
||||
bool m_teleport : 1;
|
||||
} flags_s;
|
||||
} flags_u;
|
||||
SignalType m_last_red_signal_type;
|
||||
@@ -174,6 +176,7 @@ struct CYapfRailNodeT
|
||||
m_last_signal_type = parent->m_last_signal_type;
|
||||
}
|
||||
flags_u.flags_s.m_choice_seen |= is_choice;
|
||||
flags_u.flags_s.m_teleport = false;
|
||||
}
|
||||
|
||||
inline TileIndex GetLastTile() const
|
||||
|
@@ -293,6 +293,21 @@ public:
|
||||
inline void PfFollowNode(Node &old_node)
|
||||
{
|
||||
TrackFollower F(Yapf().GetVehicle());
|
||||
if (old_node.flags_u.flags_s.m_reverse_pending && old_node.m_segment->m_end_segment_reason & (ESRB_SAFE_TILE | ESRB_DEPOT | ESRB_DEAD_END)) {
|
||||
Node *rev_node = &old_node;
|
||||
while (rev_node && !(rev_node->m_segment->m_end_segment_reason & ESRB_REVERSE)) {
|
||||
rev_node = rev_node->m_parent;
|
||||
}
|
||||
if (rev_node) {
|
||||
if (F.Follow(rev_node->GetLastTile(), ReverseTrackdir(rev_node->GetLastTrackdir()))) {
|
||||
Yapf().AddMultipleNodes(&old_node, F, [&](Node &n) {
|
||||
n.flags_u.flags_s.m_reverse_pending = false;
|
||||
n.flags_u.flags_s.m_teleport = true;
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (F.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir())) {
|
||||
Yapf().AddMultipleNodes(&old_node, F);
|
||||
}
|
||||
@@ -471,6 +486,21 @@ public:
|
||||
inline void PfFollowNode(Node &old_node)
|
||||
{
|
||||
TrackFollower F(Yapf().GetVehicle());
|
||||
if (old_node.flags_u.flags_s.m_reverse_pending && old_node.m_segment->m_end_segment_reason & (ESRB_SAFE_TILE | ESRB_DEPOT | ESRB_DEAD_END)) {
|
||||
Node *rev_node = &old_node;
|
||||
while (rev_node && !(rev_node->m_segment->m_end_segment_reason & ESRB_REVERSE)) {
|
||||
rev_node = rev_node->m_parent;
|
||||
}
|
||||
if (rev_node) {
|
||||
if (F.Follow(rev_node->GetLastTile(), ReverseTrackdir(rev_node->GetLastTrackdir()))) {
|
||||
Yapf().AddMultipleNodes(&old_node, F, [&](Node &n) {
|
||||
n.flags_u.flags_s.m_reverse_pending = false;
|
||||
n.flags_u.flags_s.m_teleport = true;
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (F.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir())) {
|
||||
Yapf().AddMultipleNodes(&old_node, F);
|
||||
}
|
||||
|
@@ -31,6 +31,7 @@ enum EndSegmentReason {
|
||||
ESR_FIRST_TWO_WAY_RED, ///< first signal was 2-way and it was red
|
||||
ESR_LOOK_AHEAD_END, ///< we have just passed the last look-ahead signal
|
||||
ESR_TARGET_REACHED, ///< we have just reached the destination
|
||||
ESR_REVERSE, ///< we should reverse after this point
|
||||
|
||||
/* Special values */
|
||||
ESR_NONE = 0xFF, ///< no reason to end the segment here
|
||||
@@ -53,6 +54,7 @@ enum EndSegmentReasonBits {
|
||||
ESRB_FIRST_TWO_WAY_RED = 1 << ESR_FIRST_TWO_WAY_RED,
|
||||
ESRB_LOOK_AHEAD_END = 1 << ESR_LOOK_AHEAD_END,
|
||||
ESRB_TARGET_REACHED = 1 << ESR_TARGET_REACHED,
|
||||
ESRB_REVERSE = 1 << ESR_REVERSE,
|
||||
|
||||
/* Additional (composite) values. */
|
||||
|
||||
@@ -60,10 +62,13 @@ enum EndSegmentReasonBits {
|
||||
ESRB_POSSIBLE_TARGET = ESRB_DEPOT | ESRB_WAYPOINT | ESRB_STATION | ESRB_SAFE_TILE,
|
||||
|
||||
/* What reasons can be stored back into cached segment. */
|
||||
ESRB_CACHED_MASK = ESRB_DEAD_END | ESRB_RAIL_TYPE | ESRB_INFINITE_LOOP | ESRB_SEGMENT_TOO_LONG | ESRB_CHOICE_FOLLOWS | ESRB_DEPOT | ESRB_WAYPOINT | ESRB_STATION | ESRB_SAFE_TILE,
|
||||
ESRB_CACHED_MASK = ESRB_DEAD_END | ESRB_RAIL_TYPE | ESRB_INFINITE_LOOP | ESRB_SEGMENT_TOO_LONG | ESRB_CHOICE_FOLLOWS | ESRB_DEPOT | ESRB_WAYPOINT | ESRB_STATION | ESRB_SAFE_TILE | ESRB_REVERSE,
|
||||
|
||||
/* Reasons to abort pathfinding in this direction. */
|
||||
ESRB_ABORT_PF_MASK = ESRB_DEAD_END | ESRB_PATH_TOO_LONG | ESRB_INFINITE_LOOP | ESRB_FIRST_TWO_WAY_RED,
|
||||
|
||||
/* Reasons to abort pathfinding in this direction, when reversing is pending. */
|
||||
ESRB_ABORT_PF_MASK_PENDING_REVERSE = ESRB_ABORT_PF_MASK & ~ESRB_DEAD_END,
|
||||
};
|
||||
|
||||
DECLARE_ENUM_AS_BIT_SET(EndSegmentReasonBits)
|
||||
|
@@ -51,6 +51,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
|
||||
{ XSLFI_TRACE_RESTRICT_OWNER, XSCF_NULL, 1, 1, "tracerestrict_owner", NULL, NULL, NULL },
|
||||
{ XSLFI_TRACE_RESTRICT_ORDRCND, XSCF_NULL, 2, 2, "tracerestrict_order_cond", NULL, NULL, NULL },
|
||||
{ XSLFI_TRACE_RESTRICT_STATUSCND,XSCF_NULL, 1, 1, "tracerestrict_status_cond", NULL, NULL, NULL },
|
||||
{ XSLFI_TRACE_RESTRICT_REVERSE, XSCF_NULL, 1, 1, "tracerestrict_reverse", NULL, NULL, NULL },
|
||||
{ XSLFI_PROG_SIGS, XSCF_NULL, 1, 1, "programmable_signals", NULL, NULL, "SPRG" },
|
||||
{ XSLFI_ADJACENT_CROSSINGS, XSCF_NULL, 1, 1, "adjacent_crossings", NULL, NULL, NULL },
|
||||
{ XSLFI_SAFER_CROSSINGS, XSCF_NULL, 1, 1, "safer_crossings", NULL, NULL, NULL },
|
||||
|
@@ -25,6 +25,7 @@ enum SlXvFeatureIndex {
|
||||
XSLFI_TRACE_RESTRICT_OWNER, ///< Trace restrict: train owner test
|
||||
XSLFI_TRACE_RESTRICT_ORDRCND, ///< Trace restrict: slot conditional order
|
||||
XSLFI_TRACE_RESTRICT_STATUSCND, ///< Trace restrict: train status condition
|
||||
XSLFI_TRACE_RESTRICT_REVERSE, ///< Trace restrict: reverse
|
||||
XSLFI_PROG_SIGS, ///< programmable signals patch
|
||||
XSLFI_ADJACENT_CROSSINGS, ///< Adjacent level crossings closure patch
|
||||
XSLFI_SAFER_CROSSINGS, ///< Safer level crossings
|
||||
|
@@ -612,6 +612,22 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp
|
||||
break;
|
||||
}
|
||||
|
||||
case TRIT_REVERSE:
|
||||
switch (static_cast<TraceRestrictReverseValueField>(GetTraceRestrictValue(item))) {
|
||||
case TRRVF_REVERSE:
|
||||
out.flags |= TRPRF_REVERSE;
|
||||
break;
|
||||
|
||||
case TRRVF_CANCEL_REVERSE:
|
||||
out.flags &= ~TRPRF_REVERSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
NOT_REACHED();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
@@ -776,6 +792,10 @@ CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem>
|
||||
}
|
||||
break;
|
||||
|
||||
case TRIT_REVERSE:
|
||||
actions_used_flags |= TRPAUF_REVERSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
return_cmd_error(STR_TRACE_RESTRICT_ERROR_VALIDATE_UNKNOWN_INSTRUCTION);
|
||||
}
|
||||
@@ -836,6 +856,7 @@ void SetTraceRestrictValueDefault(TraceRestrictItem &item, TraceRestrictValueTyp
|
||||
case TRVT_FORCE_WEIGHT_RATIO:
|
||||
case TRVT_WAIT_AT_PBS:
|
||||
case TRVT_TRAIN_STATUS:
|
||||
case TRVT_REVERSE:
|
||||
SetTraceRestrictValue(item, 0);
|
||||
if (!IsTraceRestrictTypeAuxSubtype(GetTraceRestrictType(item))) {
|
||||
SetTraceRestrictAuxField(item, 0);
|
||||
|
@@ -140,7 +140,7 @@ enum TraceRestrictItemType {
|
||||
TRIT_COND_TRAIN_STATUS = 25, ///< Test train status
|
||||
|
||||
TRIT_COND_END = 48, ///< End (exclusive) of conditional item types, note that this has the same value as TRIT_REVERSE
|
||||
//TRIT_REVERSE = 48, ///< Reverse: reserved for future use
|
||||
TRIT_REVERSE = 48, ///< Reverse behind signal
|
||||
|
||||
/* space up to 63 */
|
||||
};
|
||||
@@ -238,6 +238,14 @@ enum TraceRestrictWaitAtPbsValueField {
|
||||
TRWAPVF_CANCEL_PBS_RES_END_WAIT = 3, ///< Cancel PBS reservations ending at this signal wait
|
||||
};
|
||||
|
||||
/**
|
||||
* TraceRestrictItem value field, for TRIT_REVERSE
|
||||
*/
|
||||
enum TraceRestrictReverseValueField {
|
||||
TRRVF_REVERSE = 0, ///< Reverse
|
||||
TRRVF_CANCEL_REVERSE = 1, ///< Cancel reverse
|
||||
};
|
||||
|
||||
/**
|
||||
* TraceRestrictItem value field, for TRIT_COND_TRAIN_STATUS
|
||||
*/
|
||||
@@ -298,6 +306,7 @@ enum TraceRestrictProgramResultFlags {
|
||||
TRPRF_LONG_RESERVE = 1 << 2, ///< Long reserve is set
|
||||
TRPRF_WAIT_AT_PBS = 1 << 3, ///< Wait at PBS signal is set
|
||||
TRPRF_PBS_RES_END_WAIT = 1 << 4, ///< PBS reservations ending at this signal wait is set
|
||||
TRPRF_REVERSE = 1 << 5, ///< Reverse behind signal
|
||||
};
|
||||
DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramResultFlags)
|
||||
|
||||
@@ -314,6 +323,7 @@ enum TraceRestrictProgramActionsUsedFlags {
|
||||
TRPAUF_SLOT_RELEASE_FRONT = 1 << 6, ///< Slot release (front) action is present
|
||||
TRPAUF_PBS_RES_END_WAIT = 1 << 7, ///< PBS reservations ending at this signal wait action is present
|
||||
TRPAUF_PBS_RES_END_SLOT = 1 << 8, ///< PBS reservations ending at this signal slot action is present
|
||||
TRPAUF_REVERSE = 1 << 9, ///< Reverse behind signal
|
||||
};
|
||||
DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramActionsUsedFlags)
|
||||
|
||||
@@ -545,6 +555,7 @@ enum TraceRestrictValueType {
|
||||
TRVT_SLOT_INDEX_INT = 20,///< takes a TraceRestrictSlotID, and an integer in the next item slot
|
||||
TRVT_OWNER = 40,///< takes a CompanyID
|
||||
TRVT_TRAIN_STATUS = 41,///< takes a TraceRestrictTrainStatusValueField
|
||||
TRVT_REVERSE = 42,///< takes a TraceRestrictReverseValueField
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -684,6 +695,8 @@ static inline TraceRestrictTypePropertySet GetTraceRestrictTypeProperties(TraceR
|
||||
out.value_type = TRVT_WAIT_AT_PBS;
|
||||
} else if (GetTraceRestrictType(item) == TRIT_SLOT) {
|
||||
out.value_type = TRVT_SLOT_INDEX;
|
||||
} else if (GetTraceRestrictType(item) == TRIT_REVERSE) {
|
||||
out.value_type = TRVT_REVERSE;
|
||||
} else {
|
||||
out.value_type = TRVT_NONE;
|
||||
}
|
||||
|
@@ -152,6 +152,7 @@ static const StringID _program_insert_str[] = {
|
||||
STR_TRACE_RESTRICT_LONG_RESERVE,
|
||||
STR_TRACE_RESTRICT_WAIT_AT_PBS,
|
||||
STR_TRACE_RESTRICT_SLOT_OP,
|
||||
STR_TRACE_RESTRICT_REVERSE,
|
||||
INVALID_STRING_ID
|
||||
};
|
||||
static const uint32 _program_insert_else_hide_mask = 8; ///< disable bitmask for else
|
||||
@@ -170,6 +171,7 @@ static const uint _program_insert_val[] = {
|
||||
TRIT_LONG_RESERVE, // long reserve
|
||||
TRIT_WAIT_AT_PBS, // wait at PBS signal
|
||||
TRIT_SLOT, // slot operation
|
||||
TRIT_REVERSE, // reverse
|
||||
};
|
||||
|
||||
/** insert drop down list strings and values */
|
||||
@@ -297,6 +299,21 @@ static const TraceRestrictDropDownListSet _train_status_value = {
|
||||
_train_status_value_str, _train_status_value_val,
|
||||
};
|
||||
|
||||
static const StringID _reverse_value_str[] = {
|
||||
STR_TRACE_RESTRICT_REVERSE_SIG,
|
||||
STR_TRACE_RESTRICT_REVERSE_SIG_CANCEL,
|
||||
INVALID_STRING_ID
|
||||
};
|
||||
static const uint _reverse_value_val[] = {
|
||||
TRRVF_REVERSE,
|
||||
TRRVF_CANCEL_REVERSE,
|
||||
};
|
||||
|
||||
/** value drop down list for wait at PBS types strings and values */
|
||||
static const TraceRestrictDropDownListSet _reverse_value = {
|
||||
_reverse_value_str, _reverse_value_val,
|
||||
};
|
||||
|
||||
/**
|
||||
* Get index of @p value in @p list_set
|
||||
* if @p value is not present, assert if @p missing_ok is false, otherwise return -1
|
||||
@@ -353,6 +370,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG
|
||||
STR_TRACE_RESTRICT_LONG_RESERVE,
|
||||
STR_TRACE_RESTRICT_WAIT_AT_PBS,
|
||||
STR_TRACE_RESTRICT_SLOT_OP,
|
||||
STR_TRACE_RESTRICT_REVERSE,
|
||||
INVALID_STRING_ID,
|
||||
};
|
||||
static const uint val_action[] = {
|
||||
@@ -362,6 +380,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG
|
||||
TRIT_LONG_RESERVE,
|
||||
TRIT_WAIT_AT_PBS,
|
||||
TRIT_SLOT,
|
||||
TRIT_REVERSE,
|
||||
};
|
||||
static const TraceRestrictDropDownListSet set_action = {
|
||||
str_action, val_action,
|
||||
@@ -1188,6 +1207,22 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric
|
||||
SetDParam(2, selected ? STR_TRACE_RESTRICT_WHITE : STR_EMPTY);
|
||||
break;
|
||||
|
||||
case TRIT_REVERSE:
|
||||
switch (static_cast<TraceRestrictReverseValueField>(GetTraceRestrictValue(item))) {
|
||||
case TRRVF_REVERSE:
|
||||
instruction_string = STR_TRACE_RESTRICT_REVERSE_SIG;
|
||||
break;
|
||||
|
||||
case TRRVF_CANCEL_REVERSE:
|
||||
instruction_string = STR_TRACE_RESTRICT_REVERSE_SIG_CANCEL;
|
||||
break;
|
||||
|
||||
default:
|
||||
NOT_REACHED();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
NOT_REACHED();
|
||||
break;
|
||||
@@ -1482,6 +1517,10 @@ public:
|
||||
this->ShowDropDownListWithValue(&_train_status_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case TRVT_REVERSE:
|
||||
this->ShowDropDownListWithValue(&_reverse_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -2465,6 +2504,13 @@ private:
|
||||
GetDropDownStringByValue(&_train_status_value, GetTraceRestrictValue(item));
|
||||
break;
|
||||
|
||||
case TRVT_REVERSE:
|
||||
right_sel->SetDisplayedPlane(DPR_VALUE_DROPDOWN);
|
||||
this->EnableWidget(TR_WIDGET_VALUE_DROPDOWN);
|
||||
this->GetWidget<NWidgetCore>(TR_WIDGET_VALUE_DROPDOWN)->widget_data =
|
||||
GetDropDownStringByValue(&_reverse_value, GetTraceRestrictValue(item));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@@ -4007,11 +4007,16 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
|
||||
const Trackdir dir = FindFirstTrackdir(trackdirbits);
|
||||
if (HasSignalOnTrack(gp.new_tile, TrackdirToTrack(dir))) {
|
||||
const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(gp.new_tile, TrackdirToTrack(dir));
|
||||
if (prog && prog->actions_used_flags & (TRPAUF_SLOT_ACQUIRE | TRPAUF_SLOT_RELEASE_FRONT)) {
|
||||
if (prog && prog->actions_used_flags & (TRPAUF_SLOT_ACQUIRE | TRPAUF_SLOT_RELEASE_FRONT | TRPAUF_REVERSE)) {
|
||||
TraceRestrictProgramResult out;
|
||||
TraceRestrictProgramInput input(gp.new_tile, dir, NULL, NULL);
|
||||
input.permitted_slot_operations = TRPISP_ACQUIRE | TRPISP_RELEASE_FRONT;
|
||||
prog->Execute(v, input, out);
|
||||
if (out.flags & TRPRF_REVERSE && GetSignalType(gp.new_tile, TrackdirToTrack(dir)) == SIGTYPE_PBS &&
|
||||
!HasSignalOnTrackdir(gp.new_tile, dir)) {
|
||||
v->reverse_distance = v->gcache.cached_total_length + (IsDiagonalTrack(TrackdirToTrack(dir)) ? 16 : 8);
|
||||
SetWindowDirty(WC_VEHICLE_VIEW, v->index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user