From 1ee33c46ef749597253b32527a77b5ca5c561a74 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 30 Apr 2019 23:11:11 +0100 Subject: [PATCH] Linkgraph: Allow overriding distribution mode on a per-cargo basis, in game --- src/lang/english.txt | 5 ++ src/linkgraph/linkgraph_type.h | 2 + src/saveload/extended_ver_sl.cpp | 1 + src/saveload/extended_ver_sl.h | 1 + src/settings_gui.cpp | 69 ++++++++++++++- src/settings_type.h | 2 + src/table/settings.ini | 140 +++++++++++++++++++++++++++++++ 7 files changed, 219 insertions(+), 1 deletion(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index 366594149a..7067faa9b8 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1827,6 +1827,10 @@ STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED :Distribution mo STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_HELPTEXT :The ARMOURED cargo class contains valuables in the temperate, diamonds in the subtropical or gold in subarctic climate. NewGRFs may change that. "symmetric" means that roughly the same amount of that cargo will be sent from a station A to a station B as from B to A. "asymmetric" means that arbitrary amounts of that cargo can be sent in either direction. "manual" means that no automatic distribution will take place for that cargo. It is recommended to set this to asymmetric or manual when playing subarctic, as banks won't send any gold back to gold mines. For temperate and subtropical you can also choose symmetric as banks will send valuables back to the origin bank of some load of valuables. STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT :Distribution mode for other cargo classes: {STRING2} STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_HELPTEXT :"asymmetric" means that arbitrary amounts of cargo can be sent in either direction. "manual" means that no automatic distribution will take place for those cargoes. +STR_CONFIG_SETTING_DISTRIBUTION_PER_CARGO :Distribution mode override for this cargo: {STRING2} +STR_CONFIG_SETTING_DISTRIBUTION_PER_CARGO_PARAM :Distribution mode override for {STRING}: {STRING2} +STR_CONFIG_SETTING_DISTRIBUTION_PER_CARGO_HELPTEXT :"(default)" means that the distribution mode is the default for the class of this cargo. "symmetric" means that roughly the same number of cargo will go from a station A to a station B as from B to A. "asymmetric" means that arbitrary amounts of cargo can be sent in either direction. "manual" means that no automatic distribution will take place for this cargo. +STR_CONFIG_SETTING_DISTRIBUTION_PER_CARGO_DEFAULT :(default) STR_CONFIG_SETTING_LINKGRAPH_ACCURACY :Distribution accuracy: {STRING2} STR_CONFIG_SETTING_LINKGRAPH_ACCURACY_HELPTEXT :The higher you set this the more CPU time the calculation of the link graph will take. If it takes too long you may notice lag. If you set it to a low value, however, the distribution will be inaccurate, and you may notice cargo not being sent to the places you expect it to go. STR_CONFIG_SETTING_DEMAND_DISTANCE :Effect of distance on demands: {STRING2} @@ -1897,6 +1901,7 @@ STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES :{ORANGE}Authori STR_CONFIG_SETTING_ENVIRONMENT_TOWNS :{ORANGE}Towns STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES :{ORANGE}Industries STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST :{ORANGE}Cargo distribution +STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST_PER_CARGO_OVERRIDE :{ORANGE}Cargo distribution - per cargo overrides STR_CONFIG_SETTING_ENVIRONMENT_TREES :{ORANGE}Trees STR_CONFIG_SETTING_AI :{ORANGE}Competitors STR_CONFIG_SETTING_AI_NPC :{ORANGE}Computer players diff --git a/src/linkgraph/linkgraph_type.h b/src/linkgraph/linkgraph_type.h index 9ee50f956d..f23c7696b3 100644 --- a/src/linkgraph/linkgraph_type.h +++ b/src/linkgraph/linkgraph_type.h @@ -28,6 +28,8 @@ enum DistributionType : byte { DT_ASYMMETRIC_EQ = 20, ///< Asymmetric distribution (equal). Usually cargo will only travel in one direction. Attempt to distribute the same amount of cargo to each sink. DT_ASYMMETRIC_NEAR = 21, ///< Asymmetric distribution (nearest). Usually cargo will only travel in one direction. Attempt to distribute cargo to the nearest sink. + + DT_PER_CARGO_DEFAULT = 128, ///< Per cargo: Use default value }; /** diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index b008370bf1..770c4de77e 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -104,6 +104,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_CONSIST_SPEED_RD_FLAG, XSCF_NULL, 1, 1, "consist_speed_rd_flag", nullptr, nullptr, nullptr }, { XSLFI_SAVEGAME_UNIQUE_ID, XSCF_IGNORABLE_ALL, 1, 1, "savegame_unique_id", nullptr, nullptr, nullptr }, { XSLFI_RV_OVERTAKING, XSCF_NULL, 1, 1, "roadveh_overtaking", nullptr, nullptr, nullptr }, + { XSLFI_LINKGRAPH_MODES, XSCF_NULL, 1, 1, "linkgraph_modes", nullptr, nullptr, nullptr }, { XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker }; diff --git a/src/saveload/extended_ver_sl.h b/src/saveload/extended_ver_sl.h index e1027a1a82..d4da2269d7 100644 --- a/src/saveload/extended_ver_sl.h +++ b/src/saveload/extended_ver_sl.h @@ -71,6 +71,7 @@ enum SlXvFeatureIndex { XSLFI_CONSIST_SPEED_RD_FLAG, ///< Consist speed reduction flag XSLFI_SAVEGAME_UNIQUE_ID, ///< Savegame unique ID XSLFI_RV_OVERTAKING, ///< Roadvehicle overtaking + XSLFI_LINKGRAPH_MODES, ///< Linkgraph additional distribution modes XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index ce58a48a39..24fe154c61 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -792,12 +792,26 @@ struct SettingEntry : BaseSettingEntry { void SetValueDParams(uint first_param, int32 value) const; protected: + SettingEntry(const SettingDesc *setting, uint index); virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const; + virtual void DrawSettingString(uint left, uint right, int y, bool highlight, int32 value) const; private: bool IsVisibleByRestrictionMode(RestrictionMode mode) const; }; +/** Standard setting */ +struct CargoDestPerCargoSettingEntry : SettingEntry { + CargoID cargo; + + CargoDestPerCargoSettingEntry(CargoID cargo, const SettingDesc *setting, uint index); + virtual void Init(byte level = 0); + virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible); + +protected: + virtual void DrawSettingString(uint left, uint right, int y, bool highlight, int32 value) const; +}; + /** Containers for BaseSettingEntry */ struct SettingsContainer { typedef std::vector EntryVector; @@ -964,6 +978,13 @@ SettingEntry::SettingEntry(const char *name) this->index = 0; } +SettingEntry::SettingEntry(const SettingDesc *setting, uint index) +{ + this->name = nullptr; + this->setting = setting; + this->index = index; +} + /** * Initialization of a setting entry * @param level Page nesting level of this entry @@ -1173,8 +1194,46 @@ void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state, editable && value != (sdb->flags & SGF_0ISDISABLED ? 0 : sdb->min), editable && (uint32)value != sdb->max); } + this->DrawSettingString(text_left, text_right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, highlight, value); +} + +void SettingEntry::DrawSettingString(uint left, uint right, int y, bool highlight, int32 value) const +{ + const SettingDesc *sd = this->setting; + const SettingDescBase *sdb = &sd->desc; this->SetValueDParams(1, value); - DrawString(text_left, text_right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, sdb->str, highlight ? TC_WHITE : TC_LIGHT_BLUE); + DrawString(left, right, y, sdb->str, highlight ? TC_WHITE : TC_LIGHT_BLUE); +} + +/* == CargoDestPerCargoSettingEntry methods == */ + +CargoDestPerCargoSettingEntry::CargoDestPerCargoSettingEntry(CargoID cargo, const SettingDesc *setting, uint index) + : SettingEntry(setting, index), cargo(cargo) {} + +void CargoDestPerCargoSettingEntry::Init(byte level) +{ + BaseSettingEntry::Init(level); +} + +void CargoDestPerCargoSettingEntry::DrawSettingString(uint left, uint right, int y, bool highlight, int32 value) const +{ + const SettingDesc *sd = this->setting; + const SettingDescBase *sdb = &sd->desc; + assert(sdb->str == STR_CONFIG_SETTING_DISTRIBUTION_PER_CARGO); + SetDParam(0, CargoSpec::Get(this->cargo)->name); + SetDParam(1, highlight ? STR_ORANGE_STRING1_WHITE : STR_ORANGE_STRING1_LTBLUE); + this->SetValueDParams(2, value); + DrawString(left, right, y, STR_CONFIG_SETTING_DISTRIBUTION_PER_CARGO_PARAM, highlight ? TC_WHITE : TC_LIGHT_BLUE); +} + +bool CargoDestPerCargoSettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible) +{ + if (!HasBit(_cargo_mask, this->cargo)) { + SETBITS(this->flags, SEF_FILTERED); + return false; + } else { + return SettingEntry::UpdateFilterState(filter, force_visible); + } } /* == SettingsContainer methods == */ @@ -1857,6 +1916,14 @@ static SettingsContainer &GetSettingsTree() cdist->Add(new SettingEntry("linkgraph.distribution_mail")); cdist->Add(new SettingEntry("linkgraph.distribution_armoured")); cdist->Add(new SettingEntry("linkgraph.distribution_default")); + SettingsPage *cdist_override = cdist->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST_PER_CARGO_OVERRIDE)); + { + uint index = 0; + const SettingDesc *setting = GetSettingFromName("linkgraph.distribution_per_cargo[0]", &index); + for (CargoID c = 0; c < NUM_CARGO; c++) { + cdist_override->Add(new CargoDestPerCargoSettingEntry(c, setting + c, index + c)); + } + } cdist->Add(new SettingEntry("linkgraph.accuracy")); cdist->Add(new SettingEntry("linkgraph.demand_distance")); cdist->Add(new SettingEntry("linkgraph.demand_size")); diff --git a/src/settings_type.h b/src/settings_type.h index 7851651645..fee6de8853 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -588,12 +588,14 @@ struct LinkGraphSettings { DistributionType distribution_mail; ///< distribution type for mail DistributionType distribution_armoured; ///< distribution type for armoured cargo class DistributionType distribution_default; ///< distribution type for all other goods + DistributionType distribution_per_cargo[NUM_CARGO]; ///< per cargo distribution types uint8 accuracy; ///< accuracy when calculating things on the link graph. low accuracy => low running time uint8 demand_size; ///< influence of supply ("station size") on the demand function uint8 demand_distance; ///< influence of distance between stations on the demand function uint8 short_path_saturation; ///< percentage up to which short paths are saturated before saturating most capacious paths inline DistributionType GetDistributionType(CargoID cargo) const { + if (this->distribution_per_cargo[cargo] != DT_PER_CARGO_DEFAULT) return this->distribution_per_cargo[cargo]; if (IsCargoInClass(cargo, CC_PASSENGERS)) return this->distribution_pax; if (IsCargoInClass(cargo, CC_MAIL)) return this->distribution_mail; if (IsCargoInClass(cargo, CC_ARMOURED)) return this->distribution_armoured; diff --git a/src/table/settings.ini b/src/table/settings.ini index 03f1f219ab..d455c38083 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -81,6 +81,15 @@ static const SettingDescEnumEntry _linkgraph_mode_asymmetric[] = { { DT_ASYMMETRIC_NEAR, STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC_NEAREST }, { 0, STR_NULL } }; +static const SettingDescEnumEntry _linkgraph_mode_per_cargo[] = { +{ DT_PER_CARGO_DEFAULT, STR_CONFIG_SETTING_DISTRIBUTION_PER_CARGO_DEFAULT }, +{ DT_MANUAL, STR_CONFIG_SETTING_DISTRIBUTION_MANUAL }, +{ DT_SYMMETRIC, STR_CONFIG_SETTING_DISTRIBUTION_SYMMETRIC }, +{ DT_ASYMMETRIC, STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC }, +{ DT_ASYMMETRIC_EQ, STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC_EQ }, +{ DT_ASYMMETRIC_NEAR, STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC_NEAREST }, +{ 0, STR_NULL } +}; /* Some settings do not need to be synchronised when playing in multiplayer. * These include for example the GUI settings and will not be saved with the @@ -113,6 +122,8 @@ SDT_NULL = SDT_NULL($length, $from, $to, $extver), SDT_XREF = SDT_XREF( $from, $to, $extver, $xref), SDT_END = SDT_END() +SDT_LINKGRAPH_PER_CARGO = SDT_ENUM(GameSettings, linkgraph.distribution_per_cargo[$linkgraph_cargo], SLE_UINT8, $flags | SLF_NOT_IN_CONFIG, $guiflags | SGF_NO_NEWGAME, DT_PER_CARGO_DEFAULT, STR_CONFIG_SETTING_DISTRIBUTION_PER_CARGO, STR_CONFIG_SETTING_DISTRIBUTION_PER_CARGO_HELPTEXT, $proc, $from, $to, SC_EXPERT, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_MODES), nullptr, _linkgraph_mode_per_cargo), + [defaults] flags = 0 guiflags = 0 @@ -870,6 +881,135 @@ enumlist = _linkgraph_mode_asymmetric str = STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT strhelp = STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_HELPTEXT +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 0 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 1 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 2 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 3 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 4 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 5 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 6 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 7 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 8 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 9 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 10 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 11 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 12 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 13 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 14 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 15 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 16 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 17 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 18 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 19 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 20 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 21 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 22 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 23 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 24 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 25 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 26 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 27 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 28 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 29 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 30 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 31 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 32 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 33 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 34 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 35 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 36 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 37 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 38 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 39 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 40 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 41 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 42 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 43 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 44 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 45 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 46 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 47 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 48 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 49 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 50 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 51 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 52 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 53 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 54 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 55 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 56 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 57 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 58 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 59 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 60 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 61 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 62 +[SDT_LINKGRAPH_PER_CARGO] +linkgraph_cargo = 63 + [SDT_VAR] base = GameSettings var = linkgraph.accuracy