register_on_generate: tries and rarity_fertility (#8)

* Can specify the number of tries when generating
* Added rarity_fertility which means rarity can be affected by fertility level.
Rarity can now be a fraction.
A rarity of 100 (with rarity_fertility of 0) means the object will never appear, and a rarity of 0 means it will always appear.
This commit is contained in:
Jordan Leppert 2021-12-24 08:30:36 +00:00 committed by GitHub
parent bd92dc1b0b
commit 932485a6fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 15 deletions

33
API.txt
View File

@ -26,7 +26,7 @@ biome_lib.register_active_spawner(sdelay, splant, sradius, schance, ssurface, sa
This first function is an ABM-based spawner function originally created as This first function is an ABM-based spawner function originally created as
part of Ironzorg's flowers mod. It has since been largely extended and part of Ironzorg's flowers mod. It has since been largely extended and
expanded. There are two ways to call this function: You can either pass it expanded. There are two ways to call this function: You can either pass it
several individual string and number parameters to use the legacy interface, several individual string and number parameters to use the legacy interface,
or you can pass a single biome definition as a table, with all of your options or you can pass a single biome definition as a table, with all of your options
spelled out nicely. This is the preferred method. spelled out nicely. This is the preferred method.
@ -135,7 +135,7 @@ biome = {
-- radius. Defaults to 1 but is ignored if near_nodes -- radius. Defaults to 1 but is ignored if near_nodes
-- isn't set. Bear in mind that the total area to be -- isn't set. Bear in mind that the total area to be
-- checked is equal to: -- checked is equal to:
-- (near_nodes_size^2)*near_nodes_vertical*2 -- (near_nodes_size^2)*near_nodes_vertical*2
-- For example, if size is 10 and vertical is 4, then -- For example, if size is 10 and vertical is 4, then
-- the area is (10^2)*8 = 800 nodes in size, so you'll -- the area is (10^2)*8 = 800 nodes in size, so you'll
-- want to make sure you specify a value appropriate -- want to make sure you specify a value appropriate
@ -202,7 +202,7 @@ biome = {
} }
[*] spawn_plants must be either a table or a string. If it's a table, the [*] spawn_plants must be either a table or a string. If it's a table, the
values therein are treated as a list of nodenames to pick from randomly on values therein are treated as a list of nodenames to pick from randomly on
each application of the ABM code. The more nodes you can pack into this each application of the ABM code. The more nodes you can pack into this
parameter to avoid making too many calls to this function, the lower the CPU parameter to avoid making too many calls to this function, the lower the CPU
load will likely be. load will likely be.
@ -225,7 +225,7 @@ call this function with two parameters: a table with your object's biome
information, and a string, function, or table describing what to do if the information, and a string, function, or table describing what to do if the
engine finds a suitable surface node (see below). engine finds a suitable surface node (see below).
The biome table contains quite a number of options, though there are fewer The biome table contains quite a number of options, though there are fewer
here than are available in the ABM-based spawner, as some stuff doesn't make here than are available in the ABM-based spawner, as some stuff doesn't make
sense at map-generation time. sense at map-generation time.
@ -250,12 +250,21 @@ biome = {
-- skipped. Avoid using excessively large radii. -- skipped. Avoid using excessively large radii.
rarity = num, -- How rare should this object be in its biome? Larger rarity = num, -- How rare should this object be in its biome? Larger
-- values make objects more rare, via: -- values make objects more rare, via:
-- math.random(1,100) > this -- math.random() * 100 > this
rarity_fertility -- The amount that the rarity is reduced by fertility.
= num, -- This makes the rarity field the upper bound for
-- rarity, and (rarity - rarity_fertility) the lower
-- bound. Defaults to 0.
max_count = num, -- The absolute maximum number of your object that max_count = num, -- The absolute maximum number of your object that
-- should be allowed to spawn in a 5x5x5 mapblock area -- should be allowed to spawn in a 5x5x5 mapblock area
-- (80x80x80 nodes). Defaults to 5, but be sure you -- (80x80x80 nodes). Defaults to 5, but be sure you
-- set this to some reasonable value depending on your -- set this to some reasonable value depending on your
-- object and its size if 5 is insufficient. -- object and its size if 5 is insufficient.
tries = num, -- the number of attempts that will be made to spawn
-- an object, defaults to 2. This means if the first
-- attempt fails due to something blocking the object
-- for example, another attempt will be made in
-- another random location.
seed_diff = num, -- Perlin seed-diff value. Defaults to 0, which seed_diff = num, -- Perlin seed-diff value. Defaults to 0, which
-- causes the function to inherit the global value of -- causes the function to inherit the global value of
-- 329. -- 329.
@ -341,7 +350,7 @@ definition table as the only parameter. These are defined like so:
options = { options = {
label = string, -- set this to identify the ABM for Minetest's label = string, -- set this to identify the ABM for Minetest's
-- profiler. If not set, biome_lib will set it to -- profiler. If not set, biome_lib will set it to
-- "biome_lib.update_plant(): " appended with the node -- "biome_lib.update_plant(): " appended with the node
-- in grow_plant (or the first item if it's a table) -- in grow_plant (or the first item if it's a table)
grow_plant = "string" or {table}, -- Name(s) of the node(s) to be grown grow_plant = "string" or {table}, -- Name(s) of the node(s) to be grown
@ -406,7 +415,7 @@ 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 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 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 world, grow_result is ignored and the named function is executed and passed a
few parmeters in the following general form: few parmeters in the following general form:
somefunction(pos, perlin1, perlin2) somefunction(pos, perlin1, perlin2)
@ -431,7 +440,7 @@ 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. one it finds as a facedir value, or nil if there are no adjacent walls.
If randomflag is set to true, the function will just return the facedir of any If randomflag is set to true, the function will just return the facedir of any
random wall it finds adjacent to the target position. Defaults to false if random wall it finds adjacent to the target position. Defaults to false if
not specified. not specified.
===== =====
@ -463,7 +472,7 @@ spammy stuff.
biome_lib.generate_ltree(pos, treemodel) biome_lib.generate_ltree(pos, treemodel)
biome_lib.grow_ltree(pos, treemodel) biome_lib.grow_ltree(pos, treemodel)
In the case of the growing code and the mapgen-based tree generator code, In the case of the growing code and the mapgen-based tree generator code,
generating a tree is done via the above two calls, which in turn immediately generating a tree is done via the above two calls, which in turn immediately
call the usual spawn_tree() functions. This rerouting exists as a way for call the usual spawn_tree() functions. This rerouting exists as a way for
other mods to hook into biome_lib's tree-growing functions in general, other mods to hook into biome_lib's tree-growing functions in general,
@ -475,7 +484,7 @@ is to be placed. 'treemodel' is the standard L-Systems tree definition table
expected by the spawn_tree() function. Refer to the 'trunk' field in that expected by the spawn_tree() function. Refer to the 'trunk' field in that
table to derive the name of the tree being spawned. table to derive the name of the tree being spawned.
biome_lib.grow_ltree(pos, treemodel) does the same sort of thing whenever a biome_lib.grow_ltree(pos, treemodel) does the same sort of thing whenever a
tree is spawned within the abm-based growing code, for example when growing a tree is spawned within the abm-based growing code, for example when growing a
sapling into a tree. sapling into a tree.
@ -518,7 +527,7 @@ appears to be the standard now. Those values are:
temperature_persistence = 0.5 temperature_persistence = 0.5
temperature_scale = 150 temperature_scale = 150
The way Perlin values are used by this mod, in keeping with the snow mod's The way Perlin values are used by this mod, in keeping with the snow mod's
apparent methods, larger values returned by the Perlin function represent apparent methods, larger values returned by the Perlin function represent
*colder* temperatures. In this mod, the following table gives a rough *colder* temperatures. In this mod, the following table gives a rough
approximation of how temperature maps to these values, normalized to approximation of how temperature maps to these values, normalized to
@ -542,7 +551,7 @@ Perlin Approx. Temperature
Included in this table are even 0.25 steps in Perlin values along with some Included in this table are even 0.25 steps in Perlin values along with some
common temperatures on both the Centigrade and Fahrenheit scales. Note that common temperatures on both the Centigrade and Fahrenheit scales. Note that
unless you're trying to model the Moon or perhaps Mercury in your mods/maps, unless you're trying to model the Moon or perhaps Mercury in your mods/maps,
you probably won't need to bother with Perlin values of less than -0.56 or so. you probably won't need to bother with Perlin values of less than -0.56 or so.

12
api.lua
View File

@ -73,7 +73,9 @@ function biome_lib.set_defaults(biome)
biome.near_nodes_size = biome.near_nodes_size or 0 biome.near_nodes_size = biome.near_nodes_size or 0
biome.near_nodes_count = biome.near_nodes_count or 1 biome.near_nodes_count = biome.near_nodes_count or 1
biome.rarity = biome.rarity or 50 biome.rarity = biome.rarity or 50
biome.rarity_fertility = biome.rarity_fertility or 0
biome.max_count = biome.max_count or 125 biome.max_count = biome.max_count or 125
biome.tries = biome.tries or 2
if biome.check_air ~= false then biome.check_air = true end if biome.check_air ~= false then biome.check_air = true end
-- specific to abm spawner -- specific to abm spawner
@ -182,14 +184,18 @@ end
local function populate_single_surface(biome, pos, perlin_fertile_area, checkair) local function populate_single_surface(biome, pos, perlin_fertile_area, checkair)
local p_top = { x = pos.x, y = pos.y + 1, z = pos.z } local p_top = { x = pos.x, y = pos.y + 1, z = pos.z }
if math.random(1, 100) <= biome.rarity then if biome.rarity - biome.rarity_fertility == 100 then
return return
end end
local fertility, temperature, humidity = get_biome_data(pos, perlin_fertile_area) local fertility, temperature, humidity = get_biome_data(pos, perlin_fertile_area)
if math.random() * 100 <= (biome.rarity - ((fertility + 1) / 2 * biome.rarity_fertility)) then
return
end
local pos_biome_ok = pos.y >= biome.min_elevation and pos.y <= biome.max_elevation local pos_biome_ok = pos.y >= biome.min_elevation and pos.y <= biome.max_elevation
and fertility > biome.plantlife_limit and fertility >= biome.plantlife_limit
and temperature <= biome.temp_min and temperature >= biome.temp_max and temperature <= biome.temp_min and temperature >= biome.temp_max
and humidity <= biome.humidity_min and humidity >= biome.humidity_max and humidity <= biome.humidity_min and humidity >= biome.humidity_max
@ -286,7 +292,7 @@ function biome_lib.populate_surfaces(b, nodes_or_function_or_model, snodes, chec
for i = 1, math.min(math.ceil(biome.max_count/25), num_in_biome_nodes) do for i = 1, math.min(math.ceil(biome.max_count/25), num_in_biome_nodes) do
local tries = 0 local tries = 0
local spawned = false local spawned = false
while tries < 2 and not spawned do while tries < biome.tries and not spawned do
local pos = in_biome_nodes[math.random(1, num_in_biome_nodes)] local pos = in_biome_nodes[math.random(1, num_in_biome_nodes)]
local will_place = true local will_place = true