Compare commits

...

26 Commits

Author SHA1 Message Date
trans_soup 3fa17f8b68 make decomposition require dirty nodes nearby.
decomposition will no longer happen unless the decomposing leaves are
touching a dirty node. thus, they can now be used for decoration in
non-dirty locations.
2023-10-19 17:14:39 +02:00
trans_soup 845e951d8d fix decomposing leaves construction.
decomposing leaves will now check if they can stack after being
constructed, fixing an error where there would be decomposing leaves
floating over other decomposing leaves.
2023-10-19 17:11:18 +02:00
trans_soup ecd04f8105 balance: tweak decomposition rate bonuses.
decomposing leaves now provide a smaller bonus, and dirty nodes now
provide a larger bonus, than before.
2023-10-19 17:08:08 +02:00
trans_soup 37d192798e fix: decomposing leaves now check for falling.
leaves now call `minetest.check_for_falling` at their position when
decomposing into air. this fixes an error where falling nodes would be
left floating above decomposing leaves once said leaves disappeared.
2023-10-19 17:05:49 +02:00
trans_soup 123d3329cd increase decomposition temporal resolution.
make decomposition ABM:s happen more often. also decrease their chance
of happening, so that the overall balance isn't affected.
2023-10-19 16:51:14 +02:00
trans_soup e42407978d add time control for decomposition.
add chat command that changes the rate at which decomposition happens.
2023-10-19 16:49:36 +02:00
trans_soup 400c27c021 tweak decomposition.
leaves will now start decomposing faster if touching certain nodes.
they'll also take longer overall to start decomposing.
2023-10-19 16:18:24 +02:00
trans_soup ae26cfad42 refactor: make decomposition use new API function.
make leaves decomposition use the `blockgame.score_nearby_nodes` API
function (which was created largely from previous decomposition code).
2023-10-19 16:10:23 +02:00
trans_soup a3537b5dda add `blockgame.score_nearby_nodes` utility to API.
expose public function that walks through nodes near a given position,
counting up a score based on their groups.
2023-10-19 16:08:25 +02:00
trans_soup 292358a3db balance: make decomposition more expensive.
decomposing leaves are now less likely to turn into dirt.
2023-10-19 16:00:43 +02:00
trans_soup 737afdfcc9 make leaves get a random level when they start decomposing. 2023-10-19 15:59:11 +02:00
trans_soup 7493d9771c balance: make it take longer for leaves to start decomposing. 2023-10-19 15:56:37 +02:00
trans_soup 87a88a88a6 fix sapling growth replacing certain nodes.
saplings can now replace alive leaves when growing (and other nodes can
easily be added in the future).

previously, instead of saplings, it was accidentally the case that
alive leaves growth worked like this when growing out of sapling,
instead of actual sapling growth.
2023-10-19 15:52:01 +02:00
trans_soup 717cbf91e2 fix leaves growth error.
make growing leaves turn into alive leaves if they should do so.
previously, this didn't happen for leaves that exceeded their max
distance from supporting node.
2023-10-19 15:39:04 +02:00
trans_soup 584187957a balance: tweak decomposition rate.
make leaves decompose bonuses from nearby nodes less powerful, and
increase decomposition cost.
2023-10-19 15:32:24 +02:00
trans_soup c3bff227aa growing saplings can now replace living leaves. 2023-10-19 15:28:26 +02:00
trans_soup 3316dcba15 improve `blockgame.attempt_place` utility.
it now takes an optional argument that specifies what nodes may be
replaced (besides air).
2023-10-19 15:27:38 +02:00
trans_soup 477afad09e balance: tweak sapling growth rate. 2023-10-19 15:23:42 +02:00
trans_soup 1282fda837 make leaves growth use an increasing ABM.
this also means that leaves now grow slower.
2023-10-19 15:23:07 +02:00
trans_soup 0dffde9363 balance: make base decomposition rate slower.
(negligible when the decomposing leaves are touching several nodes that
make them decompose faster.)
2023-10-19 15:17:05 +02:00
trans_soup f134082112 make nuts drop from leaves less often. 2023-10-19 15:14:02 +02:00
trans_soup bdfb9f5fda make leaves only grow sideways.
previously, living leaves grew into more living leaves in all 6
directions. now, they only grow in the 4 horizontal directions.
2023-10-19 15:12:36 +02:00
trans_soup 19e392d1f3 make leaves grow at new sapling position.
make leaves grow out of the new (upper) sapling position instead of the
old (lower) position when saplings grow.
2023-10-19 15:09:53 +02:00
trans_soup 68e005814f refactor sapling support checking.
saplings now only check for groups, not specific nodes, when determining
whether they are supported. the previously checked nodes are now in the
new group that's being checked.
2023-10-19 15:08:53 +02:00
trans_soup dd796c549e make unsupported roots die.
make `root_alive` nodes turn into `root` nodes if they're not touching
any of these nodes: `root_alive`, `log_alive`, `sapling`.
2023-10-19 14:53:15 +02:00
trans_soup 9e43abb69a make living roots drop dead roots. 2023-10-19 14:45:24 +02:00
11 changed files with 176 additions and 62 deletions

