blockgame/mods/bg_tree/grow.lua
2023-10-16 19:18:29 +02:00

96 lines
2.4 KiB
Lua

local modname = minetest.get_current_modname()
local api = blockgame.tree
local vec = blockgame.vector
-- NODE NAMES
local log = modname .. ":log"
local log_alive = modname .. ":log_alive"
local leaves = modname .. ":leaves"
local leaves_alive = modname .. ":leaves_alive"
local root = modname .. ":root"
-- END OF NODE NAMES
-- LOCALS CACHE
local all_sides_except_up = blockgame.shallow_copy_table(blockgame.vector.dirs)
all_sides_except_up.up = nil
-- END OF LOCALS CACHE
local function extend_leaves_from (pos)
local side = vec.random_side()
blockgame.attempt_place(pos + side, {name = leaves_alive})
end
local function spread_roots_from (source)
local root_pos = blockgame.random_walk({
pos = source,
check = function (pos)
local name = minetest.get_node(pos).name
if name == log_alive then return true end
if name == root then return true end
return false
end,
neighborhood = all_sides_except_up,
})
if not root_pos then return false end
local root_node = minetest.get_node(root_pos)
if minetest.get_node(root_pos + blockgame.vector.dirs.up).name == log_alive then
minetest.set_node(root_pos, {name = root})
return true
end
local side = blockgame.random_element(all_sides_except_up)
local target_pos = root_pos + side
if blockgame.chance(2) then target_pos = vec.get_below(root_pos) end
if minetest.get_item_group(minetest.get_node(target_pos), "dirty") then
return minetest.set_node(target_pos, {name = root})
end
return false
end
blockgame.register_abm({
label = "sapling grow",
nodenames = {"bg_tree:sapling"},
neighbors = {"group:dirty", log_alive},
interval = 15,
chance = 4,
action = function (pos, node, active_object_count, active_object_count_wider)
local below = vec.get_below(pos)
if blockgame.chance(4) then
local root_source = api.find_bottom_log(pos, 8)
if root_source ~= nil then
spread_roots_from(root_source + blockgame.vector.dirs.down)
end
end
if blockgame.chance(2) then
extend_leaves_from(pos)
end
if blockgame.chance(2) then
local side = vec.random_side()
local target = pos + side
blockgame.attempt_place(target, {name = log_alive})
end
if blockgame.chance(4) then
minetest.set_node(pos, {name = log_alive})
if minetest.get_node(below).name == log_alive and blockgame.chance(4) then return end
blockgame.attempt_place(pos + vector.new(0, 1, 0), {name = modname .. ":sapling"})
end
end,
})