Changed plants_lib API to require a table argument when not using legacy
calling options. This opens the door for even more features in the future. Changed flowers, junglegrass, poisonivy to match. Made plants lib faster in some places, especially the surface-hunting algorithm, and especially over water. Fixed a few other misc. bugs. Made growth code properly execute all biome-control code before executing any string-named function or spawn_tree(). Tuned flowers settings. Made flowers require at least some light to spawn, made waterlilies require shallower water. Fixed a bug in water depth detection and made water depth depend on whether the bottom of the water area is dirt, dirt with grass, or sand, rather than just anything. Made waterlilies randomly rotate on spawning to break up the patterns (now has 16 orientations with the help of nodeboxes and facedir, requires only 3 new nodes). Smoothed edges of the regular waterlily texture. Made all flowers and water- lilies spawn using only 3 ABM calls instead of 8. Got rid of colon prefix node def overrides on all plants, since this is a modpack now instead of an integrated mod. Fixed a misspelled folder name for poisonivy. Fixed a bug in the wall detection routine - it returned the last wall found, not the first. Made the top-side-check for air only apply when spawning on top of the target rather than its sides/bottom. Many other features and enhancements have been made. Too many to list here. Please see API.txt for details.
453
API.txt
@ -1,6 +1,6 @@
|
||||
This document briefly describes the Plantlife API.
|
||||
|
||||
Last revision: 2013-01-18
|
||||
Last revision: 2013-01-25
|
||||
|
||||
=========
|
||||
Functions
|
||||
@ -22,91 +22,206 @@ at any time. See init.lua for more.
|
||||
|
||||
-----
|
||||
|
||||
The first of these, spawn_on_surfaces() is defined with quite a large number
|
||||
of variables. All of the variables below, if specified at all, must be
|
||||
specified exactly in the order given here. This function has no return value.
|
||||
The first function is an ABM-based spawner function originally created as
|
||||
part of Ironzorg's flowers mod. It has since been largely extended and
|
||||
expanded. There are two ways to call this function. Either via the legacy
|
||||
method like that which was used in the Flowers mod:
|
||||
|
||||
spawn_on_surfaces = function(sdelay, splant, sradius, schance, ssurface,
|
||||
savoid, seed_diff, lightmin, lightmax, nneighbors, ocount, facedir,
|
||||
depthmax, altitudemin, altitudemax, sbiome, sbiomesize, sbiomecount,
|
||||
airsize, aircount, tempmin, tempmax)
|
||||
spawn_on_surfaces(sdelay, splant, sradius, schance, ssurface, savoid)
|
||||
|
||||
The first several of these are all required, and are from the last version of
|
||||
the flowers mod, so this part of the API should be the same as before.
|
||||
Or, you can specify the various options with a single table as the parameter:
|
||||
|
||||
sdelay: The value passed to the ABM's interval parameter, in seconds.
|
||||
splant: The node name of the item to spawn (e.g.
|
||||
"flowers:flower_rose"). Note that if the plant is
|
||||
"poisonivy:seedling", and it's next to a wall at spawn
|
||||
time, it automatically becomes the wall-climbing variety.
|
||||
A plant will of course only be spawned if the node about
|
||||
to be replaced is air.
|
||||
sradius: Don't spawn within this many nodes of the avoid items
|
||||
mentioned below.
|
||||
schance: The value passed to the ABM's chance parameter, normally
|
||||
in the 10-100 range (1-in-X chance of operating on a given
|
||||
node, e.g. 1-in-10).
|
||||
ssurface: Table with the names of the nodes on which to spawn the
|
||||
plant in question, such as {"default:sand",
|
||||
"default:dirt_with_grass"}. It is not recommended to put
|
||||
"default:dirt" or "default:stone" into this table if you
|
||||
can do without it, as this will cause the engine to
|
||||
process potentially large numbers of such nodes when
|
||||
deciding when to execute the ABM and where it should
|
||||
operate.
|
||||
savoid: Table with a list of groups and/or node names to avoid
|
||||
when spawning the plant, such as {"group:flowers",
|
||||
"default:tree"}.
|
||||
spawn_on_surfaces({table of options})
|
||||
|
||||
From here down are several optional parameters. You can use as many as you
|
||||
need, but you must specify them in order. To keep the default values for
|
||||
those parameters you don't wish to alter, set them to nil in your function
|
||||
call.
|
||||
When used with the legacy interface, you must specify the parameters exactly
|
||||
in order, with the first five being mandatory and the last one being optional:
|
||||
|
||||
seed_diff: The Perlin seed difference value passed to the
|
||||
minetest.env:get_perlin() function. Used along with the
|
||||
global Perlin controls below to create the "biome" in
|
||||
which the plants will spawn. Usually a value of somewhere
|
||||
in the 10 to 100 range is good. Defaults to 0 if not
|
||||
provided.
|
||||
lightmin: Minimum amount of light necessary to make a plant spawn.
|
||||
Defaults to 0.
|
||||
lightmax: Maximum amount of light present to allow a plant to spawn.
|
||||
Defaults to the engine's MAX_LIGHT value of 14.
|
||||
nneighbors: Table with a list of neighboring nodes, passed to the ABM
|
||||
as the "neighbors" parameter, indicating what needs to be
|
||||
next to the node the plant is about to spawn on, such as
|
||||
{"default:stone","default:water_source"}. Defaults to the
|
||||
value of ssurface if not provided.
|
||||
ocount: There must be at least this many of the above neighbors in
|
||||
the eight spaces immediately surrounding the node the
|
||||
plant is about to spawn on for it to happen. Defaults to
|
||||
0.
|
||||
facedir: The value passed to the param2 variable when adding the
|
||||
plant node to the map. Defaults to 0.
|
||||
depthmax: If a node spawns on top of a water source, the water must
|
||||
be at most this deep. Defaults to 1 node.
|
||||
altitudemin: Items must be at this altitude or higher to spawn at all.
|
||||
Defaults to -31000.
|
||||
altitudemax: But no higher than this altitude. Defaults to +31000.
|
||||
sbiome: List of nodes that must be somewhere in the vicinity in
|
||||
order for the plant to spawn. Typically this would be
|
||||
something like "default:water_source" or "default:sand".
|
||||
Defaults to the value of ssurface if not provided.
|
||||
sbiomesize: How large of an area to check for the above node.
|
||||
Specifically, this checks a cuboid area centered on the
|
||||
node to be spawned on, 3 tall and this wide/long.
|
||||
Defaults to 0.
|
||||
sbiomecount: How many of the above nodes must be within that radius.
|
||||
Defaults to 1.
|
||||
airradius: How large of an area to check for air around the target.
|
||||
Defaults to 0 (only check the target).
|
||||
aircount: How many of the surrounding nodes need to be air for the
|
||||
above check to return true. Defaults to 1.
|
||||
tempmin: Minimum 2d Perlin value (which has a floating point range of
|
||||
-1 to +1) needed in the temperature map for the desired
|
||||
plant to spawn. Defaults to -1 if not supplied.
|
||||
tempmax: Maximum temperature. Defaults to +1.
|
||||
sdelay: The value passed to the ABM's interval parameter, in
|
||||
seconds.
|
||||
splant: The node name of the item to spawn (e.g.
|
||||
"flowers:flower_rose"). Note that if the plant is
|
||||
"poisonivy:seedling", and it's next to a wall at spawn
|
||||
time, it automatically becomes the wall-climbing
|
||||
variety. A plant will of course only be spawned if the
|
||||
node about to be replaced is air.
|
||||
sradius: Don't spawn within this many nodes of the avoid items
|
||||
mentioned below. If set to nil, this check is
|
||||
skipped.
|
||||
schance: The value passed to the ABM's chance parameter,
|
||||
normally in the 10-100 range (1-in-X chance of
|
||||
operating on a given node, e.g. 1-in-10).
|
||||
ssurface: String with the name of the node on which to spawn
|
||||
the plant in question, such as "default:sand" or
|
||||
"default:dirt_with_grass". It is not recommended to
|
||||
put air, stone, or plain dirt here if you can use some
|
||||
other node, as doing so will cause the engine to
|
||||
process potentially large numbers of such nodes when
|
||||
deciding when to execute the ABM and where it should
|
||||
operate.
|
||||
savoid: Table with a list of groups and/or node names to avoid
|
||||
when spawning the plant, such as {"group:flowers",
|
||||
"default:tree"}. If not specified, this defaults to
|
||||
the value of splant.
|
||||
|
||||
When passed a table as the argument, and thus using the modern calling method,
|
||||
you must pass at least four arguments as regular keyed entries in the table,
|
||||
in any order:
|
||||
|
||||
plants_lib: spawn_on_surfaces({
|
||||
spawn_plants = {table}, -- List of plants to spawn with this ABM call.
|
||||
-- The program will choose one of these at
|
||||
-- random each time the ABM executes. The
|
||||
-- more nodes you can pack into this parameter
|
||||
-- to avoid making too many calls to this
|
||||
-- function, the lower the CPU load will
|
||||
-- likely be.
|
||||
spawn_delay = number, -- same as sdelay
|
||||
spawn_chance = number, -- same as schance
|
||||
spawn_surfaces = {table} -- List of node names on which the plants
|
||||
-- should be spawned. As with the single-
|
||||
-- node "ssurface" option in the legacy API,
|
||||
-- you should not put stone, air, etc. here.
|
||||
|
||||
-- From here down are several optional
|
||||
-- parameters.
|
||||
|
||||
avoid_nodes = {table}, -- same meaning as savoid, above
|
||||
avoid_radius = num, -- same as sradius
|
||||
seed_diff = num -- The Perlin seed difference value passed to
|
||||
-- the minetest.env:get_perlin() function.
|
||||
-- Used along with the global Perlin controls
|
||||
-- below to create the "biome" in which the
|
||||
-- plants will spawn. Defaults to 0 if not
|
||||
-- provided.
|
||||
light_min = num, -- Minimum amount of light necessary to make a
|
||||
-- plant spawn. Defaults to 0.
|
||||
light_max = num, -- Maximum amount of light needed to spawn.
|
||||
-- Defaults to the engine's MAX_LIGHT value of
|
||||
-- 14.
|
||||
neighbors = {table}, -- List of neighboring nodes that need to be
|
||||
-- immediately next to the node the plant is
|
||||
-- about to spawn on. Can also be a string
|
||||
-- with a single node name. It is both passed
|
||||
-- to the ABM as the "neighbors" parameter,
|
||||
-- and is used to manually check the
|
||||
-- adjacent nodes. It only takes one of these
|
||||
-- for the spawn routine to mark the target as
|
||||
-- spawnable. Defaults to nil (ignored).
|
||||
ncount = num, -- There must be at least this many of the
|
||||
-- above neighbors in the eight spaces
|
||||
-- immediately surrounding the node the plant
|
||||
-- is about to spawn on for it to happen. If
|
||||
-- not provided, this check is disabled.
|
||||
facedir = num, -- The value passed to the param2 variable
|
||||
-- when adding the node to the map. Defaults
|
||||
-- to 0. Be sure that the value you use here
|
||||
-- (and the range thereof) is appropriate for
|
||||
-- the type of node you're spawning.
|
||||
random_facedir = {table}, -- If set, the table should contain two
|
||||
-- values. If they're both provided, the
|
||||
-- spawned plant will be given a random
|
||||
-- facedir value in the range specified by
|
||||
-- these two numbers. Overrides the facedir
|
||||
-- parameter above, if it exists. Use {0,3}
|
||||
-- if you want the full range for wallmounted
|
||||
-- nodes, or {2,5} for most everything else,
|
||||
-- or any other pair of numbers in the 0 to 5
|
||||
-- range, as appropriate for the node you want
|
||||
-- to spawn.
|
||||
verticals_list = {table} -- List of nodes that should be considered to
|
||||
-- be natural walls.
|
||||
alt_wallnode = "string", -- If specified, this node will be
|
||||
-- substituted in place of the plant(s)
|
||||
-- defined by spawn_plants above, if the spawn
|
||||
-- target has one or more adjacent walls. In
|
||||
-- such a case, the two above facedir
|
||||
-- parameters will be ignored.
|
||||
depth_max = num, -- If the object spawns on top of a water
|
||||
-- source, the water must be at most this
|
||||
-- deep. Defaults to 1 node.
|
||||
min_elevation = num, -- Surface must be at this altitude or higher
|
||||
-- to spawn at all. Defaults to -31000...
|
||||
max_elevation = num, -- ...but must be no higher than this
|
||||
-- altitude. Defaults to +31000.
|
||||
near_nodes = {table}, -- List of nodes that must be somewhere in the
|
||||
-- vicinity in order for the plant to spawn.
|
||||
-- Can also be a string with a single node
|
||||
-- name. If not provided, this check is
|
||||
-- disabled.
|
||||
near_nodes_size = num, -- How large of an area to check for the above
|
||||
-- node. Specifically, this checks a flat
|
||||
-- horizontal area centered on the node to be
|
||||
-- spawned on. Defaults to 0, but is ignored
|
||||
-- if the above near_nodes value is not set.
|
||||
near_nodes_vertical = num, -- Used with the size value above, this
|
||||
-- extends the vertical range of the near
|
||||
-- nodes search. Basically, this turns the
|
||||
-- flat region described above into a cuboid
|
||||
-- region. The area to be checked will extend
|
||||
-- this high AND this low above/below the
|
||||
-- target node, centered thereon. Defaults to
|
||||
-- 1 (check only the layer above, the layer
|
||||
-- at, and the layer below the target node),
|
||||
-- but is ignored if near_nodes is not set.
|
||||
near_nodes_count = num, -- How many of the above nodes must be within
|
||||
-- that radius. Defaults to 1 but is ignored
|
||||
-- if near_nodes isn't set. Bear in mind that
|
||||
-- the total area to be checked is equal to
|
||||
-- (near_nodes_size^2)*near_nodes_vertical*2.
|
||||
-- so for example, if size is 10 and vertical
|
||||
-- is 4 then the area is (10^2)*8 = 800 nodes
|
||||
-- in size, so you'll want to make sure you
|
||||
-- specify a value appropriate for the amount
|
||||
-- in question.
|
||||
air_size = num, -- How large of an area to check for air
|
||||
-- above and around the target. If omitted,
|
||||
-- only the space above the target is checked.
|
||||
-- This does not check for air at the sides or
|
||||
-- below the target.
|
||||
air_count = num, -- How many of the surrounding nodes need to
|
||||
-- be air for the above check to return true.
|
||||
-- If omitted, only the space above the target
|
||||
-- is checked.
|
||||
plantlife_limit = num, -- The value compared against the generic
|
||||
-- "plants can grow here" Perlin noise layer.
|
||||
-- Smaller numbers result in more abundant
|
||||
-- plants. Range of -1 to +1, with values in
|
||||
-- the range of about 0 to 0.5 being most
|
||||
-- useful. Defaults to 0.1.
|
||||
temp_min = num, -- Minimum temperature needed for the desired
|
||||
-- object to spawn. This is a 2d Perlin
|
||||
-- value, which has an inverted range of +1 to
|
||||
-- -1. Larger values represent *colder*
|
||||
-- temperatures, so this value is actually the
|
||||
-- upper end of the desired Perlin range. See
|
||||
-- the temperature map section at the bottom
|
||||
-- of this document for details on how these
|
||||
-- values work. Defaults to +1 (unlimited
|
||||
-- coldness).
|
||||
temp_max = num, -- Maximum temperature/lower end of the Perlin
|
||||
-- range. Defaults to -1 (unlimited heat).
|
||||
spawn_on_side = bool, -- Set this to true to spawn the node on one
|
||||
-- side of the target node rather than the
|
||||
-- top. The code will search for an airspace
|
||||
-- to the side of the target, then spawn the
|
||||
-- plant at the first one found. The above
|
||||
-- facedir and random_facedir parameters are
|
||||
-- ignored in this case. If the above
|
||||
-- parameters for selecting generic wall nodes
|
||||
-- are provided, this option is ignored.
|
||||
-- Important note: the facedir values assigned
|
||||
-- by this option only make sense with
|
||||
-- wallmounted nodes (nodes which don't use
|
||||
-- facedir won't be affected).
|
||||
spawn_on_bottom = bool, -- If set to true, spawn the object below the
|
||||
-- target node instead of above it. The above
|
||||
-- spawn_on_side variable takes precedence
|
||||
-- over this one if both happen to be true.
|
||||
-- When using this option with the random
|
||||
-- facedir function above, the values given to
|
||||
-- the facedir parameter are for regular
|
||||
-- nodes, not wallmounted.
|
||||
})
|
||||
|
||||
By default, if a biome node, size, and count are not defined, the biome
|
||||
checking is disabled. Same holds true for the nneighbors bit above that.
|
||||
@ -120,7 +235,7 @@ node (see below):
|
||||
|
||||
plantslib:register_generate_plant(biome, function_or_treedef)
|
||||
|
||||
Where "biome" is a table containing about a dozen variables:
|
||||
Where "biome" is a table containing about a dozen variables.
|
||||
|
||||
biome = {
|
||||
surface = "string", -- [*] what nodes to spawn on.
|
||||
@ -153,13 +268,23 @@ biome = {
|
||||
of the object being spawned.
|
||||
near_nodes_size = num, -- how wide of a search area to look for
|
||||
the nodes in that list.
|
||||
near_nodes_vertical = num, -- How high/low of an area to search from
|
||||
-- the target node.
|
||||
near_nodes_count = num, -- at least this many of those nodes must be
|
||||
in the area.
|
||||
plantlife_limit = num, -- The value compared against the generic
|
||||
-- "plants can grow here" Perlin noise layer.
|
||||
-- Smaller numbers result in more abundant
|
||||
-- plants. Range of -1 to +1, with values in
|
||||
-- the range of about 0 to 0.5 being most
|
||||
-- useful. Defaults to 0.1.
|
||||
temp_min = num, -- coldest allowable temperature for a plant
|
||||
to spawn (that is, the highest Perlin
|
||||
temperature map value).
|
||||
temp_max = num, -- warmest allowable temperature to spawn a
|
||||
plant (lowest Perlin temperature value).
|
||||
verticals_list = {table}, -- Same as with the spawn_on_surfaces
|
||||
-- function.
|
||||
}
|
||||
|
||||
[*] These entries are required for the spawn code to work. Everything else
|
||||
@ -179,82 +304,120 @@ with the position to spawn the tree on.
|
||||
-----
|
||||
|
||||
The third function, grow_plants() is used to turn the spawned nodes above
|
||||
into something else over time. This function has no return value, and is
|
||||
defined like so:
|
||||
into something else over time. This function has no return value, and accepts
|
||||
a table as the only parameter:
|
||||
|
||||
grow_plants = function(gdelay, gchance, gplant, gresult, dry_early_node,
|
||||
grow_nodes, facedir, need_wall, grow_vertically, height_limit,
|
||||
ground_nodes, grow_function, seed_diff)
|
||||
grow_plants({list of options})
|
||||
|
||||
gdelay: Passed as the ABM "interval" parameter, as with spawning.
|
||||
gchance: Passed as the ABM "chance" parameter.
|
||||
gplant: Name of the node being grown. This value is passed as the
|
||||
only item in the table given to the ABM as the nodenames
|
||||
parameter, so it is the plants themselves that are the ABM
|
||||
trigger, rather than the ground they spawned on. A plant
|
||||
will only grow if the node above it is air.
|
||||
gresult: Name of the node into which the above should transform
|
||||
when the ABM executes.
|
||||
dry_early_node: This value is ignored except for jungle grass, where it
|
||||
indicates which node the grass must be on in order for it
|
||||
to turn from "short" to default:dry_shrub.
|
||||
grow_nodes: One of these nodes must be under the plant in order for it to
|
||||
grow at all. Normally this should be the same as the list of
|
||||
surfaces passed to the spawning ABM as the "nodenames"
|
||||
parameter. This is so that the plant can be manually placed
|
||||
on something like a flower pot or something without it growing
|
||||
and eventually dieing. Defaults to "default:dirt_with_grass".
|
||||
facedir: Same as with spawning a plant. If supplied, this value is
|
||||
passed to the param2 variable when changing the plant. If
|
||||
nil or left out, no new param2 value is applied.
|
||||
need_wall: Set this to true if you the plant needs to grow against a
|
||||
wall. Defaults to false.
|
||||
grow_vertically: Set this to true if the plant needs to grow vertically, as
|
||||
in climbing poison ivy. Defaults to false.
|
||||
height_limit: Just how tall can a vertically-growing plant go? Set this
|
||||
accordingly. The mod will search straight down from the
|
||||
position being spawned at to find a ground node, set via the
|
||||
parameter below. Defaults to 62000 (unlimited).
|
||||
ground_nodes: What nodes should be treated as "the ground" below a
|
||||
vertically-growing plant. Usually this will be the same
|
||||
as the grow_nodes table, but might also include, for
|
||||
example, water or some other surrounding material.
|
||||
Defaults to "default:dirt_with_grass".
|
||||
grow_function: String indicating what function to use to grow the plant, if
|
||||
any, or a table with an L-Systems tree model, or nil. If it's
|
||||
nil, If it's nil, a regular plant will be inserted in place
|
||||
of the one being grown, per the above variables. If it's a
|
||||
string, the function named therein is executed and passed a
|
||||
parameter for the current position, followed by the "can grow
|
||||
here" and temperature map Perlin values at that location. If
|
||||
it's a table, the tree described by that table is spawned at
|
||||
the current position. In both string and table cases, all
|
||||
parameters from gresult to ground_nodes, except for
|
||||
grow_nodes, are ignored.
|
||||
seed_diff: The Perlin seed diff to be use to calculate the first noise
|
||||
value given to the above grow_function. Should be the same as
|
||||
the seed diff used when first spawning the plant that's being
|
||||
grown.
|
||||
These are defined like so:
|
||||
|
||||
plants_lib:grow_plants({
|
||||
|
||||
grow_plant = "string", -- Name of the node to be grown into something
|
||||
-- else. This value is passed to the ABM as
|
||||
-- the "nodenames" parameter, so it is the
|
||||
-- plants themselves that are the ABM trigger,
|
||||
-- rather than the ground they spawned on. A
|
||||
-- plant will only grow if the node above it
|
||||
-- is air. Can also be a table, but note that
|
||||
-- all nodes referenced therein will be grown
|
||||
-- into the same object.
|
||||
grow_delay = num, -- Passed as the ABM "interval" parameter, as
|
||||
-- with spawning.
|
||||
grow_chance = num, -- Passed as the ABM "chance" parameter.
|
||||
grow_result = "string", -- Name of the node into which the grow_plant
|
||||
-- node(s) should transform when the ABM
|
||||
-- executes.
|
||||
dry_early_node = "string" -- This value is ignored except for jungle
|
||||
-- grass (a corner case needed by that mod),
|
||||
-- where it indicates which node the grass
|
||||
-- must be on in order for it to turn from
|
||||
-- the short size to "default:dry_shrub"
|
||||
-- instead of the medium size.
|
||||
grow_nodes = {table}, -- One of these nodes must be under the plant
|
||||
-- in order for it to grow at all. Normally
|
||||
-- this should be the same as the list of
|
||||
-- surfaces passed to the spawning ABM as the
|
||||
-- "nodenames" parameter. This is so that the
|
||||
-- plant can be manually placed on something
|
||||
-- like a flower pot or something without it
|
||||
-- growing and eventually dieing. Defaults to
|
||||
-- "default:dirt_with_grass".
|
||||
facedir = num, -- Same as with spawning a plant.
|
||||
need_wall = bool, -- Set this to true if you the plant needs to
|
||||
-- grow against a wall. Defaults to false.
|
||||
verticals_list = {table}, -- List of nodes that should be considered
|
||||
-- to be wall surfaces when growing the plant
|
||||
-- vertically. If not provided, the walls
|
||||
-- check is skipped.
|
||||
grow_vertically = bool, -- Set this to true if the plant needs to grow
|
||||
-- vertically, as in climbing poison ivy.
|
||||
-- Defaults to false.
|
||||
height_limit = num, -- Set this to limit how tall the desired node
|
||||
-- can grow. The mod will search straight
|
||||
-- down from the position being spawned at to
|
||||
-- find a ground node, set via the parameter
|
||||
-- below. Defaults to 5 nodes.
|
||||
ground_nodes = {table}, -- What nodes should be treated as "the
|
||||
-- ground" below a vertically-growing plant.
|
||||
-- Usually this should be the same as the
|
||||
-- grow_nodes table, but might also include,
|
||||
-- for example, water or some other
|
||||
-- surrounding material. Defaults to
|
||||
-- "default:dirt_with_grass".
|
||||
grow_function = something, -- [*] see below.
|
||||
seed_diff = num, -- [*] see below.
|
||||
})
|
||||
|
||||
|
||||
[*] grow_function can take one of three possible settings: it can be nil (or
|
||||
not provided), a string, or a table.
|
||||
|
||||
If it is not provided or it's set to nil, all of the regular growing code
|
||||
is executed normally. The value of seed_diff, if any, is ignored in this
|
||||
case.
|
||||
|
||||
If this value is set to a simple string, this is treated as the name of
|
||||
the function to use to grow the plant. In this case, all of the usual
|
||||
growing code is executeed, but then instead of a plant being simply added
|
||||
to the world, grow_result is ignored and the named function is executed
|
||||
and passed a few parmeters:
|
||||
|
||||
somefunction(pos, perlin1, perlin2)
|
||||
|
||||
These values represent the current position (the usual table), the
|
||||
Perlin noise value for that spot in the generic "plants can grow here"
|
||||
map for the seed_diff value above, the Perlin value for that same spot
|
||||
from the temperature map, and the detected neighboring wall face, if
|
||||
there was one (or nil if not). If seed_diff is not provided, it
|
||||
defaults to 0.
|
||||
|
||||
If this variable is instead set to a table, it is treated an an L-Systems
|
||||
tree definition. All of the growing code is executed in the usual manner,
|
||||
then the tree described by that definition is spawned at the current
|
||||
position instead, and grow_result is ignored.
|
||||
|
||||
-----
|
||||
|
||||
Of the few helper functions, plant_valid_wall() expects only a single
|
||||
parameter, "pos", which is the usual table indicating the coordinates around
|
||||
which to search for adjacent walls. This function returns the location of the
|
||||
first wall found as a facedir value, or nil if there are no adjacent walls.
|
||||
Of the few helper functions, plantslib:find_adjacent_wall() expects a position
|
||||
parameter and a table with the list of nodes that should be considered as
|
||||
walls. The code will search around the given position for a neighboring wall,
|
||||
returning the first one it finds as a facedir value, or nil if there are no
|
||||
adjacent walls.
|
||||
|
||||
-----
|
||||
|
||||
is_node_loaded() is defined in exactly the same manner (that is, "node_pos" is
|
||||
a set of coordinates), and acts as a wrapper for the
|
||||
plantslib:is_node_loaded() is defined in exactly the same manner (that is,
|
||||
"node_pos" is a set of coordinates), and acts as a wrapper for the
|
||||
minetest.env:get_node_or_nil(node_pos) function. Returns true if the node in
|
||||
question is already loaded, or false if not.
|
||||
|
||||
-----
|
||||
|
||||
dbg() is a simple debug output function which takes one string parameter. It
|
||||
just checks if plantlife_debug is true and outputs the phrase "[Plantlife] "
|
||||
followed by the supplied string, via the print() function.
|
||||
plantslib:dbg() is a simple debug output function which takes one string
|
||||
parameter. It just checks if DEBUG is true and outputs the phrase
|
||||
"[Plantlife] " followed by the supplied string, via the print() function, if
|
||||
so.
|
||||
|
||||
|
||||
===============
|
||||
|
222
flowers/init.lua
@ -1,27 +1,25 @@
|
||||
-- This file supplies flowers for the plantlife modpack
|
||||
-- Last revision: 2013-01-24
|
||||
|
||||
local spawn_delay = 2000 -- 2000
|
||||
local spawn_chance = 100 -- 100
|
||||
local flowers_seed_diff = plantslib.plantlife_seed_diff+20
|
||||
local SPAWN_DELAY = 1000
|
||||
local SPAWN_CHANCE = 200
|
||||
local flowers_seed_diff = 349
|
||||
|
||||
local flowers_list = {
|
||||
{ "Rose", "rose", spawn_delay, 10, spawn_chance , 10},
|
||||
{ "Tulip", "tulip", spawn_delay, 10, spawn_chance , 10},
|
||||
{ "Yellow Dandelion", "dandelion_yellow", spawn_delay, 10, spawn_chance*2 , 10},
|
||||
{ "White Dandelion", "dandelion_white", spawn_delay, 10, spawn_chance*2 , 10},
|
||||
{ "Blue Geranium", "geranium", spawn_delay, 10, spawn_chance , 10},
|
||||
{ "Viola", "viola", spawn_delay, 10, spawn_chance , 10},
|
||||
{ "Cotton Plant", "cotton", spawn_delay, 10, spawn_chance*2 , 10},
|
||||
{ "Rose", "rose"},
|
||||
{ "Tulip", "tulip"},
|
||||
{ "Yellow Dandelion", "dandelion_yellow"},
|
||||
{ "White Dandelion", "dandelion_white"},
|
||||
{ "Blue Geranium", "geranium"},
|
||||
{ "Viola", "viola"},
|
||||
{ "Cotton Plant", "cotton"},
|
||||
}
|
||||
|
||||
for i in ipairs(flowers_list) do
|
||||
local flowerdesc = flowers_list[i][1]
|
||||
local flower = flowers_list[i][2]
|
||||
local delay = flowers_list[i][3]
|
||||
local radius = flowers_list[i][4]
|
||||
local chance = flowers_list[i][5]
|
||||
|
||||
minetest.register_node(":flowers:flower_"..flower, {
|
||||
minetest.register_node("flowers:flower_"..flower, {
|
||||
description = flowerdesc,
|
||||
drawtype = "plantlike",
|
||||
tiles = { "flower_"..flower..".png" },
|
||||
@ -38,7 +36,7 @@ for i in ipairs(flowers_list) do
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_node(":flowers:flower_"..flower.."_pot", {
|
||||
minetest.register_node("flowers:flower_"..flower.."_pot", {
|
||||
description = flowerdesc.." in a pot",
|
||||
drawtype = "plantlike",
|
||||
tiles = { "flower_"..flower.."_pot.png" },
|
||||
@ -63,29 +61,100 @@ for i in ipairs(flowers_list) do
|
||||
"flowers:flower_"..flower
|
||||
}
|
||||
})
|
||||
|
||||
plantslib:spawn_on_surfaces(delay, "flowers:flower_"..flower, radius, chance, "default:dirt_with_grass", {"group:flower", "group:poisonivy"}, flowers_seed_diff)
|
||||
end
|
||||
|
||||
minetest.register_node(":flowers:flower_waterlily", {
|
||||
minetest.register_node("flowers:flower_waterlily", {
|
||||
description = "Waterlily",
|
||||
drawtype = "raillike",
|
||||
drawtype = "nodebox",
|
||||
tiles = { "flower_waterlily.png" },
|
||||
inventory_image = "flower_waterlily.png",
|
||||
wield_image = "flower_waterlily.png",
|
||||
sunlight_propagates = true,
|
||||
paramtype = "light",
|
||||
paramtype2 = "wallmounted",
|
||||
paramtype2 = "facedir",
|
||||
walkable = false,
|
||||
groups = { snappy = 3,flammable=2,flower=1 },
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.4, -0.5, -0.4, 0.4, -0.45, 0.4 },
|
||||
},
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.49, -0.5, 0.5, -0.49, 0.5 },
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_node(":flowers:flower_seaweed", {
|
||||
minetest.register_node("flowers:flower_waterlily_225", {
|
||||
description = "Waterlily",
|
||||
drawtype = "nodebox",
|
||||
tiles = { "flower_waterlily_22.5.png" },
|
||||
inventory_image = "flower_waterlily.png",
|
||||
wield_image = "flower_waterlily.png",
|
||||
sunlight_propagates = true,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = false,
|
||||
groups = { snappy = 3,flammable=2,flower=1, not_in_creative_inventory=1 },
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.4, -0.5, -0.4, 0.4, -0.45, 0.4 },
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.49, -0.5, 0.5, -0.49, 0.5 },
|
||||
},
|
||||
drop = "flowers:flower_waterlily"
|
||||
})
|
||||
|
||||
minetest.register_node("flowers:flower_waterlily_45", {
|
||||
description = "Waterlily",
|
||||
drawtype = "raillike",
|
||||
tiles = { "flower_waterlily_45.png" },
|
||||
inventory_image = "flower_waterlily.png",
|
||||
wield_image = "flower_waterlily.png",
|
||||
sunlight_propagates = true,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = false,
|
||||
groups = { snappy = 3,flammable=2,flower=1, not_in_creative_inventory=1 },
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.4, -0.5, -0.4, 0.4, -0.45, 0.4 },
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.49, -0.5, 0.5, -0.49, 0.5 },
|
||||
},
|
||||
drop = "flowers:flower_waterlily"
|
||||
})
|
||||
|
||||
minetest.register_node("flowers:flower_waterlily_675", {
|
||||
description = "Waterlily",
|
||||
drawtype = "nodebox",
|
||||
tiles = { "flower_waterlily_67.5.png" },
|
||||
inventory_image = "flower_waterlily.png",
|
||||
wield_image = "flower_waterlily.png",
|
||||
sunlight_propagates = true,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = false,
|
||||
groups = { snappy = 3,flammable=2,flower=1, not_in_creative_inventory=1 },
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.4, -0.5, -0.4, 0.4, -0.45, 0.4 },
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.49, -0.5, 0.5, -0.49, 0.5 },
|
||||
},
|
||||
drop = "flowers:flower_waterlily"
|
||||
})
|
||||
|
||||
minetest.register_node("flowers:flower_seaweed", {
|
||||
description = "Seaweed",
|
||||
drawtype = "signlike",
|
||||
tiles = { "flower_seaweed.png" },
|
||||
@ -103,12 +172,99 @@ minetest.register_node(":flowers:flower_seaweed", {
|
||||
},
|
||||
})
|
||||
|
||||
plantslib:spawn_on_surfaces(spawn_delay/2, "flowers:flower_waterlily", 3, spawn_chance*2, "default:water_source" , {"group:flower"}, flowers_seed_diff, 10, nil, nil, nil, nil, 4)
|
||||
-- spawn ABM registrations
|
||||
|
||||
plantslib:spawn_on_surfaces(spawn_delay*2, "flowers:flower_seaweed" , 0.1, spawn_chance*2, "default:water_source" , {"group:flower"}, flowers_seed_diff, 4, 10, {"default:dirt_with_grass"}, 0, 1)
|
||||
plantslib:spawn_on_surfaces(spawn_delay*2, "flowers:flower_seaweed" , 0.1, spawn_chance*2, "default:dirt_with_grass", {"group:flower"}, flowers_seed_diff, 4, 10, {"default:water_source"} , 1, 1)
|
||||
plantslib:spawn_on_surfaces(spawn_delay*2, "flowers:flower_seaweed" , 0.1, spawn_chance*2, "default:stone" , {"group:flower"}, flowers_seed_diff, 4, 10, {"default:water_source"} , 6, 1)
|
||||
plantslib:spawn_on_surfaces({
|
||||
spawn_delay = SPAWN_DELAY,
|
||||
spawn_plants = {
|
||||
"flowers:flower_rose",
|
||||
"flowers:flower_tulip",
|
||||
"flowers:flower_geranium",
|
||||
"flowers:flower_viola",
|
||||
},
|
||||
avoid_radius = 10,
|
||||
spawn_chance = SPAWN_CHANCE*2,
|
||||
spawn_surfaces = {"default:dirt_with_grass"},
|
||||
avoid_nodes = {"group:flower", "group:poisonivy"},
|
||||
seed_diff = flowers_seed_diff,
|
||||
light_min = 9
|
||||
})
|
||||
|
||||
plantslib:spawn_on_surfaces({
|
||||
spawn_delay = SPAWN_DELAY,
|
||||
spawn_plants = {
|
||||
"flowers:flower_dandelion_yellow",
|
||||
"flowers:flower_dandelion_white",
|
||||
"flowers:flower_cotton",
|
||||
},
|
||||
avoid_radius = 7,
|
||||
spawn_chance = SPAWN_CHANCE,
|
||||
spawn_surfaces = {"default:dirt_with_grass"},
|
||||
avoid_nodes = {"group:flower", "group:poisonivy"},
|
||||
seed_diff = flowers_seed_diff,
|
||||
light_min = 9
|
||||
})
|
||||
|
||||
plantslib:spawn_on_surfaces({
|
||||
spawn_delay = SPAWN_DELAY/2,
|
||||
spawn_plants = {
|
||||
"flowers:flower_waterlily",
|
||||
"flowers:flower_waterlily_225",
|
||||
"flowers:flower_waterlily_45",
|
||||
"flowers:flower_waterlily_675"
|
||||
},
|
||||
avoid_radius = 2.5,
|
||||
spawn_chance = SPAWN_CHANCE*4,
|
||||
spawn_surfaces = {"default:water_source"},
|
||||
avoid_nodes = {"group:flower"},
|
||||
seed_diff = flowers_seed_diff,
|
||||
light_min = 9,
|
||||
depth_max = 2,
|
||||
random_facedir = {2,5}
|
||||
})
|
||||
|
||||
plantslib:spawn_on_surfaces({
|
||||
spawn_delay = SPAWN_DELAY*2,
|
||||
spawn_plants = {"flowers:flower_seaweed"},
|
||||
spawn_chance = SPAWN_CHANCE*2,
|
||||
spawn_surfaces = {"default:water_source"},
|
||||
avoid_nodes = {"group:flower"},
|
||||
seed_diff = flowers_seed_diff,
|
||||
light_min = 4,
|
||||
light_max = 10,
|
||||
neighbors = {"default:dirt_with_grass"},
|
||||
facedir = 1
|
||||
})
|
||||
|
||||
plantslib:spawn_on_surfaces({
|
||||
spawn_delay = SPAWN_DELAY*2,
|
||||
spawn_plants = {"flowers:flower_seaweed"},
|
||||
spawn_chance = SPAWN_CHANCE*2,
|
||||
spawn_surfaces = {"default:dirt_with_grass"},
|
||||
avoid_nodes = {"group:flower"},
|
||||
seed_diff = flowers_seed_diff,
|
||||
light_min = 4,
|
||||
light_max = 10,
|
||||
neighbors = {"default:water_source"},
|
||||
ncount = 1,
|
||||
facedir = 1
|
||||
})
|
||||
|
||||
plantslib:spawn_on_surfaces({
|
||||
spawn_delay = SPAWN_DELAY*2,
|
||||
spawn_plants = {"flowers:flower_seaweed"},
|
||||
spawn_chance = SPAWN_CHANCE*2,
|
||||
spawn_surfaces = {"default:stone"},
|
||||
avoid_nodes = {"group:flower"},
|
||||
seed_diff = flowers_seed_diff,
|
||||
light_min = 4,
|
||||
light_max = 10,
|
||||
neighbors = {"default:water_source"},
|
||||
ncount = 6,
|
||||
facedir = 1
|
||||
})
|
||||
|
||||
-- crafting recipes!
|
||||
|
||||
minetest.register_craftitem(":flowers:flower_pot", {
|
||||
description = "Flower Pot",
|
||||
@ -124,23 +280,23 @@ minetest.register_craft( {
|
||||
})
|
||||
|
||||
minetest.register_craftitem(":flowers:cotton", {
|
||||
description = "Cotton",
|
||||
image = "cotton.png",
|
||||
description = "Cotton",
|
||||
image = "cotton.png",
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "flowers:cotton 3",
|
||||
recipe ={
|
||||
{"flowers:flower_cotton"},
|
||||
}
|
||||
output = "flowers:cotton 3",
|
||||
recipe ={
|
||||
{"flowers:flower_cotton"},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "wool:white 2",
|
||||
recipe = {
|
||||
{'', '', ''},
|
||||
{'flowers:cotton', 'flowers:cotton', ''},
|
||||
{'flowers:cotton', 'flowers:cotton', ''},
|
||||
}
|
||||
})
|
||||
|
||||
print("[Flowers] Loaded.")
|
||||
|
Before Width: | Height: | Size: 221 B After Width: | Height: | Size: 413 B |
BIN
flowers/textures/flower_waterlily_22.5.png
Normal file
After Width: | Height: | Size: 491 B |
BIN
flowers/textures/flower_waterlily_45.png
Normal file
After Width: | Height: | Size: 502 B |
BIN
flowers/textures/flower_waterlily_67.5.png
Normal file
After Width: | Height: | Size: 471 B |
@ -1,10 +1,11 @@
|
||||
-- This file supplies jungle grass for the plantlife modpack
|
||||
-- Last revision: 2013-01-24
|
||||
|
||||
local spawn_delay = 2000 -- 2000
|
||||
local spawn_chance = 100 -- 100
|
||||
local grow_delay = 1000 -- 1000
|
||||
local grow_chance = 10 -- 10
|
||||
local junglegrass_seed_diff = plantslib.plantlife_seed_diff
|
||||
local SPAWN_DELAY = 1000
|
||||
local SPAWN_CHANCE = 200
|
||||
local GROW_DELAY = 500
|
||||
local GROW_CHANCE = 30
|
||||
local junglegrass_seed_diff = 329
|
||||
|
||||
local grasses_list = {
|
||||
{"junglegrass:shortest","junglegrass:short" },
|
||||
@ -13,7 +14,7 @@ local grasses_list = {
|
||||
{"default:junglegrass" , nil}
|
||||
}
|
||||
|
||||
minetest.register_node(':junglegrass:medium', {
|
||||
minetest.register_node('junglegrass:medium', {
|
||||
description = "Jungle Grass (medium height)",
|
||||
drawtype = 'plantlike',
|
||||
tile_images = { 'junglegrass_medium.png' },
|
||||
@ -32,7 +33,7 @@ minetest.register_node(':junglegrass:medium', {
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_node(':junglegrass:short', {
|
||||
minetest.register_node('junglegrass:short', {
|
||||
description = "Jungle Grass (short)",
|
||||
drawtype = 'plantlike',
|
||||
tile_images = { 'junglegrass_short.png' },
|
||||
@ -50,7 +51,7 @@ minetest.register_node(':junglegrass:short', {
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_node(':junglegrass:shortest', {
|
||||
minetest.register_node('junglegrass:shortest', {
|
||||
description = "Jungle Grass (very short)",
|
||||
drawtype = 'plantlike',
|
||||
tile_images = { 'junglegrass_shortest.png' },
|
||||
@ -68,12 +69,48 @@ minetest.register_node(':junglegrass:shortest', {
|
||||
},
|
||||
})
|
||||
|
||||
plantslib:spawn_on_surfaces(spawn_delay*2, "junglegrass:shortest", 4, spawn_chance, "default:dirt_with_grass", {"group:junglegrass", "default:junglegrass", "default:dry_shrub"}, junglegrass_seed_diff, 5)
|
||||
plantslib:spawn_on_surfaces(spawn_delay*2, "junglegrass:shortest", 4, spawn_chance*2, "default:sand" , {"group:junglegrass", "default:junglegrass", "default:dry_shrub"}, junglegrass_seed_diff, 5)
|
||||
plantslib:spawn_on_surfaces(spawn_delay*2, "junglegrass:shortest", 4, spawn_chance*3, "default:desert_sand" , {"group:junglegrass", "default:junglegrass", "default:dry_shrub"}, junglegrass_seed_diff, 5)
|
||||
plantslib:spawn_on_surfaces(spawn_delay*2, "junglegrass:shortest", 4, spawn_chance*3, "default:desert_sand" , {"group:junglegrass", "default:junglegrass", "default:dry_shrub"}, junglegrass_seed_diff, 5)
|
||||
plantslib:spawn_on_surfaces({
|
||||
spawn_delay = SPAWN_DELAY,
|
||||
spawn_plants = {"junglegrass:shortest"},
|
||||
avoid_radius = 4,
|
||||
spawn_chance = SPAWN_CHANCE,
|
||||
spawn_surfaces = {"default:dirt_with_grass", "default:cactus", "default:papyrus"},
|
||||
avoid_nodes = {"group:junglegrass", "default:junglegrass", "default:dry_shrub"},
|
||||
seed_diff = junglegrass_seed_diff,
|
||||
light_min = 5
|
||||
})
|
||||
|
||||
plantslib:spawn_on_surfaces({
|
||||
spawn_delay = SPAWN_DELAY,
|
||||
spawn_plants = {"junglegrass:shortest"},
|
||||
avoid_radius = 4,
|
||||
spawn_chance = SPAWN_CHANCE*2,
|
||||
spawn_surfaces = {"default:sand"},
|
||||
avoid_nodes = {"group:junglegrass", "default:junglegrass", "default:dry_shrub"},
|
||||
seed_diff = junglegrass_seed_diff,
|
||||
light_min = 5
|
||||
})
|
||||
|
||||
plantslib:spawn_on_surfaces({
|
||||
spawn_delay = SPAWN_DELAY,
|
||||
spawn_plants = {"junglegrass:shortest"},
|
||||
avoid_radius = 4,
|
||||
spawn_chance = SPAWN_CHANCE*5,
|
||||
spawn_surfaces = {"default:desert_sand"},
|
||||
avoid_nodes = {"group:junglegrass", "default:junglegrass", "default:dry_shrub"},
|
||||
seed_diff = junglegrass_seed_diff,
|
||||
light_min = 5
|
||||
})
|
||||
|
||||
for i in ipairs(grasses_list) do
|
||||
plantslib:grow_plants(grow_delay, grow_chance/2, grasses_list[i][1], grasses_list[i][2], "default:desert_sand", {"default:dirt_with_grass", "default:sand", "default:desert_sand"})
|
||||
plantslib:grow_plants({
|
||||
grow_delay = GROW_DELAY,
|
||||
grow_chance = GROW_CHANCE/2,
|
||||
grow_plant = grasses_list[i][1],
|
||||
grow_result = grasses_list[i][2],
|
||||
dry_early_node = "default:desert_sand",
|
||||
grow_nodes = {"default:dirt_with_grass", "default:sand", "default:desert_sand"}
|
||||
})
|
||||
end
|
||||
|
||||
print("[Junglegrass] Loaded.")
|
||||
|
@ -1,5 +1,5 @@
|
||||
-- Plantlife library mod by Vanessa Ezekowitz
|
||||
-- 2013-01-20
|
||||
-- last revision, 2013-01-24
|
||||
--
|
||||
-- License: WTFPL
|
||||
--
|
||||
@ -24,7 +24,7 @@ local temperature_octaves = 3
|
||||
local temperature_persistence = 0.5
|
||||
local temperature_scale = 150
|
||||
|
||||
local plantlife_limit = 0.1
|
||||
|
||||
|
||||
-- Local functions
|
||||
|
||||
@ -47,13 +47,18 @@ end
|
||||
|
||||
-- Spawn plants using the map generator
|
||||
|
||||
function plantslib:register_generate_plant(biome, funct_or_model)
|
||||
minetest.register_on_generated(plantslib:search_for_surfaces(minp, maxp, biome, funct_or_model))
|
||||
function plantslib:register_generate_plant(biomedef, funct_or_model)
|
||||
plantslib:dbg("Registered mapgen spawner:")
|
||||
plantslib:dbg(dump(biomedef))
|
||||
|
||||
minetest.register_on_generated(plantslib:search_for_surfaces(minp, maxp, biomedef, funct_or_model))
|
||||
end
|
||||
|
||||
function plantslib:search_for_surfaces(minp, maxp, biome, funct_or_model)
|
||||
function plantslib:search_for_surfaces(minp, maxp, biomedef, funct_or_model)
|
||||
return function(minp, maxp, blockseed)
|
||||
|
||||
local biome = biomedef
|
||||
|
||||
if biome.seed_diff == nil then biome.seed_diff = 0 end
|
||||
if biome.neighbors == nil then biome.neighbors = biome.surface end
|
||||
if biome.min_elevation == nil then biome.min_elevation = -31000 end
|
||||
@ -64,6 +69,8 @@ function plantslib:search_for_surfaces(minp, maxp, biome, funct_or_model)
|
||||
if biome.temp_max == nil then biome.temp_max = -1 end
|
||||
if biome.rarity == nil then biome.rarity = 50 end
|
||||
if biome.max_count == nil then biome.max_count = 5 end
|
||||
if biome.plantlife_limit == nil then biome.plantlife_limit = 0.1 end
|
||||
if biome.near_nodes_vertical == nil then biome.near_nodes_vertical = 1 end
|
||||
|
||||
plantslib:dbg("Started checking generated mapblock volume...")
|
||||
local searchnodes = minetest.env:find_nodes_in_area(minp, maxp, biome.surface)
|
||||
@ -80,131 +87,166 @@ function plantslib:search_for_surfaces(minp, maxp, biome, funct_or_model)
|
||||
and minetest.env:get_node(p_top).name == "air"
|
||||
and pos.y >= biome.min_elevation
|
||||
and pos.y <= biome.max_elevation
|
||||
and noise1 > plantlife_limit
|
||||
and noise1 > biome.plantlife_limit
|
||||
and noise2 <= biome.temp_min
|
||||
and noise2 >= biome.temp_max
|
||||
and (biome.ncount == nil or table.getn(minetest.env:find_nodes_in_area({x=pos.x-1, y=pos.y, z=pos.z-1}, {x=pos.x+1, y=pos.y, z=pos.z+1}, biome.neighbors)) > biome.ncount)
|
||||
and (biome.near_nodes == nil or table.getn(minetest.env:find_nodes_in_area({x=pos.x-biome.near_nodes_size, y=pos.y-1, z=pos.z-biome.near_nodes_size}, {x=pos.x+biome.near_nodes_size, y=pos.y+1, z=pos.z+biome.near_nodes_size}, biome.near_nodes)) >= biome.near_nodes_count)
|
||||
and (biome.near_nodes == nil or table.getn(minetest.env:find_nodes_in_area({x=pos.x-biome.near_nodes_size, y=pos.y-biome.near_nodes_vertical, z=pos.z-biome.near_nodes_size}, {x=pos.x+biome.near_nodes_size, y=pos.y+biome.near_nodes_vertical, z=pos.z+biome.near_nodes_size}, biome.near_nodes)) >= biome.near_nodes_count)
|
||||
and math.random(1,100) > biome.rarity
|
||||
then
|
||||
table.insert(in_biome_nodes, pos)
|
||||
num_in_biome_nodes = num_in_biome_nodes + 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
plantslib:dbg("Found "..num_in_biome_nodes.." surface nodes of type "..biome.surface.." in 5x5x5 mapblock volume at {"..dump(minp)..":"..dump(maxp).."} to check.")
|
||||
|
||||
if num_in_biome_nodes > 0 then
|
||||
plantslib:dbg("Found "..num_in_biome_nodes.." surface nodes of type "..biome.surface.." in 5x5x5 mapblock volume at {"..dump(minp)..":"..dump(maxp).."} to check.")
|
||||
for i = 1,biome.max_count do
|
||||
plantslib:dbg("Calculated maximum of "..math.min(biome.max_count*3, num_in_biome_nodes).." nodes to be checked in that list.")
|
||||
for i = 1, math.min(biome.max_count, num_in_biome_nodes) do
|
||||
local tries = 0
|
||||
local spawned = false
|
||||
while tries < 2 and not planted do
|
||||
while tries < 2 and not spawned do
|
||||
local pos = in_biome_nodes[math.random(1, num_in_biome_nodes)]
|
||||
local p_top = { x = pos.x, y = pos.y + 1, z = pos.z }
|
||||
if minetest.env:find_node_near(p_top, biome.avoid_radius + math.random(-1.5,1.5), biome.avoid_nodes) == nil then
|
||||
spawned = true
|
||||
if type(funct_or_model) == "table" then
|
||||
plantslib:dbg("Spawn tree at {"..dump(pos).."}")
|
||||
|
||||
--[[
|
||||
for v = 0,10 do
|
||||
minetest.env:remove_node({ x = pos.x, y = pos.y + v, z = pos.z })
|
||||
minetest.env:remove_node({ x = pos.x-1, y = pos.y + v, z = pos.z })
|
||||
minetest.env:remove_node({ x = pos.x+1, y = pos.y + v, z = pos.z })
|
||||
minetest.env:remove_node({ x = pos.x, y = pos.y + v, z = pos.z-1 })
|
||||
minetest.env:remove_node({ x = pos.x, y = pos.y + v, z = pos.z+1 })
|
||||
end
|
||||
]]--
|
||||
|
||||
minetest.env:spawn_tree(pos, funct_or_model)
|
||||
else
|
||||
plantslib:dbg("Call function: "..funct_or_model.."("..dump(pos)..")")
|
||||
plantslib:dbg("Call function: "..funct_or_model.."("..dump(pos)..")")
|
||||
assert(loadstring(funct_or_model.."("..dump(pos)..")"))()
|
||||
end
|
||||
else
|
||||
tries = tries + 1
|
||||
spawned = false
|
||||
plantslib:dbg("Couldn't spawn a tree at {"..dump(pos).."} -- trying again elsewhere")
|
||||
plantslib:dbg("No room to spawn object at {"..dump(pos).."} -- trying again elsewhere")
|
||||
end
|
||||
end
|
||||
if tries == 2 and spawned == false then
|
||||
plantslib:dbg("Unable to spawn that tree. Giving up on it.")
|
||||
if tries == 2 then
|
||||
plantslib:dbg("Unable to spawn that object. Giving up on it.")
|
||||
end
|
||||
end
|
||||
end
|
||||
plantslib:dbg("Finished checking generated area.")
|
||||
end
|
||||
end
|
||||
|
||||
-- The spawning ABM
|
||||
|
||||
function plantslib:spawn_on_surfaces(
|
||||
sdelay,
|
||||
splant,
|
||||
sradius,
|
||||
schance,
|
||||
ssurface,
|
||||
savoid,
|
||||
seed_diff,
|
||||
lightmin,
|
||||
lightmax,
|
||||
nneighbors,
|
||||
ocount,
|
||||
facedir,
|
||||
depthmax,
|
||||
altmin,
|
||||
altmax,
|
||||
sbiome,
|
||||
sbiomesize,
|
||||
sbiomecount,
|
||||
airsize,
|
||||
aircount,
|
||||
tempmin,
|
||||
tempmax)
|
||||
if seed_diff == nil then seed_diff = 0 end
|
||||
if lightmin == nil then lightmin = 0 end
|
||||
if lightmax == nil then lightmax = LIGHT_MAX end
|
||||
if nneighbors == nil then nneighbors = ssurface end
|
||||
if ocount == nil then ocount = -1 end
|
||||
if depthmax == nil then depthmax = 1 end
|
||||
if altmin == nil then altmin = -31000 end
|
||||
if altmax == nil then altmax = 31000 end
|
||||
if sbiome == nil then sbiome = "" end
|
||||
if sbiomesize == nil then sbiomesize = 0 end
|
||||
if sbiomecount == nil then sbiomecount = 1 end
|
||||
if airsize == nil then airsize = 0 end
|
||||
if aircount == nil then aircount = 1 end
|
||||
if tempmin == nil then tempmin = -2 end
|
||||
if tempmax == nil then tempmax = 2 end
|
||||
function plantslib:spawn_on_surfaces(sd,sp,sr,sc,ss,sa)
|
||||
|
||||
local biome = {}
|
||||
|
||||
if type(sd) ~= "table" then
|
||||
biome.spawn_delay = sd -- old api expects ABM interval param here.
|
||||
biome.spawn_plants = {sp}
|
||||
biome.avoid_radius = sr
|
||||
biome.spawn_chance = sc
|
||||
biome.spawn_surfaces = {ss}
|
||||
biome.avoid_nodes = sa
|
||||
else
|
||||
biome = sd
|
||||
end
|
||||
|
||||
if biome.seed_diff == nil then biome.seed_diff = 0 end
|
||||
if biome.light_min == nil then biome.light_min = 0 end
|
||||
if biome.light_max == nil then biome.light_max = 15 end
|
||||
if biome.depth_max == nil then biome.depth_max = 1 end
|
||||
if biome.min_elevation == nil then biome.min_elevation = -31000 end
|
||||
if biome.max_elevation == nil then biome.max_elevation = 31000 end
|
||||
if biome.temp_min == nil then biome.temp_min = 1 end
|
||||
if biome.temp_max == nil then biome.temp_max = -1 end
|
||||
if biome.plantlife_limit == nil then biome.plantlife_limit = 0.1 end
|
||||
if biome.near_nodes_vertical == nil then biome.near_nodes_vertical = 1 end
|
||||
|
||||
biome.spawn_plants_count = table.getn(biome.spawn_plants)
|
||||
|
||||
plantslib:dbg("Registered spawning ABM:")
|
||||
plantslib:dbg(dump(biome))
|
||||
plantslib:dbg("Number of trigger nodes in this ABM: "..biome.spawn_plants_count )
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = { ssurface },
|
||||
interval = sdelay,
|
||||
chance = schance,
|
||||
neighbors = nneighbors,
|
||||
nodenames = biome.spawn_surfaces,
|
||||
interval = biome.spawn_delay,
|
||||
chance = biome.spawn_chance,
|
||||
neighbors = biome.neighbors,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
local p_top = { x = pos.x, y = pos.y + 1, z = pos.z }
|
||||
local n_top = minetest.env:get_node(p_top)
|
||||
local perlin1 = minetest.env:get_perlin(seed_diff, perlin_octaves, perlin_persistence, perlin_scale)
|
||||
local perlin1 = minetest.env:get_perlin(biome.seed_diff, perlin_octaves, perlin_persistence, perlin_scale)
|
||||
local perlin2 = minetest.env:get_perlin(temperature_seeddiff, temperature_octaves, temperature_persistence, temperature_scale)
|
||||
local noise1 = perlin1:get2d({x=p_top.x, y=p_top.z})
|
||||
local noise2 = perlin2:get2d({x=p_top.x, y=p_top.z})
|
||||
if noise1 > plantlife_limit
|
||||
and noise2 >= tempmin
|
||||
and noise2 <= tempmax
|
||||
if noise1 > biome.plantlife_limit
|
||||
and noise2 <= biome.temp_min
|
||||
and noise2 >= biome.temp_max
|
||||
and plantslib:is_node_loaded(p_top) then
|
||||
local n_light = minetest.env:get_node_light(p_top, nil)
|
||||
if minetest.env:find_node_near(p_top, sradius + math.random(-1.5,2), savoid) == nil
|
||||
and n_light >= lightmin
|
||||
and n_light <= lightmax
|
||||
and (table.getn(minetest.env:find_nodes_in_area({x=pos.x-1, y=pos.y, z=pos.z-1}, {x=pos.x+1, y=pos.y, z=pos.z+1}, nneighbors)) > ocount
|
||||
or ocount == -1)
|
||||
and (table.getn(minetest.env:find_nodes_in_area({x=pos.x-sbiomesize, y=pos.y-1, z=pos.z-sbiomesize}, {x=pos.x+sbiomesize, y=pos.y+1, z=pos.z+sbiomesize}, sbiome)) >= sbiomecount
|
||||
or sbiome == "")
|
||||
and table.getn(minetest.env:find_nodes_in_area({x=p_top.x-airsize, y=p_top.y, z=p_top.z-airsize}, {x=p_top.x+airsize, y=p_top.y, z=p_top.z+airsize}, "air")) >= aircount
|
||||
and pos.y >= altmin
|
||||
and pos.y <= altmax
|
||||
then
|
||||
local walldir = plantslib:plant_valid_wall(p_top)
|
||||
if splant == "poisonivy:seedling" and walldir ~= nil then
|
||||
plantslib:dbg("Spawn: poisonivy:climbing at "..dump(p_top).." on "..ssurface)
|
||||
minetest.env:add_node(p_top, { name = "poisonivy:climbing", param2 = walldir })
|
||||
else
|
||||
local deepnode = minetest.env:get_node({ x = pos.x, y = pos.y-depthmax-1, z = pos.z }).name
|
||||
if (ssurface ~= "default:water_source")
|
||||
or (ssurface == "default:water_source"
|
||||
and deepnode ~= "default:water_source") then
|
||||
plantslib:dbg("Spawn: "..splant.." at "..dump(p_top).." on "..ssurface)
|
||||
minetest.env:add_node(p_top, { name = splant, param2 = facedir })
|
||||
if (not(biome.avoid_nodes and biome.avoid_radius) or minetest.env:find_node_near(p_top, biome.avoid_radius + math.random(-1.5,2), biome.avoid_nodes) == nil)
|
||||
and n_light >= biome.light_min
|
||||
and n_light <= biome.light_max
|
||||
and (not(biome.neighbors and biome.ncount) or table.getn(minetest.env:find_nodes_in_area({x=pos.x-1, y=pos.y, z=pos.z-1}, {x=pos.x+1, y=pos.y, z=pos.z+1}, biome.neighbors)) > biome.ncount )
|
||||
and (not(biome.near_nodes and biome.near_nodes_count and biome.near_nodes_size) or table.getn(minetest.env:find_nodes_in_area({x=pos.x-biome.near_nodes_size, y=pos.y-biome.near_nodes_vertical, z=pos.z-biome.near_nodes_size}, {x=pos.x+biome.near_nodes_size, y=pos.y+biome.near_nodes_vertical, z=pos.z+biome.near_nodes_size}, biome.near_nodes)) >= biome.near_nodes_count)
|
||||
and (not(biome.air_count and biome.air_size) or table.getn(minetest.env:find_nodes_in_area({x=p_top.x-biome.air_size, y=p_top.y, z=p_top.z-biome.air_size}, {x=p_top.x+biome.air_size, y=p_top.y, z=p_top.z+biome.air_size}, "air")) >= biome.air_count)
|
||||
and pos.y >= biome.min_elevation
|
||||
and pos.y <= biome.max_elevation
|
||||
then
|
||||
local walldir = plantslib:find_adjacent_wall(p_top, biome.verticals_list)
|
||||
if biome.alt_wallnode and walldir then
|
||||
if n_top.name == "air" then
|
||||
plantslib:dbg("Spawn: "..biome.alt_wallnode.." on top of ("..dump(pos)..") against wall "..walldir)
|
||||
minetest.env:add_node(p_top, { name = biome.alt_wallnode, param2 = walldir })
|
||||
end
|
||||
else
|
||||
local currentsurface = minetest.env:get_node(pos).name
|
||||
if currentsurface ~= "default:water_source"
|
||||
or (currentsurface == "default:water_source" and table.getn(minetest.env:find_nodes_in_area({x=pos.x, y=pos.y-biome.depth_max-1, z=pos.z}, {x=pos.x, y=pos.y, z=pos.z}, {"default:dirt", "default:dirt_with_grass", "default:sand"})) > 0 )
|
||||
then
|
||||
local rnd = math.random(1, biome.spawn_plants_count)
|
||||
local plant_to_spawn = biome.spawn_plants[rnd]
|
||||
plantslib:dbg("Chose entry number "..rnd.." of "..biome.spawn_plants_count)
|
||||
|
||||
if not biome.spawn_on_side and not biome.spawn_on_bottom then
|
||||
local fdir = nil
|
||||
if biome.random_facedir then
|
||||
fdir = math.random(biome.random_facedir[1],biome.random_facedir[2])
|
||||
plantslib:dbg("Gave it a random facedir: "..fdir)
|
||||
end
|
||||
if n_top.name == "air" then
|
||||
plantslib:dbg("Spawn: "..plant_to_spawn.." on top of ("..dump(pos)..")")
|
||||
minetest.env:add_node(p_top, { name = plant_to_spawn, param2 = fdir })
|
||||
end
|
||||
elseif biome.spawn_on_side then
|
||||
local onside = plantslib:find_open_side(pos)
|
||||
if onside then
|
||||
plantslib:dbg("Spawn: "..plant_to_spawn.." at side of ("..dump(pos).."), facedir "..onside.facedir.."")
|
||||
minetest.env:add_node(onside.newpos, { name = plant_to_spawn, param2 = onside.facedir })
|
||||
end
|
||||
elseif biome.spawn_on_bottom then
|
||||
if minetest.env:get_node({x=pos.x, y=pos.y-1, z=pos.z}).name == "air" then
|
||||
local fdir = nil
|
||||
if biome.random_facedir then
|
||||
fdir = math.random(biome.random_facedir[1],biome.random_facedir[2])
|
||||
plantslib:dbg("Gave it a random facedir: "..fdir)
|
||||
end
|
||||
plantslib:dbg("Spawn: "..plant_to_spawn.." on bottom of ("..dump(pos)..")")
|
||||
minetest.env:add_node({x=pos.x, y=pos.y-1, z=pos.z}, { name = plant_to_spawn, param2 = fdir} )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -213,134 +255,130 @@ end
|
||||
|
||||
-- The growing ABM
|
||||
|
||||
function plantslib:grow_plants(
|
||||
gdelay,
|
||||
gchance,
|
||||
gplant,
|
||||
gresult,
|
||||
dry_early_node,
|
||||
grow_nodes,
|
||||
facedir,
|
||||
need_wall,
|
||||
grow_vertically,
|
||||
height_limit,
|
||||
ground_nodes,
|
||||
grow_function,
|
||||
seed_diff)
|
||||
if need_wall ~= true then need_wall = false end
|
||||
if grow_vertically ~= true then grow_vertically = false end
|
||||
if height_limit == nil then height_limit = 62000 end
|
||||
if ground_nodes == nil then ground_nodes = { "default:dirt_with_grass" } end
|
||||
if grow_nodes == nil then grow_nodes = { "default:dirt_with_grass" } end
|
||||
function plantslib:grow_plants(opts)
|
||||
|
||||
local options = opts
|
||||
|
||||
if options.height_limit == nil then options.height_limit = 5 end
|
||||
if options.ground_nodes == nil then options.ground_nodes = { "default:dirt_with_grass" } end
|
||||
if options.grow_nodes == nil then options.grow_nodes = { "default:dirt_with_grass" } end
|
||||
if options.seed_diff == nil then options.seed_diff = 0 end
|
||||
|
||||
plantslib:dbg("Registered growing ABM:")
|
||||
plantslib:dbg(dump(options))
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = { gplant },
|
||||
interval = gdelay,
|
||||
chance = gchance,
|
||||
nodenames = { options.grow_plant },
|
||||
interval = options.grow_delay,
|
||||
chance = options.grow_chance,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
local p_top = {x=pos.x, y=pos.y+1, z=pos.z}
|
||||
local p_bot = {x=pos.x, y=pos.y-1, z=pos.z}
|
||||
local n_top = minetest.env:get_node(p_top)
|
||||
local n_bot = minetest.env:get_node(p_bot)
|
||||
local root_node = minetest.env:get_node({x=pos.x, y=pos.y-height_limit, z=pos.z})
|
||||
if string.find(dump(grow_nodes), n_bot.name) ~= nil and n_top.name == "air" then
|
||||
if grow_function == nil then
|
||||
if grow_vertically then
|
||||
if plantslib:find_first_node(pos, height_limit, ground_nodes) ~= nil then
|
||||
if need_wall then
|
||||
local walldir=plantslib:plant_valid_wall(p_top)
|
||||
if walldir ~= nil then
|
||||
plantslib:dbg("Grow: "..gplant.." upwards to ("..dump(p_top)..") on wall "..walldir)
|
||||
minetest.env:add_node(p_top, { name = gplant, param2 = walldir })
|
||||
end
|
||||
else
|
||||
plantslib:dbg("Grow: "..gplant.." upwards to ("..dump(p_top)..")")
|
||||
minetest.env:add_node(p_top, { name = gplant })
|
||||
end
|
||||
end
|
||||
local root_node = minetest.env:get_node({x=pos.x, y=pos.y-options.height_limit, z=pos.z})
|
||||
local walldir = nil
|
||||
if options.need_wall and options.verticals_list ~= nil then
|
||||
walldir = plantslib:find_adjacent_wall(p_top, options.verticals_list)
|
||||
end
|
||||
if n_top.name == "air" and (not options.need_wall or (options.need_wall and walldir))
|
||||
then
|
||||
-- corner case for changing short junglegrass
|
||||
-- to dry shrub in desert
|
||||
if n_bot.name == options.dry_early_node and options.grow_plant == "junglegrass:short" then
|
||||
plantslib:dbg("Die: "..options.grow_plant.." becomes default:dry_shrub at ("..dump(pos)..")")
|
||||
minetest.env:add_node(pos, { name = "default:dry_shrub" })
|
||||
|
||||
-- corner case for changing short junglegrass to dry shrub in desert
|
||||
elseif n_bot.name == dry_early_node and gplant == "junglegrass:short" then
|
||||
plantslib:dbg("Die: "..gplant.." becomes default:dry_shrub at ("..dump(pos)..")")
|
||||
minetest.env:add_node(pos, { name = "default:dry_shrub" })
|
||||
|
||||
elseif gresult == nil then
|
||||
plantslib:dbg("Die: "..gplant.." at ("..dump(pos)..")")
|
||||
minetest.env:remove_node(pos)
|
||||
|
||||
elseif gresult ~= nil then
|
||||
plantslib:dbg("Grow: "..gplant.." becomes "..gresult.." at ("..dump(pos)..")")
|
||||
if facedir == nil then
|
||||
minetest.env:add_node(pos, { name = gresult })
|
||||
else
|
||||
minetest.env:add_node(pos, { name = gresult, param2 = facedir })
|
||||
end
|
||||
elseif options.grow_vertically and walldir then
|
||||
if plantslib:search_downward(pos, options.height_limit, options.ground_nodes) then
|
||||
plantslib:dbg("Grow "..options.grow_plant.." vertically to "..dump(p_top))
|
||||
minetest.env:add_node(p_top, { name = options.grow_plant, param2 = walldir})
|
||||
end
|
||||
|
||||
elseif options.grow_result == nil and options.grow_function == nil then
|
||||
plantslib:dbg("Die: "..options.grow_plant.." at ("..dump(pos)..")")
|
||||
minetest.env:remove_node(pos)
|
||||
|
||||
else
|
||||
if seed_diff == nil then seed_diff = 0 end
|
||||
local perlin1 = minetest.env:get_perlin(seed_diff, perlin_octaves, perlin_persistence, perlin_scale)
|
||||
local perlin2 = minetest.env:get_perlin(temperature_seeddiff, temperature_octaves, temperature_persistence, temperature_scale)
|
||||
local noise1 = perlin1:get2d({x=p_top.x, y=p_top.z})
|
||||
local noise2 = perlin2:get2d({x=p_top.x, y=p_top.z})
|
||||
if type(grow_function) == "table" then
|
||||
plantslib:dbg("Grow sapling into tree at "..dump(pos))
|
||||
minetest.env:remove_node(pos)
|
||||
minetest.env:spawn_tree(pos, grow_function)
|
||||
else
|
||||
plantslib:dbg("Call function: "..grow_function.."("..dump(pos)..","..noise1..","..noise2..")")
|
||||
assert(loadstring(grow_function.."("..dump(pos)..","..noise1..","..noise2..")"))()
|
||||
end
|
||||
plantslib:replace_object(pos, options.grow_result, options.grow_function, options.facedir, options.seed_diff)
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
-- Function to decide how to replace a plant - either grow it, replace it with
|
||||
-- a tree, run a function, or die with an error.
|
||||
|
||||
function plantslib:replace_object(pos, replacement, grow_function, walldir, seeddiff)
|
||||
local growtype = type(grow_function)
|
||||
plantslib:dbg("replace_object called, growtype="..dump(grow_function))
|
||||
if growtype == "table" then
|
||||
plantslib:dbg("Grow: spawn tree at "..dump(pos))
|
||||
minetest.env:remove_node(pos)
|
||||
minetest.env:spawn_tree(pos, grow_function)
|
||||
return
|
||||
elseif growtype == "string" then
|
||||
local perlin1 = minetest.env:get_perlin(seeddiff, perlin_octaves, perlin_persistence, perlin_scale)
|
||||
local perlin2 = minetest.env:get_perlin(temperature_seeddiff, temperature_octaves, temperature_persistence, temperature_scale)
|
||||
local noise1 = perlin1:get2d({x=pos.x, y=pos.z})
|
||||
local noise2 = perlin2:get2d({x=pos.x, y=pos.z})
|
||||
plantslib:dbg("Grow: call function "..grow_function.."("..dump(pos)..","..noise1..","..noise2..","..dump(walldir)..")")
|
||||
assert(loadstring(grow_function.."("..dump(pos)..","..noise1..","..noise2..","..dump(walldir)..")"))()
|
||||
return
|
||||
elseif growtype == "nil" then
|
||||
if walldir ~= nil then
|
||||
plantslib:dbg("Grow: place "..replacement.." at ("..dump(pos)..") on wall "..walldir)
|
||||
minetest.env:add_node(pos, { name = replacement, param2 = walldir})
|
||||
else
|
||||
plantslib:dbg("Grow: place "..replacement.." at ("..dump(pos)..")")
|
||||
minetest.env:add_node(pos, { name = replacement})
|
||||
end
|
||||
return
|
||||
elseif growtype ~= "nil" and growtype ~= "string" and growtype ~= "table" then
|
||||
error("Invalid grow function "..dump(grow_function).." used on object at ("..dump(pos)..")")
|
||||
end
|
||||
end
|
||||
|
||||
-- function to decide if a node has a wall that's in verticals_list{}
|
||||
-- returns wall direction of valid node, or nil if invalid.
|
||||
|
||||
local verticals_list = {
|
||||
"default:dirt",
|
||||
"default:dirt_with_grass",
|
||||
"default:stone",
|
||||
"default:cobble",
|
||||
"default:mossycobble",
|
||||
"default:brick",
|
||||
"default:tree",
|
||||
"default:jungletree",
|
||||
"default:coal",
|
||||
"default:iron"
|
||||
}
|
||||
|
||||
function plantslib:plant_valid_wall(wallpos)
|
||||
local walldir = nil
|
||||
local verts = dump(verticals_list)
|
||||
|
||||
local testpos = { x = wallpos.x-1, y = wallpos.y, z = wallpos.z }
|
||||
if string.find(verts, minetest.env:get_node(testpos).name) ~= nil then walldir=3 end
|
||||
|
||||
local testpos = { x = wallpos.x+1, y = wallpos.y, z = wallpos.z }
|
||||
if string.find(verts, minetest.env:get_node(testpos).name) ~= nil then walldir=2 end
|
||||
|
||||
local testpos = { x = wallpos.x , y = wallpos.y, z = wallpos.z-1 }
|
||||
if string.find(verts, minetest.env:get_node(testpos).name) ~= nil then walldir=5 end
|
||||
|
||||
local testpos = { x = wallpos.x , y = wallpos.y, z = wallpos.z+1 }
|
||||
if string.find(verts, minetest.env:get_node(testpos).name) ~= nil then walldir=4 end
|
||||
|
||||
return walldir
|
||||
function plantslib:find_adjacent_wall(pos, verticals)
|
||||
local verts = dump(verticals)
|
||||
if string.find(verts, minetest.env:get_node({ x=pos.x-1, y=pos.y, z=pos.z }).name) then return 3 end
|
||||
if string.find(verts, minetest.env:get_node({ x=pos.x+1, y=pos.y, z=pos.z }).name) then return 2 end
|
||||
if string.find(verts, minetest.env:get_node({ x=pos.x , y=pos.y, z=pos.z-1 }).name) then return 5 end
|
||||
if string.find(verts, minetest.env:get_node({ x=pos.x , y=pos.y, z=pos.z+1 }).name) then return 4 end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Function to search straight down from (pos) to find first node in match list.
|
||||
-- Function to search downward from the given position, looking for the first
|
||||
-- node that matches the ground table. Returns the new position, or nil if
|
||||
-- height limit is exceeded before finding it.
|
||||
|
||||
function plantslib:find_first_node(pos, height_limit, nodelist)
|
||||
for i = 1, height_limit do
|
||||
n = minetest.env:get_node({x=pos.x, y=pos.y-i, z=pos.z})
|
||||
if string.find(dump(nodelist),n.name) ~= nil then
|
||||
return n.name
|
||||
function plantslib:search_downward(pos, heightlimit, ground)
|
||||
for i = 0, heightlimit do
|
||||
if string.find(dump(ground), minetest.env:get_node({x=pos.x, y=pos.y-i, z = pos.z}).name) then
|
||||
return {x=pos.x, y=pos.y-i, z = pos.z}
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function plantslib:find_open_side(pos)
|
||||
if minetest.env:get_node({ x=pos.x-1, y=pos.y, z=pos.z }).name == "air" then
|
||||
return {newpos = { x=pos.x-1, y=pos.y, z=pos.z }, facedir = 2}
|
||||
end
|
||||
if minetest.env:get_node({ x=pos.x+1, y=pos.y, z=pos.z }).name == "air" then
|
||||
return {newpos = { x=pos.x+1, y=pos.y, z=pos.z }, facedir = 3}
|
||||
end
|
||||
if minetest.env:get_node({ x=pos.x, y=pos.y, z=pos.z-1 }).name == "air" then
|
||||
return {newpos = { x=pos.x, y=pos.y, z=pos.z-1 }, facedir = 4}
|
||||
end
|
||||
if minetest.env:get_node({ x=pos.x, y=pos.y, z=pos.z+1 }).name == "air" then
|
||||
return {newpos = { x=pos.x, y=pos.y, z=pos.z+1 }, facedir = 5}
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
print("[Plantlife] Loaded!")
|
||||
|
||||
print("[Plantlife Library] Loaded")
|
||||
|
@ -1,57 +0,0 @@
|
||||
-- This file supplies poison ivy for the plantlife modpack
|
||||
|
||||
local spawn_delay = 2000 -- 2000
|
||||
local spawn_chance = 100 -- 100
|
||||
local grow_delay = 1000 -- 1000
|
||||
local grow_chance = 10 -- 10
|
||||
local poisonivy_seed_diff = plantslib.plantlife_seed_diff + 10
|
||||
|
||||
minetest.register_node(':poisonivy:seedling', {
|
||||
description = "Poison ivy (seedling)",
|
||||
drawtype = 'plantlike',
|
||||
tile_images = { 'poisonivy_seedling.png' },
|
||||
inventory_image = 'poisonivy_seedling.png',
|
||||
wield_image = 'poisonivy_seedling.png',
|
||||
sunlight_propagates = true,
|
||||
paramtype = 'light',
|
||||
walkable = false,
|
||||
groups = { snappy = 3, poisonivy=1 },
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node(':poisonivy:sproutling', {
|
||||
description = "Poison ivy (sproutling)",
|
||||
drawtype = 'plantlike',
|
||||
tile_images = { 'poisonivy_sproutling.png' },
|
||||
inventory_image = 'poisonivy_sproutling.png',
|
||||
wield_image = 'poisonivy_sproutling.png',
|
||||
sunlight_propagates = true,
|
||||
paramtype = 'light',
|
||||
walkable = false,
|
||||
groups = { snappy = 3, poisonivy=1 },
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node(':poisonivy:climbing', {
|
||||
description = "Poison ivy (climbing plant)",
|
||||
drawtype = 'signlike',
|
||||
tile_images = { 'poisonivy_climbing.png' },
|
||||
inventory_image = 'poisonivy_climbing.png',
|
||||
wield_image = 'poisonivy_climbing.png',
|
||||
sunlight_propagates = true,
|
||||
paramtype = 'light',
|
||||
paramtype2 = 'wallmounted',
|
||||
walkable = false,
|
||||
groups = { snappy = 3, poisonivy=1 },
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
selection_box = {
|
||||
type = "wallmounted",
|
||||
--wall_side = = <default>
|
||||
},
|
||||
})
|
||||
|
||||
plantslib:spawn_on_surfaces(spawn_delay, "poisonivy:seedling", 10 , spawn_chance/10, "default:dirt_with_grass", {"group:poisonivy","group:flower"}, poisonivy_seed_diff, 7)
|
||||
|
||||
plantslib:grow_plants(spawn_delay, grow_chance, "poisonivy:seedling", "poisonivy:sproutling", nil, {"default:dirt_with_grass"})
|
||||
plantslib:grow_plants(spawn_delay, grow_chance*2, "poisonivy:climbing", nil, nil, nil ,nil,true,true,nil,{"default:dirt_with_grass"})
|
||||
|
96
poisonivy/init.lua
Normal file
@ -0,0 +1,96 @@
|
||||
-- This file supplies poison ivy for the plantlife modpack
|
||||
-- Last revision: 2013-01-24
|
||||
|
||||
local SPAWN_DELAY = 1000
|
||||
local SPAWN_CHANCE = 200
|
||||
local GROW_DELAY = 500
|
||||
local GROW_CHANCE = 30
|
||||
local poisonivy_seed_diff = 339
|
||||
local walls_list = {
|
||||
"default:dirt",
|
||||
"default:dirt_with_grass",
|
||||
"default:stone",
|
||||
"default:cobble",
|
||||
"default:mossycobble",
|
||||
"default:brick",
|
||||
"default:tree",
|
||||
"default:jungletree",
|
||||
"default:coal",
|
||||
"default:iron"
|
||||
},
|
||||
minetest.register_node('poisonivy:seedling', {
|
||||
description = "Poison ivy (seedling)",
|
||||
drawtype = 'plantlike',
|
||||
tile_images = { 'poisonivy_seedling.png' },
|
||||
inventory_image = 'poisonivy_seedling.png',
|
||||
wield_image = 'poisonivy_seedling.png',
|
||||
sunlight_propagates = true,
|
||||
paramtype = 'light',
|
||||
walkable = false,
|
||||
groups = { snappy = 3, poisonivy=1 },
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node('poisonivy:sproutling', {
|
||||
description = "Poison ivy (sproutling)",
|
||||
drawtype = 'plantlike',
|
||||
tile_images = { 'poisonivy_sproutling.png' },
|
||||
inventory_image = 'poisonivy_sproutling.png',
|
||||
wield_image = 'poisonivy_sproutling.png',
|
||||
sunlight_propagates = true,
|
||||
paramtype = 'light',
|
||||
walkable = false,
|
||||
groups = { snappy = 3, poisonivy=1 },
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node('poisonivy:climbing', {
|
||||
description = "Poison ivy (climbing plant)",
|
||||
drawtype = 'signlike',
|
||||
tile_images = { 'poisonivy_climbing.png' },
|
||||
inventory_image = 'poisonivy_climbing.png',
|
||||
wield_image = 'poisonivy_climbing.png',
|
||||
sunlight_propagates = true,
|
||||
paramtype = 'light',
|
||||
paramtype2 = 'wallmounted',
|
||||
walkable = false,
|
||||
groups = { snappy = 3, poisonivy=1 },
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
selection_box = {
|
||||
type = "wallmounted",
|
||||
--wall_side = = <default>
|
||||
},
|
||||
})
|
||||
|
||||
plantslib:spawn_on_surfaces({
|
||||
spawn_delay = SPAWN_DELAY,
|
||||
spawn_plants = {"poisonivy:seedling"},
|
||||
avoid_radius = 10,
|
||||
spawn_chance = SPAWN_CHANCE/10,
|
||||
spawn_surfaces = {"default:dirt_with_grass"},
|
||||
avoid_nodes = {"group:poisonivy","group:flower"},
|
||||
seed_diff = poisonivy_seed_diff,
|
||||
light_min = 7,
|
||||
alt_wallnode = "poisonivy:climbing",
|
||||
verticals_list = walls_list
|
||||
})
|
||||
|
||||
plantslib:grow_plants({
|
||||
grow_delay = SPAWN_DELAY,
|
||||
grow_chance = GROW_CHANCE,
|
||||
grow_plant = "poisonivy:seedling",
|
||||
grow_result = "poisonivy:sproutling",
|
||||
grow_nodes = {"default:dirt_with_grass"}
|
||||
})
|
||||
|
||||
plantslib:grow_plants({
|
||||
grow_delay = GROW_DELAY,
|
||||
grow_chance = GROW_CHANCE*2,
|
||||
grow_plant = "poisonivy:climbing",
|
||||
need_wall = true,
|
||||
grow_vertically = true,
|
||||
verticals_list = walls_list,
|
||||
ground_nodes = {"default:dirt_with_grass"}
|
||||
})
|
||||
|
||||
print("[Poison Ivy] Loaded.")
|
Before Width: | Height: | Size: 456 B After Width: | Height: | Size: 456 B |
Before Width: | Height: | Size: 270 B After Width: | Height: | Size: 270 B |
Before Width: | Height: | Size: 426 B After Width: | Height: | Size: 426 B |