From 3b4cbd33235d6706baccec0073ef0a5c817d2002 Mon Sep 17 00:00:00 2001 From: Andreas Schmitt Date: Tue, 15 Jun 2021 18:52:42 +0200 Subject: [PATCH 1/6] Improve tree placement Prior to this change, trees tended to either cover the entire map like an ancient forest, or alternatively you turn off their growth which breaks industry. Furthermore there are these ugly random tree clumps at the beginning of the game which look like squares on the map someone placed there. This change adds a new tree placing setting which removes the ugly random clumps and only slightly modifies the initial placement. The actual growth causes trees to bunch up in higher levels as usual but on the lower 4 levels their growth works differently. The number of trees per tile is limited and the trees spread out over a wider area instead of only to the neighboring tile. That spreads them out more and makes for a nicer look. This also allows cacti to spread, since they can now use that same algorithm and avoid bunching up, but spread as they should. --- src/lang/english.txt | 1 + src/table/settings.ini | 4 +- src/tree_cmd.cpp | 126 ++++++++++++++++++++++++++++++++++------- 3 files changed, 107 insertions(+), 24 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index f8aa4723db..eba78574a4 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1543,6 +1543,7 @@ STR_CONFIG_SETTING_TREE_PLACER_HELPTEXT :Choose the dist STR_CONFIG_SETTING_TREE_PLACER_NONE :None STR_CONFIG_SETTING_TREE_PLACER_ORIGINAL :Original STR_CONFIG_SETTING_TREE_PLACER_IMPROVED :Improved +STR_CONFIG_SETTING_TREE_PLACER_PERFECT :Perfect STR_CONFIG_SETTING_ROAD_SIDE :Road vehicles: {STRING2} STR_CONFIG_SETTING_ROAD_SIDE_HELPTEXT :Choose the driving side STR_CONFIG_SETTING_HEIGHTMAP_ROTATION :Heightmap rotation: {STRING2} diff --git a/src/table/settings.ini b/src/table/settings.ini index 5f2e9741d2..f1c3aec765 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -3803,9 +3803,9 @@ var = game_creation.tree_placer type = SLE_UINT8 from = SLV_30 guiflags = SGF_MULTISTRING | SGF_NEWGAME_ONLY | SGF_SCENEDIT_TOO -def = 2 +def = 3 min = 0 -max = 2 +max = 3 str = STR_CONFIG_SETTING_TREE_PLACER strhelp = STR_CONFIG_SETTING_TREE_PLACER_HELPTEXT strval = STR_CONFIG_SETTING_TREE_PLACER_NONE diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index 74cfdc1aea..7ae01c5dac 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -39,6 +39,7 @@ enum TreePlacer { TP_NONE, ///< No tree placer algorithm TP_ORIGINAL, ///< The original algorithm TP_IMPROVED, ///< A 'improved' algorithm + TP_PERFECT, ///< A 'best' algorithm }; /** Where to place trees while in-game? */ @@ -305,6 +306,13 @@ static void PlaceTreeAtSameHeight(TileIndex tile, int height) } } +int MaxTreeCount(const TileIndex tile) +{ + const auto tile_z = GetTileZ(tile); + + return (tile_z == 1) ? 1 : tile_z + (_settings_game.game_creation.landscape != LT_TROPIC ? 0 : 1); +} + /** * Place some trees randomly * @@ -324,14 +332,19 @@ void PlaceTreesRandomly() if (CanPlantTreesOnTile(tile, true)) { PlaceTree(tile, r); - if (_settings_game.game_creation.tree_placer != TP_IMPROVED) continue; + if (_settings_game.game_creation.tree_placer != TP_IMPROVED && + _settings_game.game_creation.tree_placer != TP_PERFECT) continue; /* Place a number of trees based on the tile height. * This gives a cool effect of multiple trees close together. * It is almost real life ;) */ ht = GetTileZ(tile); /* The higher we get, the more trees we plant */ - j = GetTileZ(tile) * 2; + if (_settings_game.game_creation.tree_placer == TP_PERFECT) { + j = MaxTreeCount(tile); + } else { + j = GetTileZ(tile) * 2; + } /* Above snowline more trees! */ if (_settings_game.game_creation.landscape == LT_ARCTIC && ht > GetSnowLine()) j *= 3; while (j--) { @@ -436,7 +449,8 @@ void GenerateTrees() switch (_settings_game.game_creation.tree_placer) { case TP_ORIGINAL: i = _settings_game.game_creation.landscape == LT_ARCTIC ? 15 : 6; break; - case TP_IMPROVED: i = _settings_game.game_creation.landscape == LT_ARCTIC ? 4 : 2; break; + case TP_IMPROVED: + case TP_PERFECT: i = _settings_game.game_creation.landscape == LT_ARCTIC ? 4 : 2; break; default: NOT_REACHED(); } @@ -444,10 +458,16 @@ void GenerateTrees() if (_settings_game.game_creation.landscape == LT_TROPIC) total += ScaleByMapSize(DEFAULT_RAINFOREST_TREE_STEPS); total *= i; uint num_groups = (_settings_game.game_creation.landscape != LT_TOYLAND) ? ScaleByMapSize(GB(Random(), 0, 5) + 25) : 0; - total += num_groups * DEFAULT_TREE_STEPS; + + if (_settings_game.game_creation.tree_placer != TP_PERFECT) { + total += num_groups * DEFAULT_TREE_STEPS; + } + SetGeneratingWorldProgress(GWP_TREE, total); - if (num_groups != 0) PlaceTreeGroups(num_groups); + if (_settings_game.game_creation.tree_placer != TP_PERFECT) { + if (num_groups != 0) PlaceTreeGroups(num_groups); + } for (; i != 0; i--) { PlaceTreesRandomly(); @@ -479,11 +499,24 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 TileArea ta(tile, p2); TILE_AREA_LOOP(tile, ta) { switch (GetTileType(tile)) { - case MP_TREES: + case MP_TREES: { + bool grow_existing_tree_instead = false; + /* no more space for trees? */ - if (GetTreeCount(tile) == 4) { - msg = STR_ERROR_TREE_ALREADY_HERE; - continue; + if (_settings_game.game_creation.tree_placer == TP_PERFECT) { + if (GetTreeCount(tile) >= 4 || ((int)GetTreeCount(tile) >= MaxTreeCount(tile))) { + if (GetTreeGrowth(tile) < 3) { + grow_existing_tree_instead = true; + } else { + msg = STR_ERROR_TREE_ALREADY_HERE; + continue; + } + } + } else { + if (GetTreeCount(tile) == 4) { + msg = STR_ERROR_TREE_ALREADY_HERE; + continue; + } } /* Test tree limit. */ @@ -493,23 +526,28 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 } if (flags & DC_EXEC) { - AddTreeCount(tile, 1); + if (grow_existing_tree_instead) { + SetTreeGrowth(tile, 3); + } else { + AddTreeCount(tile, 1); + } MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE); if (c != nullptr) c->tree_limit -= 1 << 16; } /* 2x as expensive to add more trees to an existing tile */ cost.AddCost(_price[PR_BUILD_TREES] * 2); break; + } case MP_WATER: - if (!IsCoast(tile) || IsSlopeWithOneCornerRaised(GetTileSlope(tile))) { + if (!CanPlantTreesOnTile(tile, false) || !IsCoast(tile) || IsSlopeWithOneCornerRaised(GetTileSlope(tile))) { msg = STR_ERROR_CAN_T_BUILD_ON_WATER; continue; } FALLTHROUGH; case MP_CLEAR: { - if (IsBridgeAbove(tile)) { + if (!CanPlantTreesOnTile(tile, false) || IsBridgeAbove(tile)) { msg = STR_ERROR_SITE_UNSUITABLE; continue; } @@ -853,29 +891,73 @@ static void TileLoop_Trees(TileIndex tile) AddTreeGrowth(tile, 1); break; - case 1: // add a tree - if (GetTreeCount(tile) < 4 && CanPlantExtraTrees(tile)) { + case 1: { // add a tree + if (_settings_game.game_creation.tree_placer == TP_PERFECT) { + if ((GetTreeCount(tile) < 4) && (GetTreeType(tile) != TREE_CACTUS) && ((int)GetTreeCount(tile) < MaxTreeCount(tile))) { + AddTreeCount(tile, 1); + SetTreeGrowth(tile, 0); + break; + } + } else if (GetTreeCount(tile) < 4 && CanPlantExtraTrees(tile)) { AddTreeCount(tile, 1); SetTreeGrowth(tile, 0); break; } - FALLTHROUGH; + } + FALLTHROUGH; case 2: { // add a neighbouring tree if (!CanPlantExtraTrees(tile)) break; - TreeType treetype = GetTreeType(tile); + if (_settings_game.game_creation.tree_placer == TP_PERFECT && + ((_settings_game.game_creation.landscape != LT_TROPIC && GetTileZ(tile) < 3) || (GetTreeType(tile) == TREE_CACTUS))) { + // On lower levels we spread more randomly to not bunch up. + const uint32 r = Random(); + int x = 0; + int y = 0; + TileIndex cur_tile = INVALID_TILE; + // Give cacti more chance to spread since they are sparse to begin with. + const int max_tries = (GetTreeType(tile) == TREE_CACTUS) ? 8 : 4; + + // Try multiple times to spread + for (int i = 0; i < max_tries; ++i) { + x = GB(r, 0, 5) - 16; + y = GB(r, 8, 5) - 16; + cur_tile = TileAddWrap(tile, x, y); + + if ((cur_tile != INVALID_TILE) && + (abs(x) + abs(y) <= 16) && + (CanPlantTreesOnTile(cur_tile, true)) && + (Delta(GetTileZ(cur_tile), GetTileZ(tile)) <= 2)) { + break; + } + } - tile += TileOffsByDir((Direction)(Random() & 7)); + if (cur_tile == INVALID_TILE) return; - /* Cacti don't spread */ - if (!CanPlantTreesOnTile(tile, false)) return; + // Keep in range of the existing tree + if (abs(x) + abs(y) > 16) return; - /* Don't plant trees, if ground was freshly cleared */ - if (IsTileType(tile, MP_CLEAR) && GetClearGround(tile) == CLEAR_GRASS && GetClearDensity(tile) != 3) return; + // Clear tile, no farm-tiles or rocks + if (!CanPlantTreesOnTile(cur_tile, true)) return; - PlantTreesOnTile(tile, treetype, 0, 0); + // Not too much height difference + if (Delta(GetTileZ(cur_tile), GetTileZ(tile)) > 2) return; + // Place one tree and quit + PlantTreesOnTile(cur_tile, GetTreeType(tile), 0, 0); + } else { + const TreeType tree_type = GetTreeType(tile); + + tile += TileOffsByDir((Direction)(Random() & 7)); + + if (!CanPlantTreesOnTile(tile, false)) return; + + // Don't plant trees, if ground was freshly cleared + if (IsTileType(tile, MP_CLEAR) && GetClearGround(tile) == CLEAR_GRASS && GetClearDensity(tile) != 3) return; + + PlantTreesOnTile(tile, tree_type, 0, 0); + } break; } From 6c2152045a651ec3ed483240ebab64cfbce1beb0 Mon Sep 17 00:00:00 2001 From: Andreas Schmitt Date: Thu, 17 Jun 2021 07:56:51 +0200 Subject: [PATCH 2/6] Fix banding issue in artic tree range Using tile index for randomization is a very very very bad idea --- src/tree_cmd.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index 7ae01c5dac..fd973bf40a 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -194,8 +194,7 @@ static TreeType GetRandomTreeType(TileIndex tile, uint seed) uint normalised_distance = (height_above_snow_line < 0) ? -height_above_snow_line : height_above_snow_line + 1; bool arctic_tree = false; if (normalised_distance < lengthof(_arctic_tree_occurance)) { - uint adjusted_seed = (seed ^ tile) & 0xFF; - arctic_tree = adjusted_seed < _arctic_tree_occurance[normalised_distance]; + arctic_tree = RandomRange(256) < _arctic_tree_occurance[normalised_distance]; } if (height_above_snow_line < 0) { /* Below snow level mixed forest. */ From fe3c5d0330367b47fd86abc0978ff95646d0d85f Mon Sep 17 00:00:00 2001 From: Andreas Schmitt Date: Thu, 17 Jun 2021 14:28:11 +0200 Subject: [PATCH 3/6] Add another sparse tree growth area above the snow line and prevent that area from overgrowing --- src/tree_cmd.cpp | 145 +++++++++++++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 61 deletions(-) diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index fd973bf40a..65fbe58b1c 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -67,6 +67,12 @@ static const uint16 EDITOR_TREE_DIV = 5; ///< Game editor tree */ 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) > (_settings_game.game_creation.snow_line_height + _settings_game.construction.trees_around_snow_line_range))) { + return false; + } + switch (GetTileType(tile)) { case MP_WATER: return !IsBridgeAbove(tile) && IsCoast(tile) && !IsSlopeWithOneCornerRaised(GetTileSlope(tile)); @@ -157,7 +163,7 @@ static void RecalculateArcticTreeOccuranceArray() output *= x; output >>= 24; if (output == 0) break; - _arctic_tree_occurance[i] = output; + _arctic_tree_occurance[i] = static_cast(output); } for (; i < lengthof(_arctic_tree_occurance); i++) { _arctic_tree_occurance[i] = 0; @@ -272,22 +278,16 @@ static void PlaceTreeGroups(uint num_groups) } while (--num_groups); } -/** - * Place a tree at the same height as an existing tree. - * - * Add a new tree around the given tile which is at the same - * height or at some offset (2 units) of it. - * - * @param tile The base tile to add a new tree somewhere around - * @param height The height (like the one from the tile) - */ -static void PlaceTreeAtSameHeight(TileIndex tile, int height) +static TileIndex FindTreePositionAtSameHeight(TileIndex tile, uint steps) { - for (uint i = 0; i < DEFAULT_TREE_STEPS; i++) { - uint32 r = Random(); - int x = GB(r, 0, 5) - 16; - int y = GB(r, 8, 5) - 16; - TileIndex cur_tile = TileAddWrap(tile, x, y); + const auto height = GetTileZ(tile); + + for (uint i = 0; i < steps; i++) { + const uint32 r = Random(); + const int x = GB(r, 0, 5) - 16; + const int y = GB(r, 8, 5) - 16; + const TileIndex cur_tile = TileAddWrap(tile, x, y); + if (cur_tile == INVALID_TILE) continue; /* Keep in range of the existing tree */ @@ -299,17 +299,75 @@ static void PlaceTreeAtSameHeight(TileIndex tile, int height) /* Not too much height difference */ if (Delta(GetTileZ(cur_tile), height) > 2) continue; - /* Place one tree and quit */ - PlaceTree(cur_tile, r); - break; + /* We found a position */ + return cur_tile; } + + return INVALID_TILE; +} + +/** + * Plants a tree at the same height as an existing tree. + * + * Plant a tree around the given tile which is at the same + * height or at some offset (2 units) of it. + * + * @param tile The base tile to add a new tree somewhere around + */ +static void PlantTreeAtSameHeight(TileIndex tile) +{ + const int max_tries = (GetTreeType(tile) == TREE_CACTUS) ? 8 : 4; + const auto new_tile = FindTreePositionAtSameHeight(tile, max_tries); + + if (new_tile != INVALID_TILE) { + PlantTreesOnTile(new_tile, GetTreeType(tile), 0, 0); + } +} + +/** + * Place a tree at the same height as an existing tree. + * + * Add a new tree around the given tile which is at the same + * height or at some offset (2 units) of it. + * + * @param tile The base tile to add a new tree somewhere around + */ +static void PlaceTreeAtSameHeight(TileIndex tile) +{ + const auto new_tile = FindTreePositionAtSameHeight(tile, DEFAULT_TREE_STEPS); + + if (new_tile != INVALID_TILE) { + PlaceTree(new_tile, Random()); + } +} + +int GetSparseTreeRange() +{ + const auto max_map_height = std::max(32, _settings_game.construction.map_height_limit); + const auto sparse_tree_range = std::min(8, (4 * max_map_height) / 32); + + return sparse_tree_range; } int MaxTreeCount(const TileIndex tile) { const auto tile_z = GetTileZ(tile); + const auto round_up_divide = [](const uint x, const uint y) { return (x / y) + ((x % y != 0) ? 1 : 0); }; - return (tile_z == 1) ? 1 : tile_z + (_settings_game.game_creation.landscape != LT_TROPIC ? 0 : 1); + int max_trees_z_based = round_up_divide(tile_z * 4, GetSparseTreeRange()); + max_trees_z_based = std::max(1, max_trees_z_based); + max_trees_z_based += (_settings_game.game_creation.landscape != LT_TROPIC ? 0 : 1); + + int max_trees_snow_line_based = 4; + + if (_settings_game.game_creation.landscape == LT_ARCTIC) { + const uint height_above_snow_line = std::max(0, tile_z - _settings_game.game_creation.snow_line_height); + max_trees_snow_line_based = (height_above_snow_line < lengthof(_arctic_tree_occurance)) ? + (1 + (_arctic_tree_occurance[height_above_snow_line] * 4) / 255) : + 0; + } + + return std::min(max_trees_z_based, max_trees_snow_line_based); } /** @@ -339,15 +397,11 @@ void PlaceTreesRandomly() * It is almost real life ;) */ ht = GetTileZ(tile); /* The higher we get, the more trees we plant */ - if (_settings_game.game_creation.tree_placer == TP_PERFECT) { - j = MaxTreeCount(tile); - } else { - j = GetTileZ(tile) * 2; - } + j = GetTileZ(tile) * 2; /* Above snowline more trees! */ if (_settings_game.game_creation.landscape == LT_ARCTIC && ht > GetSnowLine()) j *= 3; while (j--) { - PlaceTreeAtSameHeight(tile, ht); + PlaceTreeAtSameHeight(tile); } } } while (--i); @@ -909,42 +963,11 @@ static void TileLoop_Trees(TileIndex tile) if (!CanPlantExtraTrees(tile)) break; if (_settings_game.game_creation.tree_placer == TP_PERFECT && - ((_settings_game.game_creation.landscape != LT_TROPIC && GetTileZ(tile) < 3) || (GetTreeType(tile) == TREE_CACTUS))) { + ((_settings_game.game_creation.landscape != LT_TROPIC && GetTileZ(tile) <= GetSparseTreeRange()) || + (GetTreeType(tile) == TREE_CACTUS) || + (_settings_game.game_creation.landscape == LT_ARCTIC && GetTileZ(tile) >= _settings_game.game_creation.snow_line_height + _settings_game.construction.trees_around_snow_line_range / 3))) { // On lower levels we spread more randomly to not bunch up. - const uint32 r = Random(); - int x = 0; - int y = 0; - TileIndex cur_tile = INVALID_TILE; - // Give cacti more chance to spread since they are sparse to begin with. - const int max_tries = (GetTreeType(tile) == TREE_CACTUS) ? 8 : 4; - - // Try multiple times to spread - for (int i = 0; i < max_tries; ++i) { - x = GB(r, 0, 5) - 16; - y = GB(r, 8, 5) - 16; - cur_tile = TileAddWrap(tile, x, y); - - if ((cur_tile != INVALID_TILE) && - (abs(x) + abs(y) <= 16) && - (CanPlantTreesOnTile(cur_tile, true)) && - (Delta(GetTileZ(cur_tile), GetTileZ(tile)) <= 2)) { - break; - } - } - - if (cur_tile == INVALID_TILE) return; - - // Keep in range of the existing tree - if (abs(x) + abs(y) > 16) return; - - // Clear tile, no farm-tiles or rocks - if (!CanPlantTreesOnTile(cur_tile, true)) return; - - // Not too much height difference - if (Delta(GetTileZ(cur_tile), GetTileZ(tile)) > 2) return; - - // Place one tree and quit - PlantTreesOnTile(cur_tile, GetTreeType(tile), 0, 0); + PlantTreeAtSameHeight(tile); } else { const TreeType tree_type = GetTreeType(tile); From f944c9e7ba95c73b1e82cd6aa9d686b2dad78d08 Mon Sep 17 00:00:00 2001 From: Andreas Schmitt Date: Thu, 17 Jun 2021 18:15:06 +0200 Subject: [PATCH 4/6] Reduce building of cacti --- src/tree_cmd.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index 65fbe58b1c..b9d4656b97 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -316,8 +316,7 @@ static TileIndex FindTreePositionAtSameHeight(TileIndex tile, uint steps) */ static void PlantTreeAtSameHeight(TileIndex tile) { - const int max_tries = (GetTreeType(tile) == TREE_CACTUS) ? 8 : 4; - const auto new_tile = FindTreePositionAtSameHeight(tile, max_tries); + const auto new_tile = FindTreePositionAtSameHeight(tile, 4); if (new_tile != INVALID_TILE) { PlantTreesOnTile(new_tile, GetTreeType(tile), 0, 0); From d719b09cf044f28ecd7882600e16889f3281aac3 Mon Sep 17 00:00:00 2001 From: Andreas Schmitt Date: Thu, 17 Jun 2021 19:09:11 +0200 Subject: [PATCH 5/6] Tweak the dispersed spreading a bit more --- src/tree_cmd.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index b9d4656b97..294ab250c8 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -316,7 +316,7 @@ static TileIndex FindTreePositionAtSameHeight(TileIndex tile, uint steps) */ static void PlantTreeAtSameHeight(TileIndex tile) { - const auto new_tile = FindTreePositionAtSameHeight(tile, 4); + const auto new_tile = FindTreePositionAtSameHeight(tile, 1); if (new_tile != INVALID_TILE) { PlantTreesOnTile(new_tile, GetTreeType(tile), 0, 0); @@ -556,7 +556,7 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 /* no more space for trees? */ if (_settings_game.game_creation.tree_placer == TP_PERFECT) { - if (GetTreeCount(tile) >= 4 || ((int)GetTreeCount(tile) >= MaxTreeCount(tile))) { + if (GetTreeCount(tile) >= 4 || ((GetTreeType(tile) != TREE_CACTUS) && ((int)GetTreeCount(tile) >= MaxTreeCount(tile)))) { if (GetTreeGrowth(tile) < 3) { grow_existing_tree_instead = true; } else { @@ -945,7 +945,7 @@ static void TileLoop_Trees(TileIndex tile) case 1: { // add a tree if (_settings_game.game_creation.tree_placer == TP_PERFECT) { - if ((GetTreeCount(tile) < 4) && (GetTreeType(tile) != TREE_CACTUS) && ((int)GetTreeCount(tile) < MaxTreeCount(tile))) { + if ((GetTreeCount(tile) < 4) && ((GetTreeType(tile) == TREE_CACTUS) || ((int)GetTreeCount(tile) < MaxTreeCount(tile)))) { AddTreeCount(tile, 1); SetTreeGrowth(tile, 0); break; @@ -966,7 +966,9 @@ static void TileLoop_Trees(TileIndex tile) (GetTreeType(tile) == TREE_CACTUS) || (_settings_game.game_creation.landscape == LT_ARCTIC && GetTileZ(tile) >= _settings_game.game_creation.snow_line_height + _settings_game.construction.trees_around_snow_line_range / 3))) { // On lower levels we spread more randomly to not bunch up. - PlantTreeAtSameHeight(tile); + if (GetTreeType(tile) != TREE_CACTUS || (RandomRange(100) < 50)) { + PlantTreeAtSameHeight(tile); + } } else { const TreeType tree_type = GetTreeType(tile); From 82fa6ed711e9fa007e11fd81442a5acc51bb9284 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sat, 19 Jun 2021 14:05:34 +0100 Subject: [PATCH 6/6] Whitespace adjustments --- src/tree_cmd.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index 294ab250c8..68b536a2d8 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -39,7 +39,7 @@ enum TreePlacer { TP_NONE, ///< No tree placer algorithm TP_ORIGINAL, ///< The original algorithm TP_IMPROVED, ///< A 'improved' algorithm - TP_PERFECT, ///< A 'best' algorithm + TP_PERFECT, ///< A 'best' algorithm }; /** Where to place trees while in-game? */ @@ -72,7 +72,7 @@ static bool CanPlantTreesOnTile(TileIndex tile, bool allow_desert) (GetTileZ(tile) > (_settings_game.game_creation.snow_line_height + _settings_game.construction.trees_around_snow_line_range))) { return false; } - + switch (GetTileType(tile)) { case MP_WATER: return !IsBridgeAbove(tile) && IsCoast(tile) && !IsSlopeWithOneCornerRaised(GetTileSlope(tile)); @@ -281,7 +281,7 @@ static void PlaceTreeGroups(uint num_groups) static TileIndex FindTreePositionAtSameHeight(TileIndex tile, uint steps) { const auto height = GetTileZ(tile); - + for (uint i = 0; i < steps; i++) { const uint32 r = Random(); const int x = GB(r, 0, 5) - 16; @@ -359,7 +359,7 @@ int MaxTreeCount(const TileIndex tile) int max_trees_snow_line_based = 4; - if (_settings_game.game_creation.landscape == LT_ARCTIC) { + if (_settings_game.game_creation.landscape == LT_ARCTIC) { const uint height_above_snow_line = std::max(0, tile_z - _settings_game.game_creation.snow_line_height); max_trees_snow_line_based = (height_above_snow_line < lengthof(_arctic_tree_occurance)) ? (1 + (_arctic_tree_occurance[height_above_snow_line] * 4) / 255) : @@ -553,7 +553,7 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 switch (GetTileType(tile)) { case MP_TREES: { bool grow_existing_tree_instead = false; - + /* no more space for trees? */ if (_settings_game.game_creation.tree_placer == TP_PERFECT) { if (GetTreeCount(tile) >= 4 || ((GetTreeType(tile) != TREE_CACTUS) && ((int)GetTreeCount(tile) >= MaxTreeCount(tile)))) {