diff --git a/src/lang/english.txt b/src/lang/english.txt index 132d7a1eb1..785dc754db 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2377,6 +2377,8 @@ STR_TRACE_RESTRICT_CONDITIONAL_COMPARATOR_LESS_THAN :< STR_TRACE_RESTRICT_CONDITIONAL_COMPARATOR_LESS_EQUALS :<= STR_TRACE_RESTRICT_CONDITIONAL_COMPARATOR_MORE_THAN :> STR_TRACE_RESTRICT_CONDITIONAL_COMPARATOR_MORE_EQUALS :>= +STR_TRACE_RESTRICT_CONDITIONAL_COMPARATOR_CARGO_EQUALS :can carry +STR_TRACE_RESTRICT_CONDITIONAL_COMPARATOR_CARGO_NOT_EQUALS :can't carry STR_TRACE_RESTRICT_CONDITIONAL_IF :If STR_TRACE_RESTRICT_CONDITIONAL_ELIF :Else if STR_TRACE_RESTRICT_CONDITIONAL_ORIF :Or if @@ -2387,12 +2389,14 @@ 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_CARGO :cargo 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 STR_TRACE_RESTRICT_CONDITIONAL_ORDER_STATION :{STRING} {STRING} {STRING} {STATION} then STR_TRACE_RESTRICT_CONDITIONAL_ORDER_WAYPOINT :{STRING} {STRING} {STRING} {WAYPOINT} then STR_TRACE_RESTRICT_CONDITIONAL_ORDER_DEPOT :{STRING} {STRING} {STRING} {DEPOT} then +STR_TRACE_RESTRICT_CONDITIONAL_CARGO :{STRING} train {STRING} cargo: {STRING} then STR_TRACE_RESTRICT_CONDITIONAL_UNDEFINED :{STRING} {STRING} {STRING} {RED}undefined {BLACK}{STRING}then STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_UNDEFINED :{STRING} {RED}undefined {BLACK}{STRING}then STR_TRACE_RESTRICT_PF_PENALTY_ITEM :Add pathfinder penalty: {COMMA} diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index 3d877e6778..6bd9c8e7c5 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -17,6 +17,7 @@ #include "viewport_func.h" #include "window_func.h" #include "order_base.h" +#include "cargotype.h" #include "pathfinder/yapf/yapf_cache.h" #include @@ -248,6 +249,18 @@ void TraceRestrictProgram::Execute(const Train* v, TraceRestrictProgramResult& o result = TestStationCondition(v->last_station_visited, item); break; + case TRIT_COND_CARGO: { + bool have_cargo = false; + for (const Vehicle *v_iter = v; v_iter != NULL; v_iter = v_iter->Next()) { + if (v_iter->cargo_type == GetTraceRestrictValue(item) && v_iter->cargo_cap > 0) { + have_cargo = true; + break; + } + } + result = TestBinaryConditionCommon(item, have_cargo); + break; + } + default: NOT_REACHED(); } @@ -348,6 +361,12 @@ void SetTraceRestrictValueDefault(TraceRestrictItem &item, TraceRestrictValueTyp SetTraceRestrictAuxField(item, TROCAF_STATION); break; + case TRVT_CARGO_ID: + assert(_sorted_standard_cargo_specs_size > 0); + SetTraceRestrictValue(item, _sorted_cargo_specs[0]->Index()); + SetTraceRestrictAuxField(item, 0); + break; + default: NOT_REACHED(); break; diff --git a/src/tracerestrict.h b/src/tracerestrict.h index 0ffe9ba0f1..424daa9fc8 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -85,6 +85,7 @@ enum TraceRestrictItemType { 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 + TRIT_COND_CARGO = 15, ///< Test if train can carry cargo type /* space up to 31 */ }; @@ -226,6 +227,7 @@ enum TraceRestrictValueType { TRVT_DENY = 3, ///< takes a value 0 = deny, 1 = allow (cancel previous deny) TRVT_SPEED = 4, ///< takes an integer speed value TRVT_ORDER = 5, ///< takes an order target ID, as per the auxiliary field as type: TraceRestrictOrderCondAuxField + TRVT_CARGO_ID = 6, ///< takes a CargoID }; void SetTraceRestrictValueDefault(TraceRestrictItem &item, TraceRestrictValueType value_type); @@ -266,6 +268,11 @@ static inline TraceRestrictTypePropertySet GetTraceRestrictTypeProperties(TraceR out.cond_type = TRCOT_BINARY; break; + case TRIT_COND_CARGO: + out.value_type = TRVT_CARGO_ID; + out.cond_type = TRCOT_BINARY; + break; + default: NOT_REACHED(); break; diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index b81f252a23..940aefabd6 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -29,6 +29,7 @@ #include "waypoint_base.h" #include "depot_base.h" #include "error.h" +#include "cargotype.h" #include "table/sprites.h" extern uint ConvertSpeedToDisplaySpeed(uint speed); @@ -177,6 +178,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictI STR_TRACE_RESTRICT_VARIABLE_CURRENT_ORDER, STR_TRACE_RESTRICT_VARIABLE_NEXT_ORDER, STR_TRACE_RESTRICT_VARIABLE_LAST_VISITED_STATION, + STR_TRACE_RESTRICT_VARIABLE_CARGO, STR_TRACE_RESTRICT_VARIABLE_UNDEFINED, INVALID_STRING_ID, }; @@ -186,6 +188,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictI TRIT_COND_CURRENT_ORDER, TRIT_COND_NEXT_ORDER, TRIT_COND_LAST_STATION, + TRIT_COND_CARGO, TRIT_COND_UNDEFINED, }; static const TraceRestrictDropDownListSet set_cond = { @@ -195,12 +198,49 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictI return IsTraceRestrictTypeConditional(type) ? &set_cond : &set_action; } +static const TraceRestrictDropDownListSet *GetSortedCargoTypeDropDownListSet() +{ + static StringID cargo_list_str[NUM_CARGO + 1]; + static uint cargo_list_id[NUM_CARGO]; + static const TraceRestrictDropDownListSet cargo_list = { + cargo_list_str, cargo_list_id, + }; + + for (size_t i = 0; i < _sorted_standard_cargo_specs_size; ++i) { + const CargoSpec *cs = _sorted_cargo_specs[i]; + cargo_list_str[i] = cs->name; + cargo_list_id[i] = cs->Index(); + } + cargo_list_str[_sorted_standard_cargo_specs_size] = INVALID_STRING_ID; + + return &cargo_list; +} + +static const StringID _cargo_cond_ops_str[] = { + STR_TRACE_RESTRICT_CONDITIONAL_COMPARATOR_CARGO_EQUALS, + STR_TRACE_RESTRICT_CONDITIONAL_COMPARATOR_CARGO_NOT_EQUALS, + INVALID_STRING_ID, +}; +static const uint _cargo_cond_ops_val[] = { + TRCO_IS, + TRCO_ISNOT, +}; +static const TraceRestrictDropDownListSet _cargo_cond_ops = { + _cargo_cond_ops_str, _cargo_cond_ops_val, +}; + +static StringID GetCargoStringByID(CargoID cargo) +{ + const CargoSpec *cs = CargoSpec::Get(cargo); + return cs->IsValid() ? cs->name : STR_NEWGRF_INVALID_CARGO; +} + static StringID GetTypeString(TraceRestrictItemType type) { return GetDropDownStringByValue(GetTypeDropDownListSet(type), type); } -static const TraceRestrictDropDownListSet *GetCondOpDropDownListSet(TraceRestrictConditionOpType type) +static const TraceRestrictDropDownListSet *GetCondOpDropDownListSet(TraceRestrictTypePropertySet properties) { static const StringID str_long[] = { STR_TRACE_RESTRICT_CONDITIONAL_COMPARATOR_EQUALS, @@ -236,7 +276,9 @@ static const TraceRestrictDropDownListSet *GetCondOpDropDownListSet(TraceRestric str_short, val_short, }; - switch (type) { + if (properties.value_type == TRVT_CARGO_ID) return &_cargo_cond_ops; + + switch (properties.cond_type) { case TRCOT_NONE: return NULL; @@ -315,7 +357,7 @@ static void DrawInstructionStringConditionalCommon(TraceRestrictItem item, const assert(GetTraceRestrictCondFlags(item) <= TRCF_OR); SetDParam(0, _program_cond_type[GetTraceRestrictCondFlags(item)]); SetDParam(1, GetTypeString(GetTraceRestrictType(item))); - SetDParam(2, GetDropDownStringByValue(GetCondOpDropDownListSet(properties.cond_type), GetTraceRestrictCondOp(item))); + SetDParam(2, GetDropDownStringByValue(GetCondOpDropDownListSet(properties), GetTraceRestrictCondOp(item))); } static void DrawInstructionStringConditionalIntegerCommon(TraceRestrictItem item, const TraceRestrictTypePropertySet &properties) @@ -395,6 +437,14 @@ static void DrawInstructionString(TraceRestrictItem item, int y, bool selected, break; } + case TRVT_CARGO_ID: + instruction_string = STR_TRACE_RESTRICT_CONDITIONAL_CARGO; + assert(GetTraceRestrictCondFlags(item) <= TRCF_OR); + SetDParam(0, _program_cond_type[GetTraceRestrictCondFlags(item)]); + SetDParam(1, GetDropDownStringByValue(&_cargo_cond_ops, GetTraceRestrictCondOp(item))); + SetDParam(2, GetCargoStringByID(GetTraceRestrictValue(item))); + break; + default: NOT_REACHED(); break; @@ -582,7 +632,7 @@ public: case TR_WIDGET_COMPARATOR: { TraceRestrictItem item = this->GetSelected(); - const TraceRestrictDropDownListSet *list_set = GetCondOpDropDownListSet(GetTraceRestrictTypeProperties(item).cond_type); + const TraceRestrictDropDownListSet *list_set = GetCondOpDropDownListSet(GetTraceRestrictTypeProperties(item)); if (list_set) { this->ShowDropDownListWithValue(list_set, GetTraceRestrictCondOp(item), false, TR_WIDGET_COMPARATOR, 0, 0, 0); } @@ -601,8 +651,17 @@ public: case TR_WIDGET_VALUE_DROPDOWN: { TraceRestrictItem item = this->GetSelected(); - if (GetTraceRestrictTypeProperties(item).value_type == TRVT_DENY) { - this->ShowDropDownListWithValue(&_deny_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0); + switch (GetTraceRestrictTypeProperties(item).value_type) { + case TRVT_DENY: + this->ShowDropDownListWithValue(&_deny_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0); + break; + + case TRVT_CARGO_ID: + this->ShowDropDownListWithValue(GetSortedCargoTypeDropDownListSet(), GetTraceRestrictValue(item), true, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0); // current cargo is permitted to not be in list + break; + + default: + break; } break; } @@ -1185,7 +1244,7 @@ private: middle_sel->SetDisplayedPlane(DPM_COMPARATOR); this->EnableWidget(TR_WIDGET_COMPARATOR); - const TraceRestrictDropDownListSet *list_set = GetCondOpDropDownListSet(properties.cond_type); + const TraceRestrictDropDownListSet *list_set = GetCondOpDropDownListSet(properties); if (list_set) { this->GetWidget(TR_WIDGET_COMPARATOR)->widget_data = @@ -1210,6 +1269,13 @@ private: this->EnableWidget(TR_WIDGET_VALUE_DEST); break; + case TRVT_CARGO_ID: + right_sel->SetDisplayedPlane(DPR_VALUE_DROPDOWN); + this->EnableWidget(TR_WIDGET_VALUE_DROPDOWN); + this->GetWidget(TR_WIDGET_VALUE_DROPDOWN)->widget_data = + GetCargoStringByID(GetTraceRestrictValue(item)); + break; + default: break; }