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
,
178 sunlight_propagates
= true,
180 paramtype2
= paramtype2
,
181 tiles
= { "vines_"..id
..".png" },
183 inventory_image
= "vines_"..id
..".png",
184 wield_image
= "vines_"..id
..".png",
186 sounds
= hades_sounds
.node_sound_leaves_defaults(),
187 selection_box
= selection_box
,
188 node_placement_prediction
= "",
190 on_place
= get_on_place(is_centered
),
192 after_dig_node
= after_dig_node
,
195 if def
.description_rotten
then
196 local groups_rotten
= table.copy(def
.groups
)
197 groups_rotten
.vines_rotten
= 1
199 minetest
.register_node("vines:"..id
.."_rotten", {
200 description
= def
.description_rotten
,
204 buildable_to
= buildable_to
,
206 sunlight_propagates
= true,
208 paramtype2
= paramtype2
,
209 tiles
= { "vines_"..id
.."_rotten.png" },
211 inventory_image
= "vines_"..id
.."_rotten.png",
212 wield_image
= "vines_"..id
.."_rotten.png",
213 groups
= groups_rotten
,
214 sounds
= hades_sounds
.node_sound_leaves_defaults(),
215 selection_box
= selection_box
,
216 node_placement_prediction
= "",
217 on_place
= get_on_place(is_centered
),
219 after_dig_node
= after_dig_node
,
224 register_vine("side", {
226 description_normal
= S("Jungle Vine"),
227 description_rotten
= S("Rotten Jungle Vine"),
228 groups
= vines_group_side
,
231 register_vine("willow", {
233 description_normal
= S("Willow Vine"),
234 description_rotten
= S("Rotten Willow Vine"),
235 groups
= vines_group_side
,
238 register_vine("vine", {
239 vines_type
= "center",
240 description_normal
= S("Cave Vine"),
241 description_rotten
= S("Rotten Cave Vine"),
242 groups
= vines_group_center
,
245 fixed
= {-0.3, -1/2, -0.3, 0.3, 1/2, 0.3},
249 register_vine("root", {
250 vines_type
= "center",
251 description_normal
= S("Root Vine"),
252 groups
= vines_group_center
,
255 fixed
= {-1/6, -1/2, -1/6, 1/6, 1/2, 1/6},
261 minetest
.register_abm({
263 nodenames
= {"vines:vine", "vines:side", "vines:willow"},
266 action
= function(pos
, node
, active_object_count
, active_object_count_wider
)
267 if minetest
.find_node_near(pos
, 5, "group:tree") == nil then
268 walldir
= node
.param2
269 minetest
.add_node(pos
, {name
=node
.name
.."_rotten", param2
= walldir
})
274 minetest
.register_abm({
275 label
= "Grow vines",
276 nodenames
= {"vines:vine", "vines:side", "vines:willow"},
279 action
= function(pos
, node
, active_object_count
, active_object_count_wider
)
280 local p
= {x
=pos
.x
, y
=pos
.y
-1, z
=pos
.z
}
281 local n
= minetest
.get_node(p
)
282 if n
.name
== "air" then
283 walldir
= node
.param2
284 minetest
.add_node(p
, {name
=node
.name
, param2
= walldir
})
289 local function vinedecay_particles(pos
, node
)
290 local g
= minetest
.get_item_group(node
.name
, "vines")
291 local relpos1
, relpos2
293 local dir
= minetest
.wallmounted_to_dir(node
.param2
)
295 relpos1
= { x
= -0.45, y
= -0.4, z
= -0.5 }
296 relpos2
= { x
= -0.4, y
= 0.4, z
= 0.5 }
297 elseif dir
.x
> 0 then
298 relpos1
= { x
= 0.4, y
= -0.4, z
= -0.5 }
299 relpos2
= { x
= 0.45, y
= 0.4, z
= 0.5 }
300 elseif dir
.z
< 0 then
301 relpos1
= { x
= -0.5, y
= -0.4, z
= -0.45 }
302 relpos2
= { x
= 0.5, y
= 0.4, z
= -0.4 }
303 elseif dir
.z
> 0 then
304 relpos1
= { x
= -0.5, y
= -0.4, z
= 0.4 }
305 relpos2
= { x
= 0.5, y
= 0.4, z
= 0.45 }
310 relpos1
= { x
= -0.25, y
= -0.5, z
= -0.25 }
311 relpos2
= { x
= 0.25, y
= 0.5, z
= 0.25 }
316 minetest
.add_particlespawner({
317 amount
= math
.random(8, 16),
319 minpos
= vector
.add(pos
, relpos1
),
320 maxpos
= vector
.add(pos
, relpos2
),
321 minvel
= {x
=-0.2, y
=-0.2, z
=-0.2},
322 maxvel
= {x
=0.2, y
=0.1, z
=0.2},
323 minacc
= {x
=0, y
=-9.81, z
=0},
324 maxacc
= {x
=0, y
=-9.81, z
=0},
329 collisiondetection
= true,
336 minetest
.register_abm({
337 label
= "Vines decay",
338 nodenames
= {"group:vines"},
339 -- A low interval and a high inverse chance spreads the load
343 action
= function(pos
, node
)
344 if not check_vines_supported(pos
, node
) then
346 vinedecay_particles(pos
, node
)
347 minetest
.remove_node(pos
)
348 minetest
.check_for_falling(pos
)
356 minetest
.register_craftitem("vines:vines", {
357 description
= S("Detached Vine"),
358 inventory_image
= "vines_item.png",
363 plantslib
:spawn_on_surfaces({
364 avoid_nodes
= {"vines:vine"},
366 spawn_delay
= spawn_interval
,
367 spawn_plants
= {"vines:vine"},
369 spawn_surfaces
= {"hades_core:dirt_with_grass","hades_core:dirt"},
370 spawn_on_bottom
= true,
371 plantlife_limit
= -0.9,
374 plantslib
:spawn_on_surfaces({
375 avoid_nodes
= {"vines:vine", "vines:side"},
377 spawn_delay
= spawn_interval
,
378 spawn_plants
= {"vines:side"},
380 spawn_surfaces
= {"group:leaves"},
381 spawn_on_side
= true,
382 near_nodes
= {"hades_core:water_source", "hades_trees:jungle_tree"},
383 near_nodes_size
= 10,
384 near_nodes_vertical
= 5,
385 near_nodes_count
= 3,
386 plantlife_limit
= -0.9,
389 plantslib
:spawn_on_surfaces({
390 spawn_plants
= {"vines:willow"},
392 spawn_delay
= spawn_interval
,
394 spawn_surfaces
= {"group:leaves"},
395 spawn_on_side
= true,
396 near_nodes
= {"hades_core:water_source"},
398 near_nodes_vertical
= 4,
399 near_nodes_count
= 3,
400 plantlife_limit
= -0.9,
403 -- Shears: jojoa1997's shears
405 minetest
.register_tool("vines:shears", {
406 description
= S("Shears"),
407 _tt_help
= S("Cuts leaves, vines and plants"),
408 inventory_image
= "vines_shears.png",
409 wield_image
= "vines_shears.png",
412 groups
= { shears
= 1 },
413 tool_capabilities
= {
414 full_punch_interval
= 1.0,
417 snappy
={times
={[3]=0.2, [2]=0.5, [1]=1.5}, uses
=20, maxlevel
=3},
422 minetest
.register_craft({
423 output
= 'vines:shears',
425 {'', 'hades_core:steel_ingot', ''},
426 {'group:stick', 'group:wood', 'hades_core:steel_ingot'},
427 {'', 'group:stick', ''},
431 minetest
.register_node("vines:vines_block",{
432 description
= S("Vines Block"),
433 sunlight_propagates
= true,
434 tiles
= {"vines_block.png", "vines_block.png", "vines_block.png"},
435 drawtype
= "allfaces_optional",
437 groups
= {snappy
=2,flammable
=2 },
438 sounds
= hades_sounds
.node_sound_leaves_defaults(),
441 minetest
.register_craft({
442 output
= 'vines:vines_block',
444 {'farming:string', '', 'farming:string'},
445 {'', 'group:vines', ''},
446 {'farming:string', '', 'farming:string'},
450 minetest
.register_alias("vines:rope", "vines:root")
451 minetest
.register_alias("vines:rope_end", "vines:root")
453 minetest
.log("action", "[vines] Loaded!")