123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- -- © 2016, Rogier <rogier777@gmail.com>
- -- Translation support
- local S = minetest.get_translator("moretrees")
- -- Some constants
- local coconut_drop_ichance = 8
- -- Make the cocos palm fruit trunk a real trunk (it is generated as a fruit)
- local trunk = minetest.registered_nodes["moretrees:palm_trunk"]
- local ftrunk = {}
- local gftrunk = {}
- for k,v in pairs(trunk) do
- ftrunk[k] = v
- gftrunk[k] = v
- end
- ftrunk.tiles = {}
- gftrunk.tiles = {}
- for k,v in pairs(trunk.tiles) do
- ftrunk.tiles[k] = v
- gftrunk.tiles[k] = v
- end
- ftrunk.drop = "moretrees:palm_trunk"
- gftrunk.drop = "moretrees:palm_trunk"
- ftrunk.after_destruct = function(pos, oldnode)
- local coconuts = minetest.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},
- {"group:moretrees_coconut"}
- )
- for _,coconutpos in pairs(coconuts) do
- -- minetest.dig_node(coconutpos) does not cause nearby coconuts to be dropped :-( ...
- --minetest.dig_node(coconutpos)
- local items = minetest.get_node_drops(minetest.get_node(coconutpos).name)
- minetest.swap_node(coconutpos, biome_lib.air)
- for _, itemname in pairs(items) do
- minetest.add_item(coconutpos, itemname)
- end
- end
- end
- -- Make the different trunk types distinguishable (but barely)
- ftrunk.tiles[1] = "moretrees_palm_trunk_top.png^[transformR90"
- gftrunk.tiles[1] = "moretrees_palm_trunk_top.png^[transformR180"
- gftrunk.description = gftrunk.description.." (gen)"
- minetest.register_node("moretrees:palm_fruit_trunk", ftrunk)
- minetest.register_node("moretrees:palm_fruit_trunk_gen", gftrunk)
- local coconut_regrow_abm_spec = {
- nodenames = { "moretrees:palm_fruit_trunk" },
- interval = moretrees.coconut_flower_interval,
- chance = moretrees.coconut_flower_chance,
- action = function(pos, node, active_object_count, active_object_count_wider)
- local coconuts = minetest.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},
- "group:moretrees_coconut"
- )
- -- Expected growth interval increases exponentially with number of coconuts already hanging.
- -- Also: if more coconuts are hanging, the chance of picking an empty spot decreases as well...
- if math.random(2^#coconuts) <= 2 then
- -- Grow in area of 3x3 round trunk
- local dx=math.floor(math.random(3)-2)
- local dz=math.floor(math.random(3)-2)
- local coconutpos = {x=pos.x+dx, y=pos.y, z=pos.z+dz}
- local coconutnode = minetest.get_node(coconutpos)
- if coconutnode.name == "air" then
- minetest.swap_node(coconutpos, {name="moretrees:coconut_0"})
- end
- end
- end
- }
- if moretrees.coconuts_regrow then
- minetest.register_abm(coconut_regrow_abm_spec)
- end
- -- Spawn initial coconuts
- -- Spawn initial coconuts
- -- (Instead of coconuts, a generated-palm fruit trunk is generated with the tree. This
- -- ABM converts the trunk to a regular fruit trunk, and spawns some coconuts)
- minetest.register_abm({
- nodenames = { "moretrees:palm_fruit_trunk_gen" },
- interval = 1,
- chance = 1,
- action = function(pos, node, active_object_count, active_object_count_wider)
- minetest.swap_node(pos, {name="moretrees:palm_fruit_trunk"})
- local poslist = minetest.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},
- "air"
- )
- local genlist = {}
- for k,v in pairs(poslist) do
- genlist[k] = {x = math.random(100), pos = v}
- end
- table.sort(genlist, function(a, b) return a.x < b.x; end)
- local count = 0
- for _, gen in pairs(genlist) do
- minetest.swap_node(gen.pos, {name = "moretrees:coconut_3"})
- count = count + 1
- if count == 4 then
- break
- end
- end
- end,
- })
- -- Register coconuts, and make them regrow
- local coconut_growfn = function(pos, elapsed)
- local node = minetest.get_node(pos)
- local delay = moretrees.coconut_grow_interval
- if not node then
- return
- elseif not moretrees.coconuts_regrow then
- -- Regrowing has been turned off. Make coconust grow instantly
- minetest.swap_node(pos, {name="moretrees:coconut_3"})
- return
- elseif node.name == "moretrees:coconut_3" then
- -- Drop coconuts (i.e. remove them), so that new coconuts can grow.
- -- Coconuts will drop as items with a small chance
- if math.random(coconut_drop_ichance) == 1 then
- if moretrees.coconut_item_drop_ichance > 0
- and math.random(moretrees.coconut_item_drop_ichance) == 1 then
- local items = minetest.get_node_drops(minetest.get_node(pos).name)
- for _, itemname in pairs(items) do
- minetest.add_item(pos, itemname)
- end
- end
- minetest.swap_node(pos, biome_lib.air)
- end
- else
- -- Grow coconuts to the next stage
- local offset = string.len("moretrees:coconut_x")
- local n = string.sub(node.name, offset)
- minetest.swap_node(pos, {name=string.sub(node.name, 1, offset-1)..n+1})
- end
- -- Don't catch up when elapsed time is large. Regular visits are needed for growth...
- local timer = minetest.get_node_timer(pos)
- timer:start(delay + math.random(moretrees.coconut_grow_interval))
- end
- local coconut_starttimer = function(pos, elapsed)
- local timer = minetest.get_node_timer(pos)
- local base_interval = moretrees.coconut_grow_interval * 2 / 3
- timer:set(base_interval + math.random(base_interval), elapsed or 0)
- end
- for _,suffix in ipairs({"_0", "_1", "_2", "_3", ""}) do
- local name
- if suffix == "_0" then
- name = S("Coconut Flower")
- else
- name = S("Coconut")
- end
- local drop = ""
- local coco_group = 1
- local tile = "moretrees_coconut"..suffix..".png"
- local timerfn = coconut_growfn
- local constructfn = coconut_starttimer
- if suffix == "_3" then
- drop = "moretrees:coconut"
- tile = "moretrees_coconut.png"
- elseif suffix == "" then
- drop = nil
- coco_group = nil
- timerfn = nil
- constructfn = nil
- end
- local coconutdef = {
- description = name,
- tiles = {tile},
- drawtype = "plantlike",
- paramtype = "light",
- sunlight_propagates = true,
- walkable = false,
- groups = { fleshy=3, dig_immediate=3, flammable=2, moretrees_coconut=coco_group },
- inventory_image = tile.."^[transformR180",
- wield_image = tile.."^[transformR180",
- sounds = default.node_sound_defaults(),
- drop = drop,
- selection_box = {
- type = "fixed",
- fixed = {-0.3, -0.3, -0.3, 0.3, 0.3, 0.3}
- },
- on_timer = timerfn,
- on_construct = constructfn,
- }
- minetest.register_node("moretrees:coconut"..suffix, coconutdef)
- end
- -- convert exisiting cocos palms. This is a bit tricky...
- -- Try to make sure that this is indeed a generated tree, and not manually-placed trunks and/or coconuts
- if moretrees.coconuts_convert_existing_palms then
- local spec = {
- name = "moretrees:convert_existing_cocos_palms_to_regrow_coconuts",
- nodenames = "moretrees:coconut",
- action = function(pos, node, active_object_count, active_object_count_wider)
- local trunks
- local cvtrunks
- local leaves
- local coconuts
- -- One regular trunk must be adjacent to the coconut
- trunks = minetest.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},
- "moretrees:palm_trunk"
- )
- if #trunks ~= 1 then
- return
- end
- local tpos = trunks[1]
- -- 1 or 2 other trunks must be one level below to the trunk being converted.
- trunks = minetest.find_nodes_in_area(
- {x=tpos.x-1, y=tpos.y-1, z=tpos.z-1},
- {x=tpos.x+1, y=tpos.y-1, z=tpos.z+1},
- "moretrees:palm_trunk"
- )
- if #trunks < 1 or #trunks > 2 then
- return
- end
- -- 1 or 2 other trunks must be two levels below to the trunk being converted.
- trunks = minetest.find_nodes_in_area(
- {x=tpos.x-1, y=tpos.y-2, z=tpos.z-1},
- {x=tpos.x+1, y=tpos.y-2, z=tpos.z+1},
- "moretrees:palm_trunk"
- )
- if #trunks < 1 or #trunks > 2 then
- return
- end
- -- 1 or 2 trunks must at the level of the trunk being converted.
- cvtrunks = minetest.find_nodes_in_area(
- {x=tpos.x-1, y=tpos.y, z=tpos.z-1},
- {x=tpos.x+1, y=tpos.y, z=tpos.z+1},
- "moretrees:palm_trunk"
- )
- if #cvtrunks < 1 or #cvtrunks > 2 then
- return
- end
- -- No trunks may be one level above the trunk being converted.
- trunks = minetest.find_nodes_in_area(
- {x=tpos.x-1, y=tpos.y+1, z=tpos.z-1},
- {x=tpos.x+1, y=tpos.y+1, z=tpos.z+1},
- "moretrees:palm_trunk"
- )
- if #trunks ~= 0 then
- return
- end
- -- Leaves must be one level above the trunk being converted.
- leaves = minetest.find_nodes_in_area(
- {x=tpos.x-1, y=tpos.y+1, z=tpos.z-1},
- {x=tpos.x+1, y=tpos.y+1, z=tpos.z+1},
- "moretrees:palm_leaves"
- )
- if #leaves == 0 then
- return
- end
- -- Leaves must be two levels above the trunk being converted.
- leaves = minetest.find_nodes_in_area(
- {x=tpos.x-1, y=tpos.y+2, z=tpos.z-1},
- {x=tpos.x+1, y=tpos.y+2, z=tpos.z+1},
- "moretrees:palm_leaves"
- )
- if #leaves == 0 then
- return
- end
- -- No cocos fruit trunk may already be adjacent to the coconut
- trunks = minetest.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},
- "moretrees:palm_fruit_trunk"
- )
- if #trunks ~= 0 then
- return
- end
- -- No cocos fruit trunk may be adjacent to or below the trunk being converted.
- trunks = minetest.find_nodes_in_area(
- {x=tpos.x-1, y=tpos.y-2, z=tpos.z-1},
- {x=tpos.x+1, y=tpos.y, z=tpos.z+1},
- "moretrees:palm_fruit_trunk"
- )
- if #trunks ~= 0 then
- return
- end
- -- Convert trunk and all coconuts nearby. Maybe convert 2 trunks, just in case...
- for _, tpos_1 in pairs(cvtrunks) do
- minetest.swap_node(tpos_1, {name = "moretrees:palm_fruit_trunk"})
- coconuts = minetest.find_nodes_in_area(
- {x=tpos_1.x-1, y=tpos_1.y, z=tpos_1.z-1},
- {x=tpos_1.x+1, y=tpos_1.y, z=tpos_1.z+1},
- "moretrees:coconut"
- )
- for _, coconutpos in pairs(coconuts) do
- minetest.swap_node(coconutpos, {name = "moretrees:coconut_3"})
- end
- end
- end,
- }
- if minetest.register_lbm then
- minetest.register_lbm(spec)
- else
- spec.interval = 3691
- spec.chance = 10
- minetest.register_abm(spec)
- end
- end
- -- If regrowing was previously disabled, but is enabled now, make sure timers are started for existing coconuts
- if moretrees.coconuts_regrow then
- local spec = {
- name = "moretrees:restart_coconut_regrow_timer",
- nodenames = "group:moretrees_coconut",
- action = function(pos, node, active_object_count, active_object_count_wider)
- local timer = minetest.get_node_timer(pos)
- if not timer:is_started() then
- coconut_starttimer(pos)
- else
- local timeout = timer:get_timeout()
- local elapsed = timer:get_elapsed()
- if timeout - elapsed > moretrees.coconut_grow_interval * 4/3 then
- coconut_starttimer(pos, math.random(moretrees.coconut_grow_interval * 4/3))
- end
- end
- end,
- }
- if minetest.register_lbm then
- minetest.register_lbm(spec)
- else
- spec.interval = 3659
- spec.chance = 10
- minetest.register_abm(spec)
- end
- end
|