# HG changeset patch # User frosch # Date 2008-01-30 18:40:42 # Node ID a518d14862f99240a958b0946973604f6dc804c8 # Parent 6d62aa4ee95e018248000baf6e3245304d9646f7 (svn r12024) -Codechange: Reduce code duplication inside tree_cmd. -CodeChange: When rocks get removed while planting trees, barren the ground. -Fix: In one case trees could spread under bridges. diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -37,6 +37,48 @@ enum TreePlacer { }; /** + * Tests if a tile can be converted to MP_TREES + * This is true for clear ground without farms or rocks. + * + * @param tile the tile of interest + * @param allow_desert Allow planting trees on CLEAR_DESERT? + * @return true if trees can be built. + */ +static inline bool CanPlantTreesOnTile(TileIndex tile, bool allow_desert) +{ + return IsTileType(tile, MP_CLEAR) && !IsBridgeAbove(tile) && + !IsClearGround(tile, CLEAR_FIELDS) && !IsClearGround(tile, CLEAR_ROCKS) && + (allow_desert || !IsClearGround(tile, CLEAR_DESERT)); +} + +/** + * Creates a tree tile + * Ground type and density is preserved. + * + * @pre the tile must be suitable for trees. + * + * @param tile where to plant the trees. + * @param type The type of the tree + * @param count the number of trees (minus 1) + * @param growth the growth status + */ +static void PlantTreesOnTile(TileIndex tile, TreeType treetype, uint count, uint growth) +{ + assert(treetype != TREE_INVALID); + assert(CanPlantTreesOnTile(tile, true)); + + TreeGround ground; + uint density = 3; + switch (GetClearGround(tile)) { + case CLEAR_GRASS: ground = TREE_GROUND_GRASS; density = GetClearDensity(tile); break; + case CLEAR_ROUGH: ground = TREE_GROUND_ROUGH; break; + default: ground = TREE_GROUND_SNOW_DESERT; density = GetClearDensity(tile); break; + } + + MakeTree(tile, treetype, count, growth, ground, density); +} + +/** * Get a random TreeType for the given tile based on a given seed * * This function returns a random TreeType which can be placed on the given tile. @@ -82,16 +124,15 @@ static void PlaceTree(TileIndex tile, ui TreeType tree = GetRandomTreeType(tile, GB(r, 24, 8)); if (tree != TREE_INVALID) { - MakeTree(tile, tree, GB(r, 22, 2), min(GB(r, 16, 3), 6), TREE_GROUND_GRASS, 0); + PlantTreesOnTile(tile, tree, GB(r, 22, 2), min(GB(r, 16, 3), 6)); - /* above snowline? */ - if (_opt.landscape == LT_ARCTIC && GetTileZ(tile) > GetSnowLine()) { - SetTreeGroundDensity(tile, TREE_GROUND_SNOW_DESERT, 3); - SetTreeCounter(tile, (TreeGround)GB(r, 24, 3)); - } else { + /* Rerandomize ground, if not snow */ + if (GetTreeGround(tile) != TREE_GROUND_SNOW_DESERT) { SetTreeGroundDensity(tile, (TreeGround)GB(r, 28, 1), 3); - SetTreeCounter(tile, (TreeGround)GB(r, 24, 4)); } + + /* Set the counter to a random start value */ + SetTreeCounter(tile, (TreeGround)GB(r, 24, 4)); } } @@ -115,11 +156,7 @@ static void DoPlaceMoreTrees(TileIndex t uint dist = abs(x) + abs(y); TileIndex cur_tile = TILE_MASK(tile + TileDiffXY(x, y)); - if (dist <= 13 && - IsTileType(cur_tile, MP_CLEAR) && - !IsBridgeAbove(cur_tile) && - !IsClearGround(cur_tile, CLEAR_FIELDS) && - !IsClearGround(cur_tile, CLEAR_ROCKS)) { + if (dist <= 13 && CanPlantTreesOnTile(cur_tile, true)) { PlaceTree(cur_tile, r); } } @@ -147,7 +184,7 @@ static void PlaceMoreTrees() * @param tile The base tile to add a new tree somewhere around * @param height The height (like the one from the tile) */ -void PlaceTreeAtSameHeight(TileIndex tile, uint height) +static void PlaceTreeAtSameHeight(TileIndex tile, uint height) { uint i; @@ -161,10 +198,7 @@ void PlaceTreeAtSameHeight(TileIndex til if (abs(x) + abs(y) > 16) continue; /* Clear tile, no farm-tiles or rocks */ - if (!IsTileType(cur_tile, MP_CLEAR) || - IsClearGround(cur_tile, CLEAR_FIELDS) || - IsClearGround(cur_tile, CLEAR_ROCKS)) - continue; + if (!CanPlantTreesOnTile(cur_tile, true)) continue; /* Not too much height difference */ if (Delta(GetTileZ(cur_tile), height) > 2) continue; @@ -191,10 +225,7 @@ void PlaceTreesRandomly() IncreaseGeneratingWorldProgress(GWP_TREE); - if (IsTileType(tile, MP_CLEAR) && - !IsBridgeAbove(tile) && - !IsClearGround(tile, CLEAR_FIELDS) && - !IsClearGround(tile, CLEAR_ROCKS)) { + if (CanPlantTreesOnTile(tile, true)) { PlaceTree(tile, r); if (_patches.tree_placer != TP_IMPROVED) continue; @@ -226,10 +257,7 @@ void PlaceTreesRandomly() IncreaseGeneratingWorldProgress(GWP_TREE); - if (IsTileType(tile, MP_CLEAR) && - !IsBridgeAbove(tile) && - !IsClearGround(tile, CLEAR_FIELDS) && - GetTropicZone(tile) == TROPICZONE_RAINFOREST) { + if (GetTropicZone(tile) == TROPICZONE_RAINFOREST && CanPlantTreesOnTile(tile, false)) { PlaceTree(tile, r); } } while (--i); @@ -318,15 +346,21 @@ CommandCost CmdPlantTree(TileIndex tile, break; case MP_CLEAR: - if (!IsTileOwner(tile, OWNER_NONE) || - IsBridgeAbove(tile)) { + if (IsBridgeAbove(tile)) { msg = STR_2804_SITE_UNSUITABLE; continue; } + /* Remove fields or rocks. Note that the ground will get barrened */ switch (GetClearGround(tile)) { - case CLEAR_FIELDS: cost.AddCost(_price.clear_fields); break; - case CLEAR_ROCKS: cost.AddCost(_price.clear_rocks); break; + case CLEAR_FIELDS: + case CLEAR_ROCKS: { + CommandCost ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (CmdFailed(ret)) return ret; + cost.AddCost(ret); + break; + } + default: break; } @@ -337,7 +371,6 @@ CommandCost CmdPlantTree(TileIndex tile, if (flags & DC_EXEC) { TreeType treetype; - uint growth; treetype = (TreeType)p1; if (treetype == TREE_INVALID) { @@ -345,15 +378,11 @@ CommandCost CmdPlantTree(TileIndex tile, if (treetype == TREE_INVALID) treetype = TREE_CACTUS; } - growth = _game_mode == GM_EDITOR ? 3 : 0; - switch (GetClearGround(tile)) { - case CLEAR_ROUGH: MakeTree(tile, treetype, 0, growth, TREE_GROUND_ROUGH, 3); break; - case CLEAR_SNOW: - case CLEAR_DESERT: MakeTree(tile, treetype, 0, growth, TREE_GROUND_SNOW_DESERT, GetClearDensity(tile)); break; - default: MakeTree(tile, treetype, 0, growth, TREE_GROUND_GRASS, GetClearDensity(tile)); break; - } + /* Plant full grown trees in scenario editor */ + PlantTreesOnTile(tile, treetype, 0, _game_mode == GM_EDITOR ? 3 : 0); MarkTileDirtyByTile(tile); + /* When planting rainforest-trees, set tropiczone to rainforest in editor. */ if (_game_mode == GM_EDITOR && IsInsideMM(treetype, TREE_RAINFOREST, TREE_CACTUS)) SetTropicZone(tile, TROPICZONE_RAINFOREST); } @@ -627,19 +656,14 @@ static void TileLoop_Trees(TileIndex til tile += TileOffsByDir((Direction)(Random() & 7)); - if (!IsTileType(tile, MP_CLEAR) || IsBridgeAbove(tile)) return; + /* Cacti don't spread */ + if (!CanPlantTreesOnTile(tile, false)) return; - switch (GetClearGround(tile)) { - case CLEAR_GRASS: - if (GetClearDensity(tile) != 3) return; - MakeTree(tile, treetype, 0, 0, TREE_GROUND_GRASS, 3); - break; + /* Don't plant trees, if ground was freshly cleared */ + if (GetClearGround(tile) == CLEAR_GRASS && GetClearDensity(tile) != 3) return; - case CLEAR_ROUGH: MakeTree(tile, treetype, 0, 0, TREE_GROUND_ROUGH, 3); break; - case CLEAR_DESERT: return; // Cacti don't spread - case CLEAR_SNOW: MakeTree(tile, treetype, 0, 0, TREE_GROUND_SNOW_DESERT, GetClearDensity(tile)); break; - default: return; - } + PlantTreesOnTile(tile, treetype, 0, 0); + break; } @@ -678,17 +702,14 @@ void OnTick_Trees() { uint32 r; TileIndex tile; - ClearGround ct; TreeType tree; /* place a tree at a random rainforest spot */ if (_opt.landscape == LT_TROPIC && (r = Random(), tile = RandomTileSeed(r), GetTropicZone(tile) == TROPICZONE_RAINFOREST) && - IsTileType(tile, MP_CLEAR) && - !IsBridgeAbove(tile) && - (ct = GetClearGround(tile), ct == CLEAR_GRASS || ct == CLEAR_ROUGH) && + CanPlantTreesOnTile(tile, false) && (tree = GetRandomTreeType(tile, GB(r, 24, 8))) != TREE_INVALID) { - MakeTree(tile, tree, 0, 0, ct == CLEAR_ROUGH ? TREE_GROUND_ROUGH : TREE_GROUND_GRASS, GetClearDensity(tile)); + PlantTreesOnTile(tile, tree, 0, 0); } /* byte underflow */ @@ -697,15 +718,8 @@ void OnTick_Trees() /* place a tree at a random spot */ r = Random(); tile = TILE_MASK(r); - if (IsTileType(tile, MP_CLEAR) && - !IsBridgeAbove(tile) && - (ct = GetClearGround(tile), ct == CLEAR_GRASS || ct == CLEAR_ROUGH || ct == CLEAR_SNOW) && - (tree = GetRandomTreeType(tile, GB(r, 24, 8))) != TREE_INVALID) { - switch (ct) { - case CLEAR_GRASS: MakeTree(tile, tree, 0, 0, TREE_GROUND_GRASS, GetClearDensity(tile)); break; - case CLEAR_ROUGH: MakeTree(tile, tree, 0, 0, TREE_GROUND_ROUGH, 3); break; - default: MakeTree(tile, tree, 0, 0, TREE_GROUND_SNOW_DESERT, GetClearDensity(tile)); break; - } + if (CanPlantTreesOnTile(tile, false) && (tree = GetRandomTreeType(tile, GB(r, 24, 8))) != TREE_INVALID) { + PlantTreesOnTile(tile, tree, 0, 0); } }