View File

@ -24,4 +24,6 @@ load_file("increasing_abm")
load_file("loose_node")
load_file("fall_fix")
load_file("privs")
load_file("cleanup")

3
mods/bg_api/privs.lua Normal file
View File

@ -0,0 +1,3 @@
local modname = minetest.get_current_modname()
minetest.register_privilege("control_time", "control the speed at which certain blockgame processes happen.")

View File

@ -8,10 +8,18 @@ end
function blockgame.attempt_place (pos, node)
if minetest.get_node(pos).name ~= "air" then return false end
minetest.set_node(pos, node)
return true
function blockgame.attempt_place (pos, node, replacable)
local replacable = replacable or {}
local node_name = minetest.get_node(pos).name
local can_place = false
if node_name == "air" then can_place = true end
if blockgame.item_matches(node_name, replacable) then can_place = true end
if can_place then
minetest.set_node(pos, node)
end
return can_place
end
@ -74,3 +82,38 @@ function blockgame.flood_fill (start, step, max_range)
return matches, rejected
end
function blockgame.score_nearby_nodes (pos, max_distance, group_scores, score_fn)
local score = 0
local source_pos = pos
blockgame.flood_fill(pos, function (pos, distance)
if pos == source_pos then return true end
local name = minetest.get_node(pos).name
local gain = 0
-- TODO: add support for individual nodes and not just groups.
for group, value in pairs(group_scores) do
local group = minetest.get_item_group(name, group)
if group > 0 then
gain = math.max(gain, value * group)
end
end
gain = score_fn(gain, distance, name, pos)
-- TODO: add support for optionally counting negative scores.
if gain > 0 then
score = score + gain
return true
end
-- TODO: add support for optionally going through non-scored nodes.
return false
end, max_distance)
return score
end

View File

