1 local S
= minetest
.get_translator("vines")
3 local mod_name
= "vines"
4 local average_height
= 12
5 local spawn_interval
= 90
9 -- Sideways vines are at the "side" of the node. They attach to the side of nodes
10 local vines_group_side
= {vines
=1,snappy
=3,flammable
=2}
11 -- Center vines are in the center of the node. They attach/"hang" from a solid node above
12 local vines_group_center
= {vines
=2,snappy
=3,flammable
=2}
13 local tt_surv
= S("Needs a tree trunk to survive")
18 -- Returns true if the node supports vines
19 local supports_vines
= function(nodename
)
20 local def
= minetest
.registered_nodes
[nodename
]
21 -- Rules: 1) walkable 2) full cube OR it's a tree node
22 return minetest
.get_item_group(nodename
, "tree") ~= 0 or (def
.walkable
and
23 (def
.node_box
== nil or def
.node_box
.type == "regular") and
24 (def
.collision_box
== nil or def
.collision_box
.type == "regular"))
27 --[[ Call this for vines nodes only.
28 Given the pos and node of a vines node, this returns true if the vines are
29 supported and false if the vines are currently floating.
30 Vines are considered “supported” if they face a walkable+solid block or
31 “hang” from a vines node above. ]]
32 local check_vines_supported
= function(pos
, node
)
33 local supported
= false
34 local dir
= minetest
.wallmounted_to_dir(node
.param2
)
35 local pos1
= vector
.add(pos
, dir
)
36 local node_neighbor
= minetest
.get_node(pos1
)
37 local pos2
= vector
.add(pos
, {x
=0, y
=1, z
=0})
38 local node2
= minetest
.get_node(pos2
)
39 local vg
= minetest
.get_item_group(node
.name
, "vines")
40 local vg2
= minetest
.get_item_group(node2
.name
, "vines")
41 -- Check if vines are attached to a solid block.
42 -- If ignore, we assume its solid.
43 if (vg
== 1) and (node_neighbor
.name
== "ignore" or supports_vines(node_neighbor
.name
)) then
45 elseif (vg
== 1) and (dir
.y
== 0) then
46 -- Vines are not attached, now we check if the vines are “hanging” below another vines block
47 -- of equal orientation.
48 -- Again, ignore means we assume its supported
49 if node2
.name
== "ignore" or (vg2
== vg
and node2
.param2
== node
.param2
) then
52 elseif (vg
== 2 and supports_vines(node2
.name
)) then
58 local function get_on_place(centered
)
59 -- Restrict placement of vines
60 return function(itemstack
, placer
, pointed_thing
)
61 if pointed_thing
.type ~= "node" then
62 -- no interaction possible with entities
66 local under
= pointed_thing
.under
67 local above
= pointed_thing
.above
68 local node
= minetest
.get_node(under
)
69 local def
= minetest
.registered_nodes
[node
.name
]
73 local groups
= def
.groups
75 -- Check special rightclick action of pointed node
76 if def
and def
.on_rightclick
then
77 if not placer
:get_player_control().sneak
then
78 return def
.on_rightclick(under
, node
, placer
, itemstack
,
79 pointed_thing
) or itemstack
, false
85 cnode
= minetest
.get_node({x
=above
.x
, y
=above
.y
+1, z
=above
.z
})
87 -- Sideways vines may not be placed on top or below another block
88 if under
.y
~= above
.y
then
93 -- Only place on full cubes
94 if not supports_vines(cnode
.name
) then
95 -- But centered vines can be placed below centered vines
96 if not (centered
and minetest
.get_item_group(cnode
.name
, "vines") == 2) then
101 local idef
= itemstack
:get_definition()
102 local itemstack
, success
= minetest
.item_place_node(itemstack
, placer
, pointed_thing
)
105 if idef
.sounds
and idef
.sounds
.place
then
106 minetest
.sound_play(idef
.sounds
.place
, {pos
=above
, gain
=1}, true)
113 -- Get vines when using shears
114 local after_dig_node
= function(pos
, oldnode
, oldmetadata
, user
)
116 if not user
or not user
:is_player() then
119 if user
:get_wielded_item() ~= nil then
120 wielded
= user
:get_wielded_item()
124 if minetest
.get_item_group(wielded
:get_name(), "shears") ~= 0 then
126 local inv
= user
:get_inventory()
127 local newstack
= ItemStack(oldnode
.name
)
130 elseif minetest
.is_creative_enabled(user
:get_player_name()) then
131 if inv
:contains_item("main", newstack
) then
136 inv
:add_item("main", newstack
)
141 -- If vine dug, also dig a “dependant” vine below it.
142 -- A vine is dependant if it hangs from this node and has no supporting block.
143 local on_dig
= function(pos
, node
, digger
)
144 local below
= {x
=pos
.x
, y
=pos
.y
-1, z
=pos
.z
}
145 local belownode
= minetest
.get_node(below
)
146 minetest
.node_dig(pos
, node
, digger
)
147 local vg
= minetest
.get_item_group(node
.name
, "vines")
148 local vg2
= minetest
.get_item_group(belownode
.name
, "vines")
149 if vg
~= 0 and vg
== vg2
and (not check_vines_supported(below
, belownode
)) then
150 return minetest
.registered_nodes
[node
.name
].on_dig(below
, node
, digger
)
154 local function register_vine(id
, def
)
155 local paramtype2
, drawtype
, buildable_to
156 if def
.vines_type
== "center" then
157 drawtype
= "plantlike"
159 elseif def
.vines_type
== "side" then
160 paramtype2
= "wallmounted"
161 drawtype
= "signlike"
164 local selection_box
= def
.selection_box
or {
165 type = "wallmounted",
168 local is_centered
= def
.groups
.vines
== 2
170 minetest
.register_node("vines:"..id
, {
171 description
= def
.description_normal
,
176 buildable_to
= buildable_to
,
177 sunlight_propagates
= true,
179 paramtype2
= paramtype2
,
180 tiles
= { "vines_"..id
..".png" },
182 inventory_image
= "vines_"..id
..".png",
183 wield_image
= "vines_"..id
..".png",
185 sounds
= hades_sounds
.node_sound_leaves_defaults(),
186 selection_box
= selection_box
,
187 node_placement_prediction
= "",
189 on_place
= get_on_place(is_centered
),
191 after_dig_node
= after_dig_node
,
194 if def
.description_rotten
then
195 local groups_rotten
= table.copy(def
.groups
)
196 groups_rotten
.vines_rotten
= 1
198 minetest
.register_node("vines:"..id
.."_rotten", {
199 description
= def
.description_rotten
,
203 buildable_to
= buildable_to
,
204 sunlight_propagates
= true,
206 paramtype2
= paramtype2
,
207 tiles
= { "vines_"..id
.."_rotten.png" },
209 inventory_image
= "vines_"..id
.."_rotten.png",
210 wield_image
= "vines_"..id
.."_rotten.png",
211 groups
= groups_rotten
,
212 sounds
= hades_sounds
.node_sound_leaves_defaults(),
213 selection_box
= selection_box
,
214 node_placement_prediction
= "",
215 on_place
= get_on_place(is_centered
),
217 after_dig_node
= after_dig_node
,
222 register_vine("side", {
224 description_normal
= S("Jungle Vine"),
225 description_rotten
= S("Rotten Jungle Vine"),
226 groups
= vines_group_side
,
229 register_vine("willow", {
231 description_normal
= S("Willow Vine"),
232 description_rotten
= S("Rotten Willow Vine"),
233 groups
= vines_group_side
,
236 register_vine("vine", {
237 vines_type
= "center",
238 description_normal
= S("Cave Vine"),
239 description_rotten
= S("Rotten Cave Vine"),
240 groups
= vines_group_center
,
243 fixed
= {-0.3, -1/2, -0.3, 0.3, 1/2, 0.3},
247 register_vine("root", {
248 vines_type
= "center",
249 description_normal
= S("Root Vine"),
250 groups
= vines_group_center
,
253 fixed
= {-1/6, -1/2, -1/6, 1/6, 1/2, 1/6},
259 minetest
.register_abm({
261 nodenames
= {"vines:vine", "vines:side", "vines:willow"},
264 action
= function(pos
, node
, active_object_count
, active_object_count_wider
)
265 if minetest
.find_node_near(pos
, 5, "group:tree") == nil then
266 walldir
= node
.param2
267 minetest
.add_node(pos
, {name
=node
.name
.."_rotten", param2
= walldir
})
272 minetest
.register_abm({
273 label
= "Grow vines",
274 nodenames
= {"vines:vine", "vines:side", "vines:willow"},
277 action
= function(pos
, node
, active_object_count
, active_object_count_wider
)
278 local p
= {x
=pos
.x
, y
=pos
.y
-1, z
=pos
.z
}
279 local n
= minetest
.get_node(p
)
280 if n
.name
== "air" then
281 walldir
= node
.param2
282 minetest
.add_node(p
, {name
=node
.name
, param2
= walldir
})
287 local function vinedecay_particles(pos
, node
)
288 local g
= minetest
.get_item_group(node
.name
, "vines")
289 local relpos1
, relpos2
291 local dir
= minetest
.wallmounted_to_dir(node
.param2
)
293 relpos1
= { x
= -0.45, y
= -0.4, z
= -0.5 }
294 relpos2
= { x
= -0.4, y
= 0.4, z
= 0.5 }
295 elseif dir
.x
> 0 then
296 relpos1
= { x
= 0.4, y
= -0.4, z
= -0.5 }
297 relpos2
= { x
= 0.45, y
= 0.4, z
= 0.5 }
298 elseif dir
.z
< 0 then
299 relpos1
= { x
= -0.5, y
= -0.4, z
= -0.45 }
300 relpos2
= { x
= 0.5, y
= 0.4, z
= -0.4 }
301 elseif dir
.z
> 0 then
302 relpos1
= { x
= -0.5, y
= -0.4, z
= 0.4 }
303 relpos2
= { x
= 0.5, y
= 0.4, z
= 0.45 }
308 relpos1
= { x
= -0.25, y
= -0.5, z
= -0.25 }
309 relpos2
= { x
= 0.25, y
= 0.5, z
= 0.25 }
314 minetest
.add_particlespawner({
315 amount
= math
.random(8, 16),
317 minpos
= vector
.add(pos
, relpos1
),
318 maxpos
= vector
.add(pos
, relpos2
),
319 minvel
= {x
=-0.2, y
=-0.2, z
=-0.2},
320 maxvel
= {x
=0.2, y
=0.1, z
=0.2},
321 minacc
= {x
=0, y
=-9.81, z
=0},
322 maxacc
= {x
=0, y
=-9.81, z
=0},
327 collisiondetection
= true,
334 minetest
.register_abm({
335 label
= "Vines decay",
336 nodenames
= {"group:vines"},
337 -- A low interval and a high inverse chance spreads the load
341 action
= function(pos
, node
)
342 if not check_vines_supported(pos
, node
) then
344 vinedecay_particles(pos
, node
)
345 minetest
.remove_node(pos
)
346 minetest
.check_for_falling(pos
)
354 minetest
.register_craftitem("vines:vines", {
355 description
= S("Detached Vine"),
356 inventory_image
= "vines_item.png",
361 plantslib
:spawn_on_surfaces({
362 avoid_nodes
= {"vines:vine"},
364 spawn_delay
= spawn_interval
,
365 spawn_plants
= {"vines:vine"},
367 spawn_surfaces
= {"hades_core:dirt_with_grass","hades_core:dirt"},
368 spawn_on_bottom
= true,
369 plantlife_limit
= -0.9,
372 plantslib
:spawn_on_surfaces({
373 avoid_nodes
= {"vines:vine", "vines:side"},
375 spawn_delay
= spawn_interval
,
376 spawn_plants
= {"vines:side"},
378 spawn_surfaces
= {"group:leaves"},
379 spawn_on_side
= true,
380 near_nodes
= {"hades_core:water_source", "hades_trees:jungle_tree"},
381 near_nodes_size
= 10,
382 near_nodes_vertical
= 5,
383 near_nodes_count
= 3,
384 plantlife_limit
= -0.9,
387 plantslib
:spawn_on_surfaces({
388 spawn_plants
= {"vines:willow"},
390 spawn_delay
= spawn_interval
,
392 spawn_surfaces
= {"group:leaves"},
393 spawn_on_side
= true,
394 near_nodes
= {"hades_core:water_source"},
396 near_nodes_vertical
= 4,
397 near_nodes_count
= 3,
398 plantlife_limit
= -0.9,
401 -- Shears: jojoa1997's shears
403 minetest
.register_tool("vines:shears", {
404 description
= S("Shears"),
405 _tt_help
= S("Cuts leaves, vines and plants"),
406 inventory_image
= "vines_shears.png",
407 wield_image
= "vines_shears.png",
410 groups
= { shears
= 1 },
411 tool_capabilities
= {
412 full_punch_interval
= 1.0,
415 snappy
={times
={[3]=0.2, [2]=0.5, [1]=1.5}, uses
=20, maxlevel
=3},
420 minetest
.register_craft({
421 output
= 'vines:shears',
423 {'', 'hades_core:steel_ingot', ''},
424 {'group:stick', 'group:wood', 'hades_core:steel_ingot'},
425 {'', 'group:stick', ''},
429 minetest
.register_node("vines:vines_block",{
430 description
= S("Vines Block"),
431 sunlight_propagates
= true,
432 tiles
= {"vines_block.png", "vines_block.png", "vines_block.png"},
433 drawtype
= "allfaces_optional",
435 groups
= {snappy
=2,flammable
=2 },
436 sounds
= hades_sounds
.node_sound_leaves_defaults(),
439 minetest
.register_craft({
440 output
= 'vines:vines_block',
442 {'farming:string', '', 'farming:string'},
443 {'', 'group:vines', ''},
444 {'farming:string', '', 'farming:string'},
448 minetest
.register_alias("vines:rope", "vines:root")
449 minetest
.register_alias("vines:rope_end", "vines:root")
451 minetest
.log("action", "[vines] Loaded!")