From f05e2e0d408cfd018d9875855bd28383569481a9 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Wed, 24 Mar 2021 23:25:51 +0100 Subject: [PATCH] Feature: allow setting a custom terrain type to define highest peak At least, TGP will try to reach it. It heavily depends on the map if it is reachable at all. But for sure it will do its atmost to get there! --- src/genworld.h | 2 ++ src/genworld_gui.cpp | 49 ++++++++++++++++++++++++++++++++++-------- src/lang/english.txt | 5 ++++- src/settings_type.h | 1 + src/table/settings.ini | 13 ++++++++++- src/tgp.cpp | 7 ++++++ src/tile_type.h | 1 + 7 files changed, 67 insertions(+), 11 deletions(-) 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)