diff --git a/src/genworld.h b/src/genworld.h index 71dae3f365..e6def69444 100644 --- a/src/genworld.h +++ b/src/genworld.h @@ -42,6 +42,8 @@ enum TgenSmoothness { TGEN_SMOOTHNESS_END, ///< Used to iterate. }; +static const uint CUSTOM_TERRAIN_TYPE_NUMBER_DIFFICULTY = 5; ///< Value for custom terrain type in difficulty settings. + static const uint CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY = 4; ///< Value for custom sea level in difficulty settings. static const uint CUSTOM_SEA_LEVEL_MIN_PERCENTAGE = 1; ///< Minimum percentage a user can specify for custom sea level. static const uint CUSTOM_SEA_LEVEL_MAX_PERCENTAGE = 90; ///< Maximum percentage a user can specify for custom sea level. diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp index f59e0ae46f..46f2eac246 100644 --- a/src/genworld_gui.cpp +++ b/src/genworld_gui.cpp @@ -347,7 +347,7 @@ static DropDownList BuildTownNameDropDown() } -static const StringID _elevations[] = {STR_TERRAIN_TYPE_VERY_FLAT, STR_TERRAIN_TYPE_FLAT, STR_TERRAIN_TYPE_HILLY, STR_TERRAIN_TYPE_MOUNTAINOUS, STR_TERRAIN_TYPE_ALPINIST, INVALID_STRING_ID}; +static const StringID _elevations[] = {STR_TERRAIN_TYPE_VERY_FLAT, STR_TERRAIN_TYPE_FLAT, STR_TERRAIN_TYPE_HILLY, STR_TERRAIN_TYPE_MOUNTAINOUS, STR_TERRAIN_TYPE_ALPINIST, STR_TERRAIN_TYPE_CUSTOM, INVALID_STRING_ID}; static const StringID _sea_lakes[] = {STR_SEA_LEVEL_VERY_LOW, STR_SEA_LEVEL_LOW, STR_SEA_LEVEL_MEDIUM, STR_SEA_LEVEL_HIGH, STR_SEA_LEVEL_CUSTOM, INVALID_STRING_ID}; static const StringID _rivers[] = {STR_RIVERS_NONE, STR_RIVERS_FEW, STR_RIVERS_MODERATE, STR_RIVERS_LOT, INVALID_STRING_ID}; static const StringID _smoothness[] = {STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH, STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_SMOOTH, STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_ROUGH, STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_ROUGH, INVALID_STRING_ID}; @@ -378,8 +378,9 @@ struct GenerateLandscapeWindow : public Window { this->SetWidgetDisabledState(WID_GL_TOWN_PULLDOWN, _game_mode == GM_EDITOR); this->SetWidgetDisabledState(WID_GL_INDUSTRY_PULLDOWN, _game_mode == GM_EDITOR); - /* In case the map_height_limit is changed, clamp heightmap_height. */ + /* In case the map_height_limit is changed, clamp heightmap_height and custom_terrain_type. */ _settings_newgame.game_creation.heightmap_height = Clamp(_settings_newgame.game_creation.heightmap_height, MIN_HEIGHTMAP_HEIGHT, GetMapHeightLimit()); + _settings_newgame.game_creation.custom_terrain_type = Clamp(_settings_newgame.game_creation.custom_terrain_type, MIN_CUSTOM_TERRAIN_TYPE, GetMapHeightLimit()); this->OnInvalidateData(); } @@ -417,7 +418,14 @@ struct GenerateLandscapeWindow : public Window { case WID_GL_INDUSTRY_PULLDOWN: SetDParam(0, _game_mode == GM_EDITOR ? STR_CONFIG_SETTING_OFF : _num_inds[_settings_newgame.difficulty.industry_density]); break; case WID_GL_LANDSCAPE_PULLDOWN: SetDParam(0, _landscape[_settings_newgame.game_creation.land_generator]); break; - case WID_GL_TERRAIN_PULLDOWN: SetDParam(0, _elevations[_settings_newgame.difficulty.terrain_type]); break; + case WID_GL_TERRAIN_PULLDOWN: + if (_settings_newgame.difficulty.terrain_type == CUSTOM_TERRAIN_TYPE_NUMBER_DIFFICULTY) { + SetDParam(0, STR_TERRAIN_TYPE_CUSTOM_VALUE); + SetDParam(1, _settings_newgame.game_creation.custom_terrain_type); + } else { + SetDParam(0, _elevations[_settings_newgame.difficulty.terrain_type]); break; + } + break; case WID_GL_WATER_PULLDOWN: if (_settings_newgame.difficulty.quantity_sea_lakes == CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY) { @@ -511,10 +519,14 @@ struct GenerateLandscapeWindow : public Window { this->SetWidgetDisabledState(WID_GL_DESERT_COVERAGE_DOWN, _settings_newgame.game_creation.desert_coverage <= 0 || _settings_newgame.game_creation.landscape != LT_TROPIC); this->SetWidgetDisabledState(WID_GL_DESERT_COVERAGE_UP, _settings_newgame.game_creation.desert_coverage >= 100 || _settings_newgame.game_creation.landscape != LT_TROPIC); - /* Do not allow a custom sea level with the original land generator. */ - if (_settings_newgame.game_creation.land_generator == LG_ORIGINAL && - _settings_newgame.difficulty.quantity_sea_lakes == CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY) { - _settings_newgame.difficulty.quantity_sea_lakes = CUSTOM_SEA_LEVEL_MIN_PERCENTAGE; + /* Do not allow a custom sea level or terrain type with the original land generator. */ + if (_settings_newgame.game_creation.land_generator == LG_ORIGINAL) { + if (_settings_newgame.difficulty.quantity_sea_lakes == CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY) { + _settings_newgame.difficulty.quantity_sea_lakes = 1; + } + if (_settings_newgame.difficulty.terrain_type == CUSTOM_TERRAIN_TYPE_NUMBER_DIFFICULTY) { + _settings_newgame.difficulty.terrain_type = 1; + } } } @@ -563,7 +575,13 @@ struct GenerateLandscapeWindow : public Window { case WID_GL_INDUSTRY_PULLDOWN: strs = _num_inds; break; case WID_GL_LANDSCAPE_PULLDOWN: strs = _landscape; break; - case WID_GL_TERRAIN_PULLDOWN: strs = _elevations; break; + + case WID_GL_TERRAIN_PULLDOWN: + strs = _elevations; + SetDParamMaxValue(0, MAX_MAP_HEIGHT_LIMIT); + *size = maxdim(*size, GetStringBoundingBox(STR_TERRAIN_TYPE_CUSTOM_VALUE)); + break; + case WID_GL_WATER_PULLDOWN: strs = _sea_lakes; SetDParamMaxValue(0, CUSTOM_SEA_LEVEL_MAX_PERCENTAGE); @@ -854,7 +872,15 @@ struct GenerateLandscapeWindow : public Window { break; case WID_GL_INDUSTRY_PULLDOWN: _settings_newgame.difficulty.industry_density = index; break; - case WID_GL_TERRAIN_PULLDOWN: _settings_newgame.difficulty.terrain_type = index; break; + case WID_GL_TERRAIN_PULLDOWN: { + if ((uint)index == CUSTOM_TERRAIN_TYPE_NUMBER_DIFFICULTY) { + this->widget_id = widget; + SetDParam(0, _settings_newgame.game_creation.custom_terrain_type); + ShowQueryString(STR_JUST_INT, STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT, 4, this, CS_NUMERAL, QSF_NONE); + } + _settings_newgame.difficulty.terrain_type = index; + break; + } case WID_GL_WATER_PULLDOWN: { if ((uint)index == CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY) { @@ -885,6 +911,7 @@ struct GenerateLandscapeWindow : public Window { case WID_GL_SNOW_COVERAGE_TEXT: value = DEF_SNOW_COVERAGE; break; case WID_GL_DESERT_COVERAGE_TEXT: value = DEF_DESERT_COVERAGE; break; case WID_GL_TOWN_PULLDOWN: value = 1; break; + case WID_GL_TERRAIN_PULLDOWN: value = MIN_MAP_HEIGHT_LIMIT; break; case WID_GL_WATER_PULLDOWN: value = CUSTOM_SEA_LEVEL_MIN_PERCENTAGE; break; default: NOT_REACHED(); } @@ -915,6 +942,10 @@ struct GenerateLandscapeWindow : public Window { _settings_newgame.game_creation.custom_town_number = Clamp(value, 1, CUSTOM_TOWN_MAX_NUMBER); break; + case WID_GL_TERRAIN_PULLDOWN: + _settings_newgame.game_creation.custom_terrain_type = Clamp(value, MIN_CUSTOM_TERRAIN_TYPE, GetMapHeightLimit()); + break; + case WID_GL_WATER_PULLDOWN: _settings_newgame.game_creation.custom_sea_level = Clamp(value, CUSTOM_SEA_LEVEL_MIN_PERCENTAGE, CUSTOM_SEA_LEVEL_MAX_PERCENTAGE); break; diff --git a/src/lang/english.txt b/src/lang/english.txt index 2af2e7e58a..2554a5a178 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1124,6 +1124,8 @@ STR_TERRAIN_TYPE_FLAT :Flat STR_TERRAIN_TYPE_HILLY :Hilly STR_TERRAIN_TYPE_MOUNTAINOUS :Mountainous STR_TERRAIN_TYPE_ALPINIST :Alpinist +STR_TERRAIN_TYPE_CUSTOM :Custom height +STR_TERRAIN_TYPE_CUSTOM_VALUE :Custom height ({NUM}) STR_CITY_APPROVAL_PERMISSIVE :Permissive STR_CITY_APPROVAL_TOLERANT :Tolerant @@ -1206,7 +1208,7 @@ STR_CONFIG_SETTING_CITY_APPROVAL :Town council's STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :Choose how much noise and environmental damage by companies affect their town rating and further construction actions in their area STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT :Map height limit: {STRING2} -STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_HELPTEXT :Set the maximum allowed height of the map; neither the terrain generator nor you can build higher than this limit. On (auto) it will pick a good value after terrain generation +STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_HELPTEXT :Set the maximum height of the map terrain. With "(auto)" a good value will be picked after terrain generation STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_VALUE :{NUM} STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_AUTO :(auto) STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN :{WHITE}You can't set the map height limit to this value. At least one mountain on the map is higher @@ -2936,6 +2938,7 @@ STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Heightma STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}Size: STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} x {NUM} +STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT :{WHITE}Target peak height STR_MAPGEN_HEIGHTMAP_HEIGHT_QUERY_CAPT :{WHITE}Highest peak STR_MAPGEN_SNOW_COVERAGE_QUERY_CAPT :{WHITE}Snow coverage (in %) STR_MAPGEN_DESERT_COVERAGE_QUERY_CAPT :{WHITE}Desert coverage (in %) diff --git a/src/settings_type.h b/src/settings_type.h index 7d50d594bd..42bdc27d4a 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -309,6 +309,7 @@ struct GameCreationSettings { byte water_borders; ///< bitset of the borders that are water uint16 custom_town_number; ///< manually entered number of towns byte variety; ///< variety level applied to TGP + byte custom_terrain_type; ///< manually entered height for TGP to aim for byte custom_sea_level; ///< manually entered percentage of water in the map byte min_river_length; ///< the minimum river length byte river_route_random; ///< the amount of randomicity for the route finding diff --git a/src/table/settings.ini b/src/table/settings.ini index 694268e763..9f5a9b2122 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -266,7 +266,7 @@ from = SLV_97 guiflags = SGF_MULTISTRING | SGF_NEWGAME_ONLY def = 1 min = 0 -max = 4 +max = 5 interval = 1 str = STR_CONFIG_SETTING_TERRAIN_TYPE strhelp = STR_CONFIG_SETTING_TERRAIN_TYPE_HELPTEXT @@ -2463,6 +2463,17 @@ strhelp = STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT strval = STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_SPREAD cat = SC_BASIC +[SDT_VAR] +base = GameSettings +var = game_creation.custom_terrain_type +type = SLE_UINT8 +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +guiflags = SGF_NEWGAME_ONLY +def = MAP_HEIGHT_LIMIT_AUTO_MINIMUM +min = MIN_CUSTOM_TERRAIN_TYPE +max = MAX_MAP_HEIGHT_LIMIT +interval = 1 + [SDT_VAR] base = GameSettings var = game_creation.custom_sea_level diff --git a/src/tgp.cpp b/src/tgp.cpp index 3ced2a1b06..d86617ee27 100644 --- a/src/tgp.cpp +++ b/src/tgp.cpp @@ -215,6 +215,13 @@ static const amplitude_t _water_percent[4] = {70, 170, 270, 420}; */ static height_t TGPGetMaxHeight() { + if (_settings_game.difficulty.terrain_type == CUSTOM_TERRAIN_TYPE_NUMBER_DIFFICULTY) { + /* TGP never reaches this height; this means that if a user inputs "2", + * it would create a flat map without the "+ 1". But that would + * overflow on "255". So we reduce it by 1 to get back in range. */ + return I2H(_settings_game.game_creation.custom_terrain_type + 1) - 1; + } + /** * Desired maximum height - indexed by: * - _settings_game.difficulty.terrain_type diff --git a/src/tile_type.h b/src/tile_type.h index efc057d2b9..73fd0e97e1 100644 --- a/src/tile_type.h +++ b/src/tile_type.h @@ -22,6 +22,7 @@ static const int MAX_VEHICLE_PIXEL_Y = 96; ///< Maximum heig static const uint MAX_TILE_HEIGHT = 255; ///< Maximum allowed tile height static const uint MIN_HEIGHTMAP_HEIGHT = 1; ///< Lowest possible peak value for heightmap creation +static const uint MIN_CUSTOM_TERRAIN_TYPE = 1; ///< Lowest possible peak value for world generation static const uint MIN_MAP_HEIGHT_LIMIT = 15; ///< Lower bound of maximum allowed heightlevel (in the construction settings) static const uint MAX_MAP_HEIGHT_LIMIT = MAX_TILE_HEIGHT; ///< Upper bound of maximum allowed heightlevel (in the construction settings)