diff -r 2c40faeef7a5 -r 889301acc299 src/tree_cmd.cpp --- a/src/tree_cmd.cpp Sun Feb 03 01:34:21 2008 +0000 +++ b/src/tree_cmd.cpp Sun Feb 03 20:34:26 2008 +0000 @@ -20,6 +20,8 @@ #include "player_func.h" #include "sound_func.h" #include "settings_type.h" +#include "water_map.h" +#include "water.h" #include "table/strings.h" #include "table/sprites.h" @@ -37,6 +39,66 @@ }; /** + * 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 bool CanPlantTreesOnTile(TileIndex tile, bool allow_desert) +{ + switch (GetTileType(tile)) { + case MP_WATER: + return !IsBridgeAbove(tile) && IsCoast(tile) && !IsSlopeWithOneCornerRaised(GetTileSlope(tile, NULL)); + + case MP_CLEAR: + return !IsBridgeAbove(tile) && !IsClearGround(tile, CLEAR_FIELDS) && !IsClearGround(tile, CLEAR_ROCKS) && + (allow_desert || !IsClearGround(tile, CLEAR_DESERT)); + + default: return false; + } +} + +/** + * 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 (GetTileType(tile)) { + case MP_WATER: + ground = TREE_GROUND_SHORE; + break; + + case MP_CLEAR: + 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; + } + break; + + default: NOT_REACHED(); + } + + 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. @@ -58,7 +120,7 @@ case LT_TROPIC: switch (GetTropicZone(tile)) { - case TROPICZONE_INVALID: return (TreeType)(seed * TREE_COUNT_SUB_TROPICAL / 256 + TREE_SUB_TROPICAL); + case TROPICZONE_NORMAL: return (TreeType)(seed * TREE_COUNT_SUB_TROPICAL / 256 + TREE_SUB_TROPICAL); case TROPICZONE_DESERT: return (TreeType)((seed > 12) ? TREE_INVALID : TREE_CACTUS); default: return (TreeType)(seed * TREE_COUNT_RAINFOREST / 256 + TREE_RAINFOREST); } @@ -82,16 +144,16 @@ 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 neither snow nor shore */ + TreeGround ground = GetTreeGround(tile); + if (ground != TREE_GROUND_SNOW_DESERT && ground != TREE_GROUND_SHORE) { 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 +177,7 @@ 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 +205,7 @@ * @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 +219,7 @@ 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 +246,7 @@ 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 +278,7 @@ 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); @@ -313,21 +362,30 @@ break; case MP_WATER: - msg = STR_3807_CAN_T_BUILD_ON_WATER; - continue; - break; - + if (!IsCoast(tile) || IsSlopeWithOneCornerRaised(GetTileSlope(tile, NULL))) { + msg = STR_3807_CAN_T_BUILD_ON_WATER; + continue; + } + /* FALL THROUGH */ case MP_CLEAR: - if (!IsTileOwner(tile, OWNER_NONE) || - IsBridgeAbove(tile)) { + if (IsBridgeAbove(tile)) { msg = STR_2804_SITE_UNSUITABLE; continue; } - switch (GetClearGround(tile)) { - case CLEAR_FIELDS: cost.AddCost(_price.clear_fields); break; - case CLEAR_ROCKS: cost.AddCost(_price.clear_rocks); break; - default: break; + if (IsTileType(tile, MP_CLEAR)) { + /* Remove fields or rocks. Note that the ground will get barrened */ + switch (GetClearGround(tile)) { + 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; + } } if (_game_mode != GM_EDITOR && IsValidPlayer(_current_player)) { @@ -337,7 +395,6 @@ if (flags & DC_EXEC) { TreeType treetype; - uint growth; treetype = (TreeType)p1; if (treetype == TREE_INVALID) { @@ -345,15 +402,11 @@ 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); } @@ -387,6 +440,7 @@ byte z; switch (GetTreeGround(ti->tile)) { + case TREE_GROUND_SHORE: DrawShoreTile(ti->tileh); break; case TREE_GROUND_GRASS: DrawClearLandTile(ti, GetTreeDensity(ti->tile)); break; case TREE_GROUND_ROUGH: DrawHillyLandTile(ti); break; default: DrawGroundSprite(_tree_sprites_1[GetTreeDensity(ti->tile)] + _tileh_to_sprite[ti->tileh], PAL_NONE); break; @@ -428,6 +482,7 @@ StartSpriteCombine(); + /* Do not draw trees when the invisible trees patch and transparency tree are set */ if (!(IsTransparencySet(TO_TREES) && _patches.invisible_trees)) { TreeListEnt te[4]; uint i; @@ -578,9 +633,13 @@ static void TileLoop_Trees(TileIndex tile) { - switch (_opt.landscape) { - case LT_TROPIC: TileLoopTreesDesert(tile); break; - case LT_ARCTIC: TileLoopTreesAlps(tile); break; + if (GetTreeGround(tile) == TREE_GROUND_SHORE) { + TileLoop_Water(tile); + } else { + switch (_opt.landscape) { + case LT_TROPIC: TileLoopTreesDesert(tile); break; + case LT_ARCTIC: TileLoopTreesAlps(tile); break; + } } TileLoopClearHelper(tile); @@ -626,19 +685,14 @@ 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 (IsTileType(tile, MP_CLEAR) && 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; } @@ -656,6 +710,7 @@ } else { /* just one tree, change type into MP_CLEAR */ switch (GetTreeGround(tile)) { + case TREE_GROUND_SHORE: MakeShore(tile); break; case TREE_GROUND_GRASS: MakeClear(tile, CLEAR_GRASS, GetTreeDensity(tile)); break; case TREE_GROUND_ROUGH: MakeClear(tile, CLEAR_ROUGH, 3); break; default: // snow or desert @@ -677,17 +732,14 @@ { 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 */ @@ -696,15 +748,8 @@ /* 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); } }