From 932485a6fecbdcca9f13782a6e1bfccbc7d142d1 Mon Sep 17 00:00:00 2001 From: Jordan Leppert Date: Fri, 24 Dec 2021 08:30:36 +0000 Subject: [PATCH] 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. --- API.txt | 33 +++++++++++++++++++++------------ api.lua | 12 +++++++++--- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/API.txt b/API.txt index b2bd94d..61c4532 100644 --- a/API.txt +++ b/API.txt @@ -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 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, or you can pass a single biome definition as a table, with all of your options spelled out nicely. This is the preferred method. @@ -135,7 +135,7 @@ biome = { -- 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 + -- (near_nodes_size^2)*near_nodes_vertical*2 -- 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 @@ -202,7 +202,7 @@ biome = { } [*] 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 parameter to avoid making too many calls to this function, the lower the CPU 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 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 sense at map-generation time. @@ -250,12 +250,21 @@ biome = { -- skipped. Avoid using excessively large radii. rarity = num, -- How rare should this object be in its biome? Larger -- 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 -- should be allowed to spawn in a 5x5x5 mapblock area -- (80x80x80 nodes). Defaults to 5, but be sure you -- set this to some reasonable value depending on your -- 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 -- causes the function to inherit the global value of -- 329. @@ -341,7 +350,7 @@ definition table as the only parameter. These are defined like so: options = { 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 -- 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 @@ -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 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 in the following general form: +few parmeters in the following general form: 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. 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. ===== @@ -463,7 +472,7 @@ spammy stuff. biome_lib.generate_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 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, @@ -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 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 sapling into a tree. @@ -518,7 +527,7 @@ appears to be the standard now. Those values are: temperature_persistence = 0.5 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 *colder* temperatures. In this mod, the following table gives a rough 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 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. diff --git a/api.lua b/api.lua index b75beb1..352b56b 100644 --- a/api.lua +++ b/api.lua @@ -73,7 +73,9 @@ function biome_lib.set_defaults(biome) biome.near_nodes_size = biome.near_nodes_size or 0 biome.near_nodes_count = biome.near_nodes_count or 1 biome.rarity = biome.rarity or 50 + biome.rarity_fertility = biome.rarity_fertility or 0 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 -- specific to abm spawner @@ -182,14 +184,18 @@ end local function populate_single_surface(biome, pos, perlin_fertile_area, checkair) 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 end 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 - and fertility > biome.plantlife_limit + and fertility >= biome.plantlife_limit and temperature <= biome.temp_min and temperature >= biome.temp_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 local tries = 0 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 will_place = true