diff --git a/docs/plugins/plant.rst b/docs/plugins/plant.rst index e5ebaad425..81f6a069d3 100644 --- a/docs/plugins/plant.rst +++ b/docs/plugins/plant.rst @@ -55,8 +55,9 @@ Examples Create a Tower Cap sapling at the cursor. ``plant create ""`` List all valid shrub and sapling IDs. -``plant create 198 -a tree`` - Create an Oak sapling at the cursor, ready to mature into a tree. +``plant create 203 -c -a tree`` + Create a Willow sapling at the cursor, even away from water features, + ready to mature into a tree. ``plant create single-grain_wheat 70,70,140`` Create a Single-grain Wheat shrub at (70, 70, 140.) ``plant grow`` @@ -82,7 +83,10 @@ Create Options ``-c``, ``--force`` Create plant even on tiles flagged ``no_grow`` and unset the flag. This flag is set on tiles that were originally boulders or pebbles, as well - as on some tiles found in deserts, etc. + as on some tiles found in deserts, etc. Also allow non-``[DRY]`` plants + (e.g., willow) to grow away (3+ tiles) from water features (i.e., pools, + brooks, and rivers,) and non-``[WET]`` plants (e.g., prickle berry) to + grow near them. ``-a``, ``--age `` Set the created plant to a specific age (in years.) ``value`` can be a non-negative integer, or one of the strings ``tree``/``1x1`` (3 years,) diff --git a/plugins/plant.cpp b/plugins/plant.cpp index 2a4ece4d06..9fb0f379b6 100644 --- a/plugins/plant.cpp +++ b/plugins/plant.cpp @@ -76,7 +76,7 @@ struct plant_options bool create = false; // Create a plant bool grow = false; // Grow saplings into trees bool del = false; // Remove plants - bool force = false; // Create plants on no_grow + bool force = false; // Create plants on no_grow or incompatible wet/dry bool shrubs = false; // Remove shrubs bool saplings = false; // Remove saplings bool trees = false; // Remove grown trees @@ -130,6 +130,34 @@ static bool tile_muddy(const df::coord &pos) return false; } +static bool tile_watery(const df::coord &pos) +{ // Determines if plant should be in wet or dry vector + int32_t x = pos.x, y = pos.y, z = pos.z - 1; + + for (int32_t dx = -2; dx <= 2; dx++) + { // Check 5x5 area under tile, skipping corners + for (int32_t dy = -2; dy <= 2; dy++) + { + if (abs(dx) == 2 && abs(dy) == 2) + continue; // Skip corners + + auto tt = Maps::getTileType(x+dx, y+dy, z); + if (!tt) + continue; // Invalid tile + + auto mat = tileMaterial(*tt); + if (mat == tiletype_material::POOL || + mat == tiletype_material::RIVER || + tileShape(*tt) == tiletype_shape::BROOK_BED) + { + return true; + } + } + } + + return false; +} + command_result df_createplant(color_ostream &out, const df::coord &pos, const plant_options &options) { auto col = Maps::getBlockColumn((pos.x / 48)*3, (pos.y / 48)*3); @@ -203,21 +231,28 @@ command_result df_createplant(color_ostream &out, const df::coord &pos, const pl return CR_FAILURE; } + bool is_watery = tile_watery(pos); + if (!options.force) + { // Check if plant compatible with wet/dry + if (is_watery && !p_raw->flags.is_set(plant_raw_flags::WET) || + !is_watery && !p_raw->flags.is_set(plant_raw_flags::DRY)) + { + out.printerr("Can't create plant: Plant type can't grow this %s water feature!\n" + "Override with --force\n", is_watery ? "close to" : "far from"); + return CR_FAILURE; + } + } + auto plant = df::allocate(); if (p_raw->flags.is_set(plant_raw_flags::TREE)) plant->hitpoints = 400000; else { - plant->hitpoints = 100000; plant->flags.bits.is_shrub = true; + plant->hitpoints = 100000; } - // This is correct except for RICE, DATE_PALM, and underground plants - // near pool/river/brook. These have both WET and DRY flags. - // Should more properly detect if near surface water feature. - if (!p_raw->flags.is_set(plant_raw_flags::DRY)) - plant->flags.bits.watery = true; - + plant->flags.bits.watery = is_watery; plant->material = options.plant_idx; plant->pos = pos; plant->grow_counter = options.age < 0 ? 0 : options.age;