@ -1,13 +1,45 @@
local modname = minetest.get_current_modname()
local api = blockgame.tree
local vec = blockgame.vector
-- NODE NAMES
local leaves = modname .. ":leaves"
local leaves_decomposing = modname .. ":leaves_decomposing"
-- END OF NODE NAMES
local decompose_time_speed = 1
-- TODO: add setting for this as well.
minetest.register_chatcommand(modname .. ":set_decompose_time_speed", {
params = "<value>",
description = "set the speed at which decomposition happens.",
privs = {
control_time = true,
},
func = function (player_name, speed)
speed = tonumber(speed)
if speed == nil then
minetest.chat_send_player(player_name, "time speed must be a number.")
return
end
if speed < 0 or speed > 256 then
minetest.chat_send_player(player_name, "time speed must be between 0 and 256 (inclusive).")
return
end
decompose_time_speed = speed
minetest.chat_send_all(player_name .. " set the leaves decomposition time speed to " .. speed .. ".")
end,
})
local decompose_scores = {
dirty = 100,
leaves_decomposing = 20,
}
local start_decompose_cost = 4000
blockgame.register_increasing_abm({
id = modname .. ":begin_decompose",
@ -15,60 +47,44 @@ blockgame.register_increasing_abm({
nodenames = {leaves},
neighbors = {"group:dirty", leaves_decomposing},
interval = 15,
chance = 4,
chance = 8,
rate = function (pos, node, data)
return data.value + math.random(4, 6)
local score = blockgame.score_nearby_nodes(pos, 2, decompose_scores, function (gain, distance)
return math.floor(gain / (distance ^ 3))
end)
return data.value + score * decompose_time_speed
end,
check = function (pos, node, data)
return data.value >= 20
return data.value >= start_decompose_cost
end,
action = function (pos, node, data)
minetest.set_node(pos, {name = leaves_decomposing})
-- NOTE: might wanna access the 4 from somewhere, instead of directly knowing it.
-- that way this won't have to change if decomposing leaves max levels change.
local level = math.random(1, 4)
minetest.set_node(pos, {name = leaves_decomposing .. "_" .. level})
end,
})
local decompose_scores = {
dirty = 50,
leaves_decomposing = 30,
}
local decompose_cost = 2000
local decompose_cost = 30000
local average_leaves_per_dirt = 4
blockgame.register_increasing_abm({
id = modname .. ":decompose",
label = "decompose leaves",
nodenames = {"group:leaves_decomposing"},
-- neighbors = {"group:dirty", "group:leaves_decomposing"},
interval = 30,
neighbors = {"group:dirty"},
interval = 15,
chance = 10,
rate = function (pos, node, data)
local score = 100
local score = 20
local source_pos = pos
blockgame.flood_fill(pos, function (pos, distance)
if pos == source_pos then return true end
local bonus = blockgame.score_nearby_nodes(pos, 4, decompose_scores, function (gain, distance)
return math.floor(gain / (distance ^ 3))
end)
local name = minetest.get_node(pos).name
local gain = 0
for group, value in pairs(decompose_scores) do
local group = minetest.get_item_group(name, group)
if group > 0 then
gain = math.max(gain, value * group)
end
end
gain = math.floor(gain / distance)
if gain > 0 then
score = score + gain
return true
end
return false
end, 4)
return data.value + score
score = score + bonus
return data.value + score * decompose_time_speed
end,
check = function (pos, node, data)
return data.value >= decompose_cost
@ -79,10 +95,11 @@ blockgame.register_increasing_abm({
local def = minetest.registered_nodes[node.name]
local dirt_chance = def.level_max - def.level + 1
if blockgame.chance(dirt_chance) then
if blockgame.chance(dirt_chance * average_leaves_per_dirt) then
minetest.set_node(pos, {name = "bg_terrain:dirt"})
else
minetest.remove_node(pos)
minetest.check_for_falling(pos)
end
end,
})

View File

@ -7,27 +7,40 @@ local leaves = modname .. ":leaves"
local leaves_growing = modname .. ":leaves_growing"
local leaves_alive = modname .. ":leaves_alive"
-- END OF NODE NAMES
local max_grow_distance = 2
local leaves_grow_cost = 250
-- TODO: turn this into an increasing ABM.
blockgame.register_abm({
blockgame.register_increasing_abm({
id = modname .. ":grow_leaves",
label = "grow leaves",
nodenames = {leaves_growing},
neighbors = {log_alive, leaves_growing, leaves_alive},
interval = 15,
chance = 8,
action = function (pos, node)
rate = function (pos, node, data)
-- TODO: account for nearby nodes? e.g. grow slower if there are more leaves nearby.
return data.value + math.random(1, 99)
end,
check = function (pos, node, data)
return data.value >= leaves_grow_cost
end,
action = function (pos, node, data)
-- TODO: give leaves energy over time, that they spend when creating new leaves.
-- this requires the API to add support for increasing ABM `action`:s to modify `data`.
local meta = minetest.get_meta(pos)
local distance = meta:get_int("leaf_distance") or 1
if distance >= max_grow_distance then return end
if distance >= max_grow_distance then
minetest.set_node(pos, {name = leaves_alive})
return
end
local neighbors = blockgame.vector.get_neighbors(pos)
for _, target in pairs(neighbors) do
local sides = blockgame.vector.get_sides_of(pos)
for _, target in pairs(sides) do
if blockgame.chance(2) then
blockgame.attempt_place(target, {name = leaves_growing})
-- TODO: find lowest possible leaf distance by checking all 4 sides?
minetest.get_meta(target):set_int("leaf_distance", distance + 1)
end
end

View File

@ -0,0 +1,23 @@
local modname = minetest.get_current_modname()
local root_alive = modname .. ":root_alive"
blockgame.register_abm({
label = "kill roots",
nodenames = {root_alive},
interval = 20,
chance = 1,
action = function (pos, node)
local can_live = blockgame.any(blockgame.vector.get_neighbors(pos), function (pos)
return blockgame.item_matches(minetest.get_node(pos).name, {
root_alive,
modname .. ":log_alive",
modname .. ":sapling",
})
end)
if can_live then return end
minetest.set_node(pos, {name = modname .. ":root"})
end,
})

View File

@ -9,8 +9,10 @@ local leaves_growing = modname .. ":leaves_growing"
local function supports_sapling (name)
if name == log_alive or name == root_alive then return true end
return minetest.get_item_group(name, "dirty") > 0
return blockgame.item_matches(name, {
"group:supports_sapling",
"group:dirty",
})
end
-- this commented-out function will be used when roots start affecting tree growth.
@ -35,26 +37,32 @@ local function find_first_root (pos, max_height = 8)
end
]]--
local sapling_grow_cost = 2000
local sapling_can_replace = {
modname .. ":leaves_alive",
}
blockgame.register_increasing_abm({
id = modname .. ":grow_sapling",
label = "grow sapling",
nodenames = {sapling},
neighbors = {"group:dirty", log_alive},
neighbors = {"group:supports_sapling", "group:dirty"},
interval = 15,
chance = 4,
rate = function (pos, node, data)
-- TODO: find connected living logs and leaves, and nearby light levels, and soil richness near roots, to calculate growth rate.
return data.value + math.random(1, 99)
return data.value + math.random(1, 100) * math.random(1, 5)
end,
check = function (pos, node, data)
if data.value < 200 then return false end
if data.value < sapling_grow_cost then return false end
local below = pos + blockgame.vector.dirs.down
local below_name = minetest.get_node(below).name
if not supports_sapling(below_name) then return false end
local above = pos + blockgame.vector.dirs.up
if minetest.get_node(above).name ~= "air" then return false end
local above_name = minetest.get_node(above).name
if above_name ~= "air" and not blockgame.item_matches(above_name, sapling_can_replace) then return false end
return true
end,
@ -81,7 +89,7 @@ blockgame.register_increasing_abm({
end
-- grow out leaves to the sides.
local sides = blockgame.vector.get_sides_of(pos)
local sides = blockgame.vector.get_sides_of(above)
for _, side in pairs(sides) do
blockgame.attempt_place(side, {name = leaves_growing})
end

View File

@ -5,6 +5,7 @@ load_file("decoration")
load_file("grow_sapling")
load_file("grow_leaves")
load_file("grow_root")
load_file("fall_leaves")
load_file("decompose")

View File

@ -19,5 +19,7 @@ blockgame.register_node("root_alive", {
description = "Growing Root",
groups = {
woody = 1,
supports_sapling = 1,
},
drop = modname .. ":root",
})

View File

@ -28,12 +28,12 @@ local nutty_drops = {
max_items = 3,
items = {
{
rarity = 8,
items = {modname .. ":nut"},
rarity = 20,
items = {modname .. ":nut 2"},
},
{
rarity = 12,
items = {modname .. ":nut 2"},
rarity = 16,
items = {modname .. ":nut"},
},
{
rarity = 1,
@ -112,6 +112,7 @@ local function reg_decomposing (level)
texture = "leaves_decomposing",
drawtype = drawtype,
node_box = node_box,
on_construct = after_place_stack,
after_place_node = after_place_stack,
after_land = after_place_stack,
drop = modname .. ":leaves_decomposing_1 " .. level,

View File

@ -28,6 +28,7 @@ reg_log("log", {
reg_log("log_alive", {
groups = {
planty = 1,
supports_sapling = 1,
},
texture = "log",
drop = modname .. ":log",