diff --git a/src/lang/english.txt b/src/lang/english.txt index cca349b9d8..55cf9eb6be 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2386,6 +2386,7 @@ STR_TRACE_RESTRICT_VARIABLE_TRAIN_LENGTH :train length STR_TRACE_RESTRICT_VARIABLE_MAX_SPEED :max speed STR_TRACE_RESTRICT_VARIABLE_CURRENT_ORDER :current order STR_TRACE_RESTRICT_VARIABLE_NEXT_ORDER :next order +STR_TRACE_RESTRICT_VARIABLE_LAST_VISITED_STATION :last visited station STR_TRACE_RESTRICT_VARIABLE_UNDEFINED :undefined STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_INTEGER :{STRING} {STRING} {STRING} {COMMA} then STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_SPEED :{STRING} {STRING} {STRING} {VELOCITY} then diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index 046e35d99b..3d877e6778 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -132,6 +132,21 @@ static bool TestCondition(uint16 value, TraceRestrictCondOp condop, uint16 condv } } +static bool TestBinaryConditionCommon(TraceRestrictItem item, bool input) +{ + switch (GetTraceRestrictCondOp(item)) { + case TRCO_IS: + return input; + + case TRCO_ISNOT: + return !input; + + default: + NOT_REACHED(); + return false; + } +} + /// Test order condition /// order may be NULL static bool TestOrderCondition(const Order *order, TraceRestrictItem item) @@ -157,18 +172,15 @@ static bool TestOrderCondition(const Order *order, TraceRestrictItem item) NOT_REACHED(); } } + return TestBinaryConditionCommon(item, result); +} - switch (GetTraceRestrictCondOp(item)) { - case TRCO_IS: - return result; +/// Test station condition +static bool TestStationCondition(StationID station, TraceRestrictItem item) +{ + bool result = (GetTraceRestrictAuxField(item) == TROCAF_STATION) && (station == GetTraceRestrictValue(item)); + return TestBinaryConditionCommon(item, result); - case TRCO_ISNOT: - return !result; - - default: - NOT_REACHED(); - return false; - } } /// Execute program on train and store results in out @@ -232,6 +244,10 @@ void TraceRestrictProgram::Execute(const Train* v, TraceRestrictProgramResult& o break; } + case TRIT_COND_LAST_STATION: + result = TestStationCondition(v->last_station_visited, item); + break; + default: NOT_REACHED(); } @@ -752,7 +768,8 @@ void TraceRestrictRemoveDestinationID(TraceRestrictOrderCondAuxField type, uint1 for (size_t i = 0; i < prog->items.size(); i++) { TraceRestrictItem &item = prog->items[i]; // note this is a reference, if (GetTraceRestrictType(item) == TRIT_COND_CURRENT_ORDER || - GetTraceRestrictType(item) == TRIT_COND_NEXT_ORDER) { + GetTraceRestrictType(item) == TRIT_COND_NEXT_ORDER || + GetTraceRestrictType(item) == TRIT_COND_LAST_STATION) { if (GetTraceRestrictAuxField(item) == type && GetTraceRestrictValue(item) == index) { SetTraceRestrictValueDefault(item, TRVT_ORDER); // this updates the instruction in-place } diff --git a/src/tracerestrict.h b/src/tracerestrict.h index 9a2dc25e78..7a62dc2053 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -84,6 +84,7 @@ enum TraceRestrictItemType { TRIT_COND_MAX_SPEED = 11, ///< Test train max speed TRIT_COND_CURRENT_ORDER = 12, ///< Test train current order (station, waypoint or depot) TRIT_COND_NEXT_ORDER = 13, ///< Test train next order (station, waypoint or depot) + TRIT_COND_LAST_STATION = 14, ///< Test train last visited station /* space up to 31 */ }; @@ -191,8 +192,6 @@ static inline void SetTraceRestrictAuxField(TraceRestrictItem &item, uint8 data) SB(item, TRIFA_AUX_FIELD_OFFSET, TRIFA_AUX_FIELD_COUNT, data); } -void SetTraceRestrictTypeAndNormalise(TraceRestrictItem &item, TraceRestrictItemType type); - static inline void SetTraceRestrictValue(TraceRestrictItem &item, uint16 value) { SB(item, TRIFA_VALUE_OFFSET, TRIFA_VALUE_COUNT, value); @@ -223,6 +222,9 @@ enum TraceRestrictValueType { TRVT_ORDER = 5, ///< takes an order target ID, as per the auxiliary field as type: TraceRestrictOrderCondAuxField }; +void SetTraceRestrictValueDefault(TraceRestrictItem &item, TraceRestrictValueType value_type); +void SetTraceRestrictTypeAndNormalise(TraceRestrictItem &item, TraceRestrictItemType type); + struct TraceRestrictTypePropertySet { TraceRestrictConditionOpType cond_type; TraceRestrictValueType value_type; @@ -253,6 +255,7 @@ static inline TraceRestrictTypePropertySet GetTraceRestrictTypeProperties(TraceR case TRIT_COND_CURRENT_ORDER: case TRIT_COND_NEXT_ORDER: + case TRIT_COND_LAST_STATION: out.value_type = TRVT_ORDER; out.cond_type = TRCOT_BINARY; break; diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index 0f13f66099..c4d7d4a88d 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -160,6 +160,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictI STR_TRACE_RESTRICT_VARIABLE_MAX_SPEED, STR_TRACE_RESTRICT_VARIABLE_CURRENT_ORDER, STR_TRACE_RESTRICT_VARIABLE_NEXT_ORDER, + STR_TRACE_RESTRICT_VARIABLE_LAST_VISITED_STATION, STR_TRACE_RESTRICT_VARIABLE_UNDEFINED, INVALID_STRING_ID, }; @@ -168,6 +169,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictI TRIT_COND_MAX_SPEED, TRIT_COND_CURRENT_ORDER, TRIT_COND_NEXT_ORDER, + TRIT_COND_LAST_STATION, TRIT_COND_UNDEFINED, }; static const TraceRestrictDropDownListSet set_cond = { @@ -599,6 +601,10 @@ public: case TR_WIDGET_TYPE: { SetTraceRestrictTypeAndNormalise(item, static_cast(value)); + if (GetTraceRestrictType(item) == TRIT_COND_LAST_STATION && GetTraceRestrictAuxField(item) != TROCAF_STATION) { + // if changing type from another order type to last visited station, reset value if not currently a station + SetTraceRestrictValueDefault(item, TRVT_ORDER); + } TraceRestrictDoCommandP(this->tile, this->track, TRDCT_MODIFY_ITEM, this->selected_instruction - 1, item, STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM); break; } @@ -701,10 +707,14 @@ public: TraceRestrictItem item = GetSelected(); if (GetTraceRestrictTypeProperties(item).value_type != TRVT_ORDER) return; + bool stations_only = (GetTraceRestrictType(item) == TRIT_COND_LAST_STATION); + if (IsDepotTypeTile(tile, TRANSPORT_RAIL)) { + if (stations_only) return; SetTraceRestrictValue(item, GetDepotIndex(tile)); SetTraceRestrictAuxField(item, TROCAF_DEPOT); } else if (IsRailWaypointTile(tile)) { + if (stations_only) return; SetTraceRestrictValue(item, GetStationIndex(tile)); SetTraceRestrictAuxField(item, TROCAF_WAYPOINT); } else if (IsTileType(tile, MP_STATION)) {