@@ -1129,32 +1129,35 @@ STR_TERRAIN_TYPE_CUSTOM_VALUE
STR_CITY_APPROVAL_PERMISSIVE :Permissive
STR_CITY_APPROVAL_TOLERANT :Tolerant
STR_CITY_APPROVAL_HOSTILE :Hostile
STR_WARNING_NO_SUITABLE_AI :{WHITE}No suitable AIs available...{}You can download several AIs via the 'Online Content' system
# Settings tree window
STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Settings
STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Filter string:
STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Expand all
STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Collapse all
STR_CONFIG_SETTING_RESET_ALL :{BLACK}Reset all values
STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(no explanation available)
STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Default value: {ORANGE}{STRING1}
STR_CONFIG_SETTING_TYPE :{LTBLUE}Setting type: {ORANGE}{STRING}
STR_CONFIG_SETTING_TYPE_CLIENT :Client setting (not stored in saves; affects all games)
STR_CONFIG_SETTING_TYPE_GAME_MENU :Game setting (stored in saves; affects only new games)
STR_CONFIG_SETTING_TYPE_GAME_INGAME :Game setting (stored in save; affects only current game)
STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Company setting (stored in saves; affects only new games)
STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Company setting (stored in save; affects only current company)
STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}Caution!
STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}This action will reset all game settings to their default values.{}Are you sure you want to proceed?
STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Category:
STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Type:
STR_CONFIG_SETTING_RESTRICT_DROPDOWN_HELPTEXT :{BLACK}Restricts the list below using predefined filters
STR_CONFIG_SETTING_RESTRICT_BASIC :Basic (show only important settings)
STR_CONFIG_SETTING_RESTRICT_ADVANCED :Advanced (show most settings)
STR_CONFIG_SETTING_RESTRICT_ALL :Expert (show all settings, including weird ones)
STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT :Settings with a different value than the default
STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW :Settings with a different value than your new-game settings
STR_CONFIG_SETTING_TYPE_DROPDOWN_HELPTEXT :{BLACK}Restricts the list below to certain setting types
STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL :All setting types
@@ -724,24 +724,25 @@ struct SettingFilter {
/** Data structure describing a single setting in a tab */
struct BaseSettingEntry {
byte flags; ///< Flags of the setting entry. @see SettingEntryFlags
byte level; ///< Nesting level of this setting entry
BaseSettingEntry() : flags(0), level(0) {}
virtual ~BaseSettingEntry() {}
virtual void Init(byte level = 0);
virtual void FoldAll() {}
virtual void UnFoldAll() {}
virtual void ResetAll() = 0;
/**
* Set whether this is the last visible entry of the parent node.
* @param last_field Value to set
*/
void SetLastField(bool last_field) { if (last_field) SETBITS(this->flags, SEF_LAST_FIELD); else CLRBITS(this->flags, SEF_LAST_FIELD); }
virtual uint Length() const = 0;
virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const {}
virtual bool IsVisible(const BaseSettingEntry *item) const;
virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
virtual uint GetMaxHelpHeight(int maxw) { return 0; }
@@ -760,24 +761,25 @@ protected:
virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const = 0;
};
/** Standard setting */
struct SettingEntry : BaseSettingEntry {
const char *name; ///< Name of the setting
const SettingDesc *setting; ///< Setting description of the setting
uint index; ///< Index of the setting in the settings table
SettingEntry(const char *name);
virtual void ResetAll();
virtual uint Length() const;
virtual uint GetMaxHelpHeight(int maxw);
virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible);
void SetButtons(byte new_val);
* Get the help text of a single setting.
* @return The requested help text.
inline StringID GetHelpText() const
{
@@ -797,46 +799,48 @@ private:
struct SettingsContainer {
typedef std::vector<BaseSettingEntry*> EntryVector;
EntryVector entries; ///< Settings on this page
template<typename T>
T *Add(T *item)
this->entries.push_back(item);
return item;
}
void Init(byte level = 0);
void ResetAll();
void FoldAll();
void UnFoldAll();
uint Length() const;
void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
bool IsVisible(const BaseSettingEntry *item) const;
BaseSettingEntry *FindEntry(uint row, uint *cur_row);
uint GetMaxHelpHeight(int maxw);
bool UpdateFilterState(SettingFilter &filter, bool force_visible);
uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row = 0, uint parent_last = 0) const;
/** Data structure describing one page of settings in the settings window. */
struct SettingsPage : BaseSettingEntry, SettingsContainer {
StringID title; ///< Title of the sub-page
bool folded; ///< Sub-page is folded (not visible except for its title)
SettingsPage(StringID title);
virtual void FoldAll();
virtual void UnFoldAll();
virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
virtual uint GetMaxHelpHeight(int maxw) { return SettingsContainer::GetMaxHelpHeight(maxw); }
virtual uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row = 0, uint parent_last = 0) const;
@@ -961,24 +965,31 @@ SettingEntry::SettingEntry(const char *n
* Initialization of a setting entry
* @param level Page nesting level of this entry
void SettingEntry::Init(byte level)
BaseSettingEntry::Init(level);
this->setting = GetSettingFromName(this->name, &this->index);
assert(this->setting != nullptr);
/* Sets the given setting entry to its default value */
void SettingEntry::ResetAll()
int32 default_value = ReadValue(&this->setting->desc.def, this->setting->save.conv);
SetSettingValue(this->index, default_value);
* Set the button-depressed flags (#SEF_LEFT_DEPRESSED and #SEF_RIGHT_DEPRESSED) to a specified value
* @param new_val New value for the button flags
* @see SettingEntryFlags
void SettingEntry::SetButtons(byte new_val)
assert((new_val & ~SEF_BUTTONS_MASK) == 0); // Should not touch any flags outside the buttons
this->flags = (this->flags & ~SEF_BUTTONS_MASK) | new_val;
/** Return number of rows needed to display the (filtered) entry */
@@ -1072,25 +1083,24 @@ bool SettingEntry::UpdateFilterState(Set
visible = false;
if (!this->IsVisibleByRestrictionMode(filter.mode)) {
while (filter.min_cat < RM_ALL && (filter.min_cat == filter.mode || !this->IsVisibleByRestrictionMode(filter.min_cat))) filter.min_cat++;
if (!visible) SETBITS(this->flags, SEF_FILTERED);
return visible;
static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd)
if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) {
return GetVariableAddress(&Company::Get(_local_company)->settings, &sd->save);
} else {
return GetVariableAddress(&_settings_client.company, &sd->save);
return GetVariableAddress(settings_ptr, &sd->save);
@@ -1163,24 +1173,32 @@ void SettingEntry::DrawSetting(GameSetti
* Initialization of an entire setting page
* @param level Nesting level of this page (internal variable, do not provide a value for it when calling)
void SettingsContainer::Init(byte level)
for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
(*it)->Init(level);
/** Resets all settings to their default values */
void SettingsContainer::ResetAll()
for (auto settings_entry : this->entries) {
settings_entry->ResetAll();
/** Recursively close all folds of sub-pages */
void SettingsContainer::FoldAll()
(*it)->FoldAll();
/** Recursively open all folds of sub-pages */
void SettingsContainer::UnFoldAll()
@@ -1314,24 +1332,32 @@ SettingsPage::SettingsPage(StringID titl
void SettingsPage::Init(byte level)
SettingsContainer::Init(level + 1);
void SettingsPage::ResetAll()
/** Recursively close all (filtered) folds of sub-pages */
void SettingsPage::FoldAll()
if (this->IsFiltered()) return;
this->folded = true;
SettingsContainer::FoldAll();
/** Recursively open all (filtered) folds of sub-pages */
void SettingsPage::UnFoldAll()
@@ -1785,24 +1811,38 @@ static const StringID _game_settings_res
STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW, // RM_CHANGED_AGAINST_NEW
static_assert(lengthof(_game_settings_restrict_dropdown) == RM_END);
/** Warnings about hidden search results. */
enum WarnHiddenResult {
WHR_NONE, ///< Nothing was filtering matches away.
WHR_CATEGORY, ///< Category setting filtered matches away.
WHR_TYPE, ///< Type setting filtered matches away.
WHR_CATEGORY_TYPE, ///< Both category and type settings filtered matches away.
* Callback function for the reset all settings button
* @param w Window which is calling this callback
* @param confirmed boolean value, true when yes was clicked, false otherwise
static void ResetAllSettingsConfirmationCallback(Window *w, bool confirmed)
if (confirmed) {
GetSettingsTree().ResetAll();
GetSettingsTree().FoldAll();
w->InvalidateData();
/** Window to edit settings of the game. */
struct GameSettingsWindow : Window {
static const int SETTINGTREE_LEFT_OFFSET = 5; ///< Position of left edge of setting values
static const int SETTINGTREE_RIGHT_OFFSET = 5; ///< Position of right edge of setting values
static const int SETTINGTREE_TOP_OFFSET = 5; ///< Position of top edge of setting values
static const int SETTINGTREE_BOTTOM_OFFSET = 5; ///< Position of bottom edge of setting values
static GameSettings *settings_ptr; ///< Pointer to the game settings being displayed and modified.
SettingEntry *valuewindow_entry; ///< If non-nullptr, pointer to setting for which a value-entering window has been opened.
SettingEntry *clicked_entry; ///< If non-nullptr, pointer to a clicked numeric setting (with a depressed left or right button).
SettingEntry *last_clicked; ///< If non-nullptr, pointer to the last clicked setting.
@@ -2022,24 +2062,33 @@ struct GameSettingsWindow : Window {
case WID_GS_EXPAND_ALL:
this->manually_changed_folding = true;
GetSettingsTree().UnFoldAll();
this->InvalidateData();
break;
case WID_GS_COLLAPSE_ALL:
case WID_GS_RESET_ALL:
ShowQuery(
STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION,
STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT,
this,
ResetAllSettingsConfirmationCallback
);
case WID_GS_RESTRICT_DROPDOWN: {
DropDownList list = this->BuildDropDownList(widget);
if (!list.empty()) {
ShowDropDownList(this, std::move(list), this->filter.mode, widget);
case WID_GS_TYPE_DROPDOWN: {
ShowDropDownList(this, std::move(list), this->filter.type, widget);
@@ -2378,24 +2427,25 @@ static const NWidgetPart _nested_setting
EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_PANEL, COLOUR_MAUVE, WID_GS_OPTIONSPANEL), SetMinimalSize(400, 174), SetScrollbar(WID_GS_SCROLLBAR), EndContainer(),
NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_GS_SCROLLBAR),
NWidget(WWT_PANEL, COLOUR_MAUVE), SetMinimalSize(400, 40),
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GS_HELP_TEXT), SetMinimalSize(300, 25), SetFill(1, 1), SetResize(1, 0),
SetPadding(WD_FRAMETEXT_TOP, WD_FRAMETEXT_RIGHT, WD_FRAMETEXT_BOTTOM, WD_FRAMETEXT_LEFT),
NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_EXPAND_ALL), SetDataTip(STR_CONFIG_SETTING_EXPAND_ALL, STR_NULL),
NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_COLLAPSE_ALL), SetDataTip(STR_CONFIG_SETTING_COLLAPSE_ALL, STR_NULL),
NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_RESET_ALL), SetDataTip(STR_CONFIG_SETTING_RESET_ALL, STR_NULL),
NWidget(WWT_PANEL, COLOUR_MAUVE), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
static WindowDesc _settings_selection_desc(
WDP_CENTER, "settings", 510, 450,
WC_GAME_OPTIONS, WC_NONE,
0,
_nested_settings_selection_widgets, lengthof(_nested_settings_selection_widgets)
@@ -35,24 +35,25 @@ enum GameOptionsWidgets {
WID_GO_VIDEO_ACCEL_BUTTON, ///< Toggle for video acceleration.
WID_GO_REFRESH_RATE_DROPDOWN, ///< Dropdown for all available refresh rates.
/** Widgets of the #GameSettingsWindow class. */
enum GameSettingsWidgets {
WID_GS_FILTER, ///< Text filter.
WID_GS_OPTIONSPANEL, ///< Panel widget containing the option lists.
WID_GS_SCROLLBAR, ///< Scrollbar.
WID_GS_HELP_TEXT, ///< Information area to display help text of the selected option.
WID_GS_EXPAND_ALL, ///< Expand all button.
WID_GS_COLLAPSE_ALL, ///< Collapse all button.
WID_GS_RESET_ALL, ///< Reset all button.
WID_GS_RESTRICT_CATEGORY, ///< Label upfront to the category drop-down box to restrict the list of settings to show
WID_GS_RESTRICT_TYPE, ///< Label upfront to the type drop-down box to restrict the list of settings to show
WID_GS_RESTRICT_DROPDOWN, ///< The drop down box to restrict the list of settings
WID_GS_TYPE_DROPDOWN, ///< The drop down box to choose client/game/company/all settings
/** Widgets of the #CustomCurrencyWindow class. */
enum CustomCurrencyWidgets {
WID_CC_RATE_DOWN, ///< Down button.
WID_CC_RATE_UP, ///< Up button.
WID_CC_RATE, ///< Rate of currency.
WID_CC_SEPARATOR_EDIT, ///< Separator edit button.
Status change: