diff --git a/src/landscape.cpp b/src/landscape.cpp index 7df8195a6d..7231b024ec 100644 --- a/src/landscape.cpp +++ b/src/landscape.cpp @@ -105,6 +105,8 @@ static bool _is_main_river = false; byte _cached_snowline = 0; byte _cached_highest_snowline = 0; byte _cached_lowest_snowline = 0; +byte _cached_tree_placement_highest_snowline = 0; +byte _cached_tree_placement_lowest_snowline = 0; /** * Map 2D viewport or smallmap coordinate to 3D world or tile coordinate. @@ -687,6 +689,10 @@ void UpdateCachedSnowLineBounds() { _cached_highest_snowline = _snow_line == nullptr ? _settings_game.game_creation.snow_line_height : _snow_line->highest_value; _cached_lowest_snowline = _snow_line == nullptr ? _settings_game.game_creation.snow_line_height : _snow_line->lowest_value; + + uint snowline_delta = (((100 - _settings_game.construction.trees_around_snow_line_dynamic_range) * (HighestSnowLine() - LowestSnowLine())) + 50) / 100; + _cached_tree_placement_highest_snowline = HighestSnowLine() - ((snowline_delta + 1) / 2); + _cached_tree_placement_lowest_snowline = LowestSnowLine() + (snowline_delta / 2); } /** diff --git a/src/landscape.h b/src/landscape.h index 99f20ff8ba..19e3cbc711 100644 --- a/src/landscape.h +++ b/src/landscape.h @@ -51,6 +51,18 @@ inline byte LowestSnowLine() return _cached_lowest_snowline; } +inline byte HighestTreePlacementSnowLine() +{ + extern byte _cached_tree_placement_highest_snowline; + return _cached_tree_placement_highest_snowline; +} + +inline byte LowestTreePlacementSnowLine() +{ + extern byte _cached_tree_placement_lowest_snowline; + return _cached_tree_placement_lowest_snowline; +} + int GetSlopeZInCorner(Slope tileh, Corner corner); Slope GetFoundationSlope(TileIndex tile, int *z = nullptr); diff --git a/src/lang/english.txt b/src/lang/english.txt index 632123f2b4..6957821013 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2204,6 +2204,8 @@ STR_CONFIG_SETTING_TREES_AROUND_SNOWLINE :Adjusted arctic STR_CONFIG_SETTING_TREES_AROUND_SNOWLINE_HELPTEXT :Adjust placement of trees around snow line in artic climate. Trees thin out above snowline. Trees are a mix of arctic and temperate just below snowline. Below that trees are temperate. STR_CONFIG_SETTING_TREES_AROUND_SNOWLINE_RANGE :Arctic tree range: {STRING2} STR_CONFIG_SETTING_TREES_AROUND_SNOWLINE_RANGE_HELPTEXT :Approximate range of arctic trees around snow line +STR_CONFIG_SETTING_TREES_AROUND_SNOWLINE_DYNAMIC_RANGE :Seasonal snow line width for arctic trees: {STRING2} +STR_CONFIG_SETTING_TREES_AROUND_SNOWLINE_DYNAMIC_RANGE_HELPTEXT :When using a seasonally variable snow line, what percentage of the snow line variation to use as the snow line for arctic tree placement. 0% uses the mid-point between summer and winter snow lines, 100% uses the whole range between the summer and winter snow lines. STR_CONFIG_SETTING_BUILD_PUBLIC_ROADS :Build public roads connecting towns: {STRING2} STR_CONFIG_SETTING_BUILD_PUBLIC_ROADS_HELPTEXT :Generates public roads which connect the towns. Takes a bit of time on bigger maps. 'Build and avoid' generates roads which avoid curves and result in very grid-like connections. diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 1f8782380e..659e02e7f9 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -2224,6 +2224,7 @@ static SettingsContainer &GetSettingsTree() treedist->Add(new SettingEntry("construction.extra_tree_placement")); treedist->Add(new SettingEntry("construction.trees_around_snow_line_enabled")); treedist->Add(new SettingEntry("construction.trees_around_snow_line_range")); + treedist->Add(new SettingEntry("construction.trees_around_snow_line_dynamic_range")); treedist->Add(new SettingEntry("construction.tree_growth_rate")); } diff --git a/src/settings_type.h b/src/settings_type.h index bc7629abd9..c73797fb55 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -441,6 +441,7 @@ struct ConstructionSettings { uint8 extra_tree_placement; ///< (dis)allow building extra trees in-game uint8 trees_around_snow_line_range; ///< range around snowline for mixed and arctic forest. bool trees_around_snow_line_enabled; ///< enable mixed and arctic forest around snowline, and no trees above snowline + uint8 trees_around_snow_line_dynamic_range; ///< how much of the snow line dynamic range to use as the snowline for arctic tree placement uint8 command_pause_level; ///< level/amount of commands that can't be executed while paused uint16 maximum_signal_evaluations; ///< maximum number of programmable pre-signals which may be evaluated in one pass bool enable_build_river; ///< enable building rivers in-game diff --git a/src/table/settings/settings.ini b/src/table/settings/settings.ini index b4c5c18673..91ee9106e3 100644 --- a/src/table/settings/settings.ini +++ b/src/table/settings/settings.ini @@ -3803,6 +3803,20 @@ strval = STR_JUST_COMMA cat = SC_BASIC patxname = ""everest_treeline.construction.trees_around_snow_line_range"" +[SDT_VAR] +var = construction.trees_around_snow_line_dynamic_range +type = SLE_UINT8 +def = 75 +min = 0 +max = 100 +interval = 5 +str = STR_CONFIG_SETTING_TREES_AROUND_SNOWLINE_DYNAMIC_RANGE +strhelp = STR_CONFIG_SETTING_TREES_AROUND_SNOWLINE_DYNAMIC_RANGE_HELPTEXT +strval = STR_CONFIG_SETTING_PERCENTAGE +cat = SC_EXPERT +patxname = ""everest_treeline.construction.trees_around_snow_line_dynamic_range"" +post_cb = [](auto) { UpdateCachedSnowLineBounds(); } + [SDT_VAR] var = construction.tree_growth_rate type = SLE_UINT8 diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index d38fd1ff17..4b0326d056 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -69,7 +69,7 @@ static bool CanPlantTreesOnTile(TileIndex tile, bool allow_desert) { if ((_settings_game.game_creation.tree_placer == TP_PERFECT) && (_settings_game.game_creation.landscape == LT_ARCTIC) && - (GetTileZ(tile) > (HighestSnowLine() + _settings_game.construction.trees_around_snow_line_range))) { + (GetTileZ(tile) > (HighestTreePlacementSnowLine() + _settings_game.construction.trees_around_snow_line_range))) { return false; } @@ -196,11 +196,10 @@ static TreeType GetRandomTreeType(TileIndex tile, uint seed) int z = GetTileZ(tile); int height_above_snow_line = 0; - if (z > HighestSnowLine()) { - height_above_snow_line = z - HighestSnowLine(); - } - else if (z < LowestSnowLine()) { - height_above_snow_line = z - LowestSnowLine(); + if (z > HighestTreePlacementSnowLine()) { + height_above_snow_line = z - HighestTreePlacementSnowLine(); + } else if (z < LowestTreePlacementSnowLine()) { + height_above_snow_line = z - LowestTreePlacementSnowLine(); } uint normalised_distance = (height_above_snow_line < 0) ? -height_above_snow_line : height_above_snow_line + 1; bool arctic_tree = false; @@ -365,7 +364,7 @@ int MaxTreeCount(const TileIndex tile) if (_settings_game.game_creation.landscape == LT_ARCTIC) { if (_settings_game.construction.trees_around_snow_line_range != _previous_trees_around_snow_line_range) RecalculateArcticTreeOccuranceArray(); - const uint height_above_snow_line = std::max(0, tile_z - HighestSnowLine()); + const uint height_above_snow_line = std::max(0, tile_z - HighestTreePlacementSnowLine()); max_trees_snow_line_based = (height_above_snow_line < _arctic_tree_occurance.size()) ? (1 + (_arctic_tree_occurance[height_above_snow_line] * 4) / 255) : 0; @@ -976,7 +975,7 @@ static void TileLoop_Trees(TileIndex tile) if (_settings_game.game_creation.tree_placer == TP_PERFECT && ((_settings_game.game_creation.landscape != LT_TROPIC && GetTileZ(tile) <= GetSparseTreeRange()) || (GetTreeType(tile) == TREE_CACTUS) || - (_settings_game.game_creation.landscape == LT_ARCTIC && GetTileZ(tile) >= HighestSnowLine() + _settings_game.construction.trees_around_snow_line_range / 3))) { + (_settings_game.game_creation.landscape == LT_ARCTIC && GetTileZ(tile) >= HighestTreePlacementSnowLine() + _settings_game.construction.trees_around_snow_line_range / 3))) { // On lower levels we spread more randomly to not bunch up. if (GetTreeType(tile) != TREE_CACTUS || (RandomRange(100) < 50)) { PlantTreeAtSameHeight(tile);