diff --git a/src/lang/english.txt b/src/lang/english.txt index 3b04fddbf4..a80d411140 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2406,6 +2406,7 @@ STR_TRACE_RESTRICT_CONDITIONAL_TILE_INDEX :{STRING} {STRIN 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} +STR_TRACE_RESTRICT_PF_PENALTY_ITEM_PRESET :Add {STRING} pathfinder penalty STR_TRACE_RESTRICT_WHITE :{WHITE} STR_TRACE_RESTRICT_START :Start STR_TRACE_RESTRICT_END :End @@ -2413,6 +2414,10 @@ STR_TRACE_RESTRICT_PF_DENY :Deny STR_TRACE_RESTRICT_PF_ALLOW :Allow STR_TRACE_RESTRICT_PF_ALLOW_LONG :Allow (cancel previous Deny) STR_TRACE_RESTRICT_PF_PENALTY :Penalty +STR_TRACE_RESTRICT_PF_VALUE_SMALL :small +STR_TRACE_RESTRICT_PF_VALUE_MEDIUM :medium +STR_TRACE_RESTRICT_PF_VALUE_LARGE :large +STR_TRACE_RESTRICT_PF_VALUE_CUSTOM :custom STR_TRACE_RESTRICT_DIRECTION_FRONT :front STR_TRACE_RESTRICT_DIRECTION_BACK :back STR_TRACE_RESTRICT_DIRECTION_NE :north-east diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index d5ee9aac59..5b9ee86c3a 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -66,6 +66,23 @@ INSTANTIATE_POOL_METHODS(TraceRestrictProgram) */ TraceRestrictMapping _tracerestrictprogram_mapping; +/** + * Default value for pathfinder penalty instructions + */ +static const uint16 _tracerestrict_penalty_item_default_value = 500; + +/** + * List of pre-defined pathfinder penalty values + * This is indexed by TraceRestrictPathfinderPenaltyPresetIndex + */ +const uint16 _tracerestrict_pathfinder_penalty_preset_values[] = { + 500, + 2000, + 8000, +}; + +assert_compile(lengthof(_tracerestrict_pathfinder_penalty_preset_values) == TRPPPI_END); + /** * This should be used when all pools have been or are immediately about to be also cleared * Calling this at other times will leave dangling refcounts @@ -347,9 +364,25 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp out.flags |= TRPRF_DENY; } break; + case TRIT_PF_PENALTY: - out.penalty += GetTraceRestrictValue(item); + switch (static_cast(GetTraceRestrictAuxField(item))) { + case TRPPAF_VALUE: + out.penalty += GetTraceRestrictValue(item); + break; + + case TRPPAF_PRESET: { + uint16 index = GetTraceRestrictValue(item); + assert(index < TRPPPI_END); + out.penalty += _tracerestrict_pathfinder_penalty_preset_values[index]; + break; + } + + default: + NOT_REACHED(); + } break; + default: NOT_REACHED(); } @@ -490,6 +523,11 @@ void SetTraceRestrictValueDefault(TraceRestrictItem &item, TraceRestrictValueTyp SetTraceRestrictAuxField(item, 0); break; + case TRVT_PF_PENALTY: + SetTraceRestrictValue(item, TRPPPI_SMALL); + SetTraceRestrictAuxField(item, TRPPAF_PRESET); + break; + default: NOT_REACHED(); break; diff --git a/src/tracerestrict.h b/src/tracerestrict.h index 415eb8f7b3..6913234bc7 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -34,6 +34,8 @@ typedef Pool TraceRest /** The actual pool for trace restrict nodes. */ extern TraceRestrictProgramPool _tracerestrictprogram_pool; +extern const uint16 _tracerestrict_pathfinder_penalty_preset_values[]; + #define FOR_ALL_TRACE_RESTRICT_PROGRAMS_FROM(var, start) FOR_ALL_ITEMS_FROM(TraceRestrictProgram, tr_index, var, start) #define FOR_ALL_TRACE_RESTRICT_PROGRAMS(var) FOR_ALL_TRACE_RESTRICT_PROGRAMS_FROM(var, 0) @@ -165,6 +167,26 @@ enum TraceRestrictOrderCondAuxField { /* space up to 3 */ }; +/** + * TraceRestrictItem auxiliary type field, for order type conditionals + */ +enum TraceRestrictPathfinderPenaltyAuxField { + TRPPAF_VALUE = 0, ///< value field is a the pathfinder penalty to use + TRPPAF_PRESET = 1, ///< value field is a pathfinder penalty prefix index: TraceRestrictPathfinderPenaltyPresetIndex + /* space up to 3 */ +}; + +/** + * TraceRestrictItem pathfinder penalty preset index + * This may not be shortened, only lengthened, as preset indexes are stored in save games + */ +enum TraceRestrictPathfinderPenaltyPresetIndex { + TRPPPI_SMALL = 0, ///< small preset value + TRPPPI_MEDIUM = 1, ///< medium preset value + TRPPPI_LARGE = 2, ///< large preset value + TRPPPI_END, ///< end value +}; + /** * Enumeration for TraceRestrictProgramResult::flags */ @@ -369,6 +391,7 @@ enum TraceRestrictValueType { TRVT_CARGO_ID = 6, ///< takes a CargoID TRVT_DIRECTION = 7, ///< takes a TraceRestrictDirectionTypeSpecialValue TRVT_TILE_INDEX = 8, ///< takes a TileIndex in the next item slot + TRVT_PF_PENALTY = 9, ///< takes a pathfinder penalty value or preset index, as per the auxiliary field as type: TraceRestrictPathfinderPenaltyAuxField }; /** @@ -437,7 +460,7 @@ static inline TraceRestrictTypePropertySet GetTraceRestrictTypeProperties(TraceR } else { out.cond_type = TRCOT_NONE; if (GetTraceRestrictType(item) == TRIT_PF_PENALTY) { - out.value_type = TRVT_INT; + out.value_type = TRVT_PF_PENALTY; } else if (GetTraceRestrictType(item) == TRIT_PF_DENY) { out.value_type = TRVT_DENY; } else { diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index 215e753d80..427bad78cb 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -372,7 +372,7 @@ static bool IsIntegerValueType(TraceRestrictValueType type) } /** - * Convert integer values between internal units and display units + * Convert integer values or custom penalty values between internal units and display units */ static uint ConvertIntegerValue(TraceRestrictValueType type, uint in, bool to_display) { @@ -385,6 +385,9 @@ static uint ConvertIntegerValue(TraceRestrictValueType type, uint in, bool to_di ? ConvertSpeedToDisplaySpeed(in) * 10 / 16 : ConvertDisplaySpeedToSpeed(in) * 16 / 10; + case TRVT_PF_PENALTY: + return in; + default: NOT_REACHED(); return 0; @@ -424,6 +427,41 @@ static const TraceRestrictDropDownListSet _condflags_dropdown = { _condflags_dropdown_str, _condflags_dropdown_val, }; +static const StringID _pf_penalty_dropdown_str[] = { + STR_TRACE_RESTRICT_PF_VALUE_SMALL, + STR_TRACE_RESTRICT_PF_VALUE_MEDIUM, + STR_TRACE_RESTRICT_PF_VALUE_LARGE, + STR_TRACE_RESTRICT_PF_VALUE_CUSTOM, + INVALID_STRING_ID, +}; +static const uint _pf_penalty_dropdown_val[] = { + TRPPPI_SMALL, + TRPPPI_MEDIUM, + TRPPPI_LARGE, + TRPPPI_END, // this is a placeholder for "custom" +}; +/** Pathfinder penalty dropdown set */ +static const TraceRestrictDropDownListSet _pf_penalty_dropdown = { + _pf_penalty_dropdown_str, _pf_penalty_dropdown_val, +}; + +static uint GetPathfinderPenaltyDropdownIndex(TraceRestrictItem item) +{ + switch (static_cast(GetTraceRestrictAuxField(item))) { + case TRPPAF_VALUE: + return TRPPPI_END; + + case TRPPAF_PRESET: { + uint16 index = GetTraceRestrictValue(item); + assert(index < TRPPPI_END); + return index; + } + + default: + NOT_REACHED(); + } +} + /** Common function for drawing an ordinary conditional instruction */ static void DrawInstructionStringConditionalCommon(TraceRestrictItem item, const TraceRestrictTypePropertySet &properties) { @@ -583,8 +621,23 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric break; case TRIT_PF_PENALTY: - instruction_string = STR_TRACE_RESTRICT_PF_PENALTY_ITEM; - SetDParam(0, GetTraceRestrictValue(item)); + switch (static_cast(GetTraceRestrictAuxField(item))) { + case TRPPAF_VALUE: + instruction_string = STR_TRACE_RESTRICT_PF_PENALTY_ITEM; + SetDParam(0, GetTraceRestrictValue(item)); + break; + + case TRPPAF_PRESET: { + instruction_string = STR_TRACE_RESTRICT_PF_PENALTY_ITEM_PRESET; + uint16 index = GetTraceRestrictValue(item); + assert(index < TRPPPI_END); + SetDParam(0, _pf_penalty_dropdown_str[index]); + break; + } + + default: + NOT_REACHED(); + } break; default: @@ -775,6 +828,10 @@ public: this->ShowDropDownListWithValue(&_direction_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0); break; + case TRVT_PF_PENALTY: + this->ShowDropDownListWithValue(&_pf_penalty_dropdown, GetPathfinderPenaltyDropdownIndex(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0); + break; + default: break; } @@ -820,7 +877,7 @@ public: TraceRestrictItem item = GetSelected(); TraceRestrictValueType type = GetTraceRestrictTypeProperties(item).value_type; - if (!IsIntegerValueType(type)) { + if (!IsIntegerValueType(type) && type != TRVT_PF_PENALTY) { return; } @@ -831,6 +888,10 @@ public: return; } + if (type == TRVT_PF_PENALTY) { + SetTraceRestrictAuxField(item, TRPPAF_VALUE); + } + SetTraceRestrictValue(item, value); TraceRestrictDoCommandP(tile, track, TRDCT_MODIFY_ITEM, this->selected_instruction - 1, item, STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM); } @@ -902,7 +963,24 @@ public: } case TR_WIDGET_VALUE_DROPDOWN: { - SetTraceRestrictValue(item, value); + if (GetTraceRestrictTypeProperties(item).value_type == TRVT_PF_PENALTY) { + if (value == TRPPPI_END) { + uint16 penalty_value; + if (GetTraceRestrictAuxField(item) == TRPPAF_PRESET) { + penalty_value = _tracerestrict_pathfinder_penalty_preset_values[GetTraceRestrictValue(item)]; + } else { + penalty_value = GetTraceRestrictValue(item); + } + SetDParam(0, penalty_value); + ShowQueryString(STR_JUST_INT, STR_TRACE_RESTRICT_VALUE_CAPTION, 10, this, CS_NUMERAL, QSF_NONE); + return; + } else { + SetTraceRestrictValue(item, value); + SetTraceRestrictAuxField(item, TRPPAF_PRESET); + } + } else { + SetTraceRestrictValue(item, value); + } TraceRestrictDoCommandP(this->tile, this->track, TRDCT_MODIFY_ITEM, this->selected_instruction - 1, item, STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM); break; } @@ -1152,6 +1230,15 @@ public: } break; } + + case TR_WIDGET_VALUE_DROPDOWN: { + TraceRestrictItem item = this->GetSelected(); + if (GetTraceRestrictTypeProperties(item).value_type == TRVT_PF_PENALTY && + GetTraceRestrictAuxField(item) == TRPPAF_VALUE) { + SetDParam(0, GetTraceRestrictValue(item)); + } + break; + } } } @@ -1475,6 +1562,17 @@ private: this->EnableWidget(TR_WIDGET_VALUE_SIGNAL); break; + case TRVT_PF_PENALTY: + right_sel->SetDisplayedPlane(DPR_VALUE_DROPDOWN); + this->EnableWidget(TR_WIDGET_VALUE_DROPDOWN); + if (GetTraceRestrictAuxField(item) == TRPPAF_VALUE) { + this->GetWidget(TR_WIDGET_VALUE_DROPDOWN)->widget_data = STR_BLACK_COMMA; + } else { + this->GetWidget(TR_WIDGET_VALUE_DROPDOWN)->widget_data = + GetDropDownStringByValue(&_pf_penalty_dropdown, GetPathfinderPenaltyDropdownIndex(item)); + } + break; + default: break; }