Replace wrong along_shore node identifier
[minetest_hades/hades_revisited.git] / mods / vines / init.lua
blobdb32fdcb3f307b7d9bcdaa0358a9d2a4879451fa
1 local S = minetest.get_translator("vines")
3 local mod_name = "vines"
4 local average_height = 12
5 local spawn_interval = 90
8 --- VINES GROUPS
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")
16 local walldir ={}
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"))
25 end
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
44 supported = true
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
50 supported = true
51 end
52 elseif (vg == 2 and supports_vines(node2.name)) then
53 supported = true
54 end
55 return supported
56 end
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
63 return itemstack
64 end
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]
70 if not def then
71 return itemstack
72 end
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
80 end
81 end
83 local cnode
84 if centered then
85 cnode = minetest.get_node({x=above.x, y=above.y+1, z=above.z})
86 else
87 -- Sideways vines may not be placed on top or below another block
88 if under.y ~= above.y then
89 return itemstack
90 end
91 cnode = node
92 end
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
97 return itemstack
98 end
99 end
101 local idef = itemstack:get_definition()
102 local itemstack, success = minetest.item_place_node(itemstack, placer, pointed_thing)
104 if success then
105 if idef.sounds and idef.sounds.place then
106 minetest.sound_play(idef.sounds.place, {pos=above, gain=1}, true)
109 return itemstack
113 -- Get vines when using shears
114 local after_dig_node = function(pos, oldnode, oldmetadata, user)
115 local wielded
116 if not user or not user:is_player() then
117 return
119 if user:get_wielded_item() ~= nil then
120 wielded = user:get_wielded_item()
121 else
122 return
124 if minetest.get_item_group(wielded:get_name(), "shears") ~= 0 then
125 local add = true
126 local inv = user:get_inventory()
127 local newstack = ItemStack(oldnode.name)
128 if not inv then
129 add = false
130 elseif minetest.is_creative_enabled(user:get_player_name()) then
131 if inv:contains_item("main", newstack) then
132 add = false
135 if add == true 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"
158 buildable_to = false
159 elseif def.vines_type == "side" then
160 paramtype2 = "wallmounted"
161 drawtype = "signlike"
162 buildable_to = true
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,
172 _tt_help = tt_surv,
173 walkable = false,
174 climbable = true,
175 drop = "",
176 buildable_to = buildable_to,
177 sunlight_propagates = true,
178 paramtype = "light",
179 paramtype2 = paramtype2,
180 tiles = { "vines_"..id..".png" },
181 drawtype = drawtype,
182 inventory_image = "vines_"..id..".png",
183 wield_image = "vines_"..id..".png",
184 groups = def.groups,
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),
190 on_dig = on_dig,
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,
200 walkable = false,
201 climbable = true,
202 drop = "",
203 buildable_to = buildable_to,
204 sunlight_propagates = true,
205 paramtype = "light",
206 paramtype2 = paramtype2,
207 tiles = { "vines_"..id.."_rotten.png" },
208 drawtype = drawtype,
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),
216 on_dig = on_dig,
217 after_dig_node = after_dig_node,
222 register_vine("side", {
223 vines_type = "side",
224 description_normal = S("Jungle Vine"),
225 description_rotten = S("Rotten Jungle Vine"),
226 groups = vines_group_side,
229 register_vine("willow", {
230 vines_type = "side",
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,
241 selection_box = {
242 type = "fixed",
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,
251 selection_box = {
252 type = "fixed",
253 fixed = {-1/6, -1/2, -1/6, 1/6, 1/2, 1/6},
257 --ABM
259 minetest.register_abm({
260 label = "Vine rot",
261 nodenames = {"vines:vine", "vines:side", "vines:willow"},
262 interval = 300,
263 chance = 8,
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"},
275 interval = 300,
276 chance = 2,
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
290 if g == 1 then
291 local dir = minetest.wallmounted_to_dir(node.param2)
292 if dir.x < 0 then
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 }
304 else
305 return
307 elseif g == 2 then
308 relpos1 = { x = -0.25, y = -0.5, z = -0.25 }
309 relpos2 = { x = 0.25, y = 0.5, z = 0.25 }
310 else
311 return
314 minetest.add_particlespawner({
315 amount = math.random(8, 16),
316 time = 0.1,
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},
323 minexptime = 0.1,
324 maxexptime = 0.5,
325 minsize = 0.5,
326 maxsize = 1.0,
327 collisiondetection = true,
328 vertical = false,
329 node = node,
334 minetest.register_abm({
335 label = "Vines decay",
336 nodenames = {"group:vines"},
337 -- A low interval and a high inverse chance spreads the load
338 interval = 2,
339 chance = 5,
341 action = function(pos, node)
342 if not check_vines_supported(pos, node) then
343 on_dig(pos, node)
344 vinedecay_particles(pos, node)
345 minetest.remove_node(pos)
346 minetest.check_for_falling(pos)
348 end,
352 --Craft
354 minetest.register_craftitem("vines:vines", {
355 description = S("Detached Vine"),
356 inventory_image = "vines_item.png",
360 --spawning
361 plantslib:spawn_on_surfaces({
362 avoid_nodes = {"vines:vine"},
363 avoid_radius = 5,
364 spawn_delay = spawn_interval,
365 spawn_plants = {"vines:vine"},
366 spawn_chance = 50,
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"},
374 avoid_radius = 3,
375 spawn_delay = spawn_interval,
376 spawn_plants = {"vines:side"},
377 spawn_chance = 50,
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"},
389 avoid_radius = 3,
390 spawn_delay = spawn_interval,
391 spawn_chance = 50,
392 spawn_surfaces = {"group:leaves"},
393 spawn_on_side = true,
394 near_nodes = {"hades_core:water_source"},
395 near_nodes_size = 7,
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",
408 stack_max = 1,
409 max_drop_level=3,
410 groups = { shears = 1 },
411 tool_capabilities = {
412 full_punch_interval = 1.0,
413 max_drop_level=0,
414 groupcaps={
415 snappy={times={[3]=0.2, [2]=0.5, [1]=1.5}, uses=20, maxlevel=3},
420 minetest.register_craft({
421 output = 'vines:shears',
422 recipe = {
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",
434 paramtype = "light",
435 groups = {snappy=2,flammable=2 },
436 sounds = hades_sounds.node_sound_leaves_defaults(),
439 minetest.register_craft({
440 output = 'vines:vines_block',
441 recipe = {
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!")