Localize accidental global var in hades_trees
[minetest_hades/hades_revisited.git] / mods / hades_trees / generator.lua
blobb655bf0b8eb09cb3d443e864624cfe0677469d35
1 local pr_a, pr_j -- PseudoRandom vars
3 function hades_trees.grow_sapling(pos, check_light)
4 local node = minetest.get_node(pos, check_light)
5 if node.name == "hades_trees:sapling" then
6 hades_trees.generate_appletree(pos, check_light)
7 elseif node.name == "hades_trees:jungle_sapling" then
8 hades_trees.generate_jungletree(pos, check_light)
9 elseif node.name == "hades_trees:cultivated_jungle_sapling" then
10 hades_trees.generate_cjtree(pos, check_light)
11 elseif node.name == "hades_trees:olive_sapling" then
12 hades_trees.generate_olivetree(pos, check_light)
13 elseif node.name == "hades_trees:birch_sapling" then
14 hades_trees.generate_birchtree(pos, check_light)
15 elseif node.name == "hades_trees:pale_sapling" then
16 hades_trees.generate_paletree(pos, check_light)
17 end
18 end
20 local function check_node_light(pos, minlight, check)
21 if check == false then
22 return true
23 end
24 local l = minetest.get_node_light(pos)
25 if not l or l < minlight then
26 return false
27 end
28 return true
29 end
31 -- Common Tree
32 function hades_trees.generate_tree(pos, check_light, trunk, leaves, underground, replacements)
33 if not trunk then
34 trunk = "hades_trees:tree"
35 end
36 if not leaves then
37 leaves = "hades_trees:leaves"
38 end
39 if not underground then
40 underground = {"hades_core:dirt", "hades_core:dirt_with_grass"}
41 end
42 pos.y = pos.y-1
43 local nodename = minetest.get_node(pos).name
44 local ret = false
45 for _,name in ipairs(underground) do
46 if nodename == name then
47 ret = true
48 break
49 end
50 end
51 if not ret then
52 return
53 end
54 pos.y = pos.y+1
55 if not check_node_light(pos, 8, check_light) then
56 return
57 end
59 local node = {name = ""}
60 for dy=1,3 do
61 pos.y = pos.y+dy
62 if minetest.get_node(pos).name ~= "air" then
63 return
64 end
65 pos.y = pos.y-dy
66 end
67 node.name = trunk
68 for dy=0,3 do
69 pos.y = pos.y+dy
70 minetest.set_node(pos, node)
71 pos.y = pos.y-dy
72 end
75 if not replacements then
76 replacements = {}
77 end
80 node.name = leaves
81 pos.y = pos.y+4
82 for dx=-2,2 do
83 for dz=-2,2 do
84 for dy=-1,2 do
85 pos.x = pos.x+dx
86 pos.y = pos.y+dy
87 pos.z = pos.z+dz
90 if dx == 0 and dz == 0 and dy==3 then
91 if minetest.get_node(pos).name == "air" and math.random(1, 6) <= 4 then
92 minetest.set_node(pos, node)
93 for name,rarity in pairs(replacements) do
94 if math.random(1, rarity) == 1 then
95 minetest.set_node(pos, {name=name})
96 end
97 end
98 end
99 elseif dx == 0 and dz == 0 and dy==4 then
100 if minetest.get_node(pos).name == "air" and math.random(1, 6) <= 4 then
101 minetest.set_node(pos, node)
102 for name,rarity in pairs(replacements) do
103 if math.random(1, rarity) == 1 then
104 minetest.set_node(pos, {name=name})
108 elseif math.abs(dx) ~= 2 and math.abs(dz) ~= 2 then
109 if minetest.get_node(pos).name == "air" then
110 minetest.set_node(pos, node)
111 for name,rarity in pairs(replacements) do
112 if math.random(1, rarity) == 1 then
113 minetest.set_node(pos, {name=name})
117 else
118 if math.abs(dx) ~= 2 or math.abs(dz) ~= 2 then
119 if minetest.get_node(pos).name == "air" and math.random(1, 6) <= 4 then
120 minetest.set_node(pos, node)
121 for name,rarity in pairs(replacements) do
122 if math.random(1, rarity) == 1 then
123 minetest.set_node(pos, {name=name})
131 pos.x = pos.x-dx
132 pos.y = pos.y-dy
133 pos.z = pos.z-dz
139 -- Olive Tree
140 function hades_trees.generate_olivetree(pos, check_light, trunk, leaves, underground, replacements)
141 if not trunk then
142 trunk = "hades_trees:tree"
144 if not leaves then
145 leaves = "hades_trees:olive_leaves"
147 if not underground then
148 underground = {"hades_core:dirt", "hades_core:dirt_with_grass"}
150 if not replacements then
151 replacements = {["hades_trees:olive"]=10}
153 hades_trees.generate_tree(pos, check_light, trunk, leaves, underground, replacements)
156 -- Pale Tree
157 function hades_trees.generate_paletree(pos, check_light, trunk, leaves, underground)
158 if not trunk then
159 trunk = "hades_trees:pale_tree"
161 if not leaves then
162 leaves = "hades_trees:pale_leaves"
164 if not underground then
165 underground = {"hades_core:dirt", "hades_core:dirt_with_grass", "hades_core:ash", "hades_core:fertile_sand"}
167 pos.y = pos.y-1
168 local nodename = minetest.get_node(pos).name
169 local ret = false
170 for _,name in ipairs(underground) do
171 if nodename == name then
172 ret = true
173 break
176 if not ret then
177 return
179 pos.y = pos.y+1
180 if not check_node_light(pos, 8, check_light) then
181 return
184 local node = {name = ""}
185 for dy=1,6 do
186 pos.y = pos.y+dy
187 if minetest.get_node(pos).name ~= "air" then
188 return
190 pos.y = pos.y-dy
192 node.name = trunk
193 for dy=0,6 do
194 pos.y = pos.y+dy
195 minetest.set_node(pos, node)
196 pos.y = pos.y-dy
200 node.name = leaves
201 pos.y = pos.y+3
202 for dx=-1,1 do
203 for dz=-1,1 do
204 for dy=-1,5 do
205 pos.x = pos.x+dx
206 pos.y = pos.y+dy
207 pos.z = pos.z+dz
210 if dx == 0 and dz == 0 and dy==5 then
211 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 4 then
212 minetest.set_node(pos, node)
214 elseif dx == 0 and dz == 0 and dy==6 then
215 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 4 then
216 minetest.set_node(pos, node)
218 elseif math.abs(dx) ~= 1 or math.abs(dz) ~= 1 and dy>=5 then
219 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 3 then
220 minetest.set_node(pos, node)
222 elseif math.abs(dx) ~= 1 or math.abs(dz) ~= 1 then
223 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 4 then
224 minetest.set_node(pos, node)
226 elseif math.abs(dx) ~= 2 or math.abs(dz) ~= 2 and dy==4 then
227 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 2 then
228 minetest.set_node(pos, node)
230 elseif math.abs(dx) ~= 2 or math.abs(dz) ~= 2 and dy==3 then
231 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 4 then
232 minetest.set_node(pos, node)
238 pos.x = pos.x-dx
239 pos.y = pos.y-dy
240 pos.z = pos.z-dz
246 -- Birch Tree
247 function hades_trees.generate_birchtree(pos, check_light, trunk, leaves, underground)
248 if not trunk then
249 trunk = "hades_trees:birch_tree"
251 if not leaves then
252 leaves = "hades_trees:birch_leaves"
254 if not underground then
255 underground = {"hades_core:dirt", "hades_core:dirt_with_grass"}
257 pos.y = pos.y-1
258 local nodename = minetest.get_node(pos).name
259 local ret = false
260 for _,name in ipairs(underground) do
261 if nodename == name then
262 ret = true
263 break
266 if not ret then
267 return
269 pos.y = pos.y+1
270 if not check_node_light(pos, 8, check_light) then
271 return
274 local node = {name = ""}
275 for dy=1,6 do
276 pos.y = pos.y+dy
277 if minetest.get_node(pos).name ~= "air" then
278 return
280 pos.y = pos.y-dy
282 node.name = trunk
283 for dy=0,6 do
284 pos.y = pos.y+dy
285 minetest.set_node(pos, node)
286 pos.y = pos.y-dy
290 node.name = leaves
291 pos.y = pos.y+4
292 for dx=-2,2 do
293 for dz=-2,2 do
294 for dy=-1,5 do
295 pos.x = pos.x+dx
296 pos.y = pos.y+dy
297 pos.z = pos.z+dz
300 if dx == 0 and dz == 0 and dy==5 then
301 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 2 then
302 minetest.set_node(pos, node)
304 elseif dx == 0 and dz == 0 and dy==6 then
305 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 2 then
306 minetest.set_node(pos, node)
308 elseif math.abs(dx) ~= 1 or math.abs(dz) ~= 1 and dy>=5 then
309 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 3 then
310 minetest.set_node(pos, node)
313 elseif math.abs(dx) ~= 1 or math.abs(dz) ~= 1 then
314 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 2 then
315 minetest.set_node(pos, node)
318 elseif math.abs(dx) ~= 2 or math.abs(dz) ~= 2 and dy==4 then
319 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 2 then
320 minetest.set_node(pos, node)
322 elseif math.abs(dx) ~= 2 or math.abs(dz) ~= 2 and dy==3 then
323 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 3 then
324 minetest.set_node(pos, node)
330 pos.x = pos.x-dx
331 pos.y = pos.y-dy
332 pos.z = pos.z-dz
339 -- Cultivated Jungle Tree
340 function hades_trees.generate_cjtree(pos, check_light, trunk, leaves, underground)
341 if not trunk then
342 trunk = "hades_trees:jungle_tree"
344 if not leaves then
345 leaves = "hades_trees:cultivated_jungle_leaves"
347 if not underground then
348 underground = {"hades_core:dirt", "hades_core:dirt_with_grass"}
351 pos.y = pos.y-1
352 local nodename = minetest.get_node(pos).name
353 local ret = false
354 for _,name in ipairs(underground) do
355 if nodename == name then
356 ret = true
357 break
360 if not ret then
361 return
363 pos.y = pos.y+1
364 if not check_node_light(pos, 8, check_light) then
365 return
368 local node = {name = ""}
369 for dy=1,12 do
370 pos.y = pos.y+dy
371 if minetest.get_node(pos).name ~= "air" then
372 return
374 pos.y = pos.y-dy
376 node.name = trunk
377 for dy=0,12 do
378 pos.y = pos.y+dy
379 minetest.set_node(pos, node)
380 pos.y = pos.y-dy
384 node.name = leaves
385 pos.y = pos.y+10
386 for dx=-3,3 do
387 for dz=-3,3 do
388 for dy=0,3 do
389 pos.x = pos.x+dx
390 pos.y = pos.y+dy
391 pos.z = pos.z+dz
394 if dx == 0 and dz == 0 and dy==1 then
395 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 4 then
396 minetest.set_node(pos, node)
398 elseif dx == 0 and dz == 0 and dy==2 then
399 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 4 then
400 minetest.set_node(pos, node)
402 elseif math.abs(dx) ~= 1 or math.abs(dz) ~= 1 and dy>=3 then
403 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 3 then
404 minetest.set_node(pos, node)
406 elseif math.abs(dx) ~= 1 or math.abs(dz) ~= 1 then
407 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 4 then
408 minetest.set_node(pos, node)
410 elseif math.abs(dx) ~= 2 or math.abs(dz) ~= 2 and dy==2 then
411 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 2 then
412 minetest.set_node(pos, node)
414 elseif math.abs(dx) ~= 3 or math.abs(dz) ~= 3 and dy==3 then
415 if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 4 then
416 minetest.set_node(pos, node)
422 pos.x = pos.x-dx
423 pos.y = pos.y-dy
424 pos.z = pos.z-dz
430 --------
431 local c_air = minetest.CONTENT_AIR
432 local c_ignore = minetest.CONTENT_IGNORE
433 local c_jungletree = minetest.get_content_id("hades_trees:jungle_tree")
434 local c_jungleleaves = minetest.get_content_id("hades_trees:jungle_leaves")
435 local c_tree = minetest.get_content_id("hades_trees:tree")
436 local c_leaves = minetest.get_content_id("hades_trees:leaves")
437 local c_apple = minetest.get_content_id("hades_trees:apple")
439 function hades_trees.generate_jungletree(pos, check_light)
440 local nu = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name
442 local ret = false
443 for _,name in ipairs({"hades_core:dirt", "hades_core:dirt_with_grass"}) do
444 if nu == name then
445 ret = true
446 break
449 if not ret then
450 return
453 minetest.log("action", "[action] A jungle sapling grows into a tree at "..minetest.pos_to_string(pos))
454 local vm = minetest.get_voxel_manip()
455 local minp, maxp = vm:read_from_map({x=pos.x-16, y=pos.y-1, z=pos.z-16}, {x=pos.x+16, y=pos.y+16, z=pos.z+16})
456 local a = VoxelArea:new{MinEdge=minp, MaxEdge=maxp}
457 local data = vm:get_data()
459 if not pr_j then
460 local seed = math.random(1,100000)
461 pr_j = PseudoRandom(seed)
463 local x, y, z = pos.x, pos.y, pos.z
465 local lpos = {x=pos.x, y=pos.y+1, z=pos.z}
466 if not check_node_light(lpos, 8, check_light) then
467 return
470 local th = pr_j:next(10, 14)
471 for yy = y, y+th-1 do
472 local vi = a:index(x, yy, z)
473 if a:contains(x, yy, z) and (data[vi] == c_air or yy == y) then
474 data[vi] = c_jungletree
477 y = y+th-1 -- (x, y, z) is now last piece of trunk
478 local leaves_a = VoxelArea:new{MinEdge={x=-3, y=-4, z=-3}, MaxEdge={x=3, y=2, z=3}}
479 local leaves_buffer = {}
481 -- Force leaves near the trunk
482 local d = 1
483 for xi = -d, d do
484 for yi = -d, d do
485 for zi = -d, d do
486 leaves_buffer[leaves_a:index(xi, yi, zi)] = true
491 -- Add leaves randomly
492 for iii = 1, 30 do
493 local d = 1
494 local xx = pr_j:next(leaves_a.MinEdge.x, leaves_a.MaxEdge.x - d)
495 local yy = pr_j:next(leaves_a.MinEdge.y, leaves_a.MaxEdge.y - d)
496 local zz = pr_j:next(leaves_a.MinEdge.z, leaves_a.MaxEdge.z - d)
498 for xi = 0, d do
499 for yi = 0, d do
500 for zi = 0, d do
501 leaves_buffer[leaves_a:index(xx+xi, yy+yi, zz+zi)] = true
507 -- Add the leaves
508 for xi = leaves_a.MinEdge.x, leaves_a.MaxEdge.x do
509 for yi = leaves_a.MinEdge.y, leaves_a.MaxEdge.y do
510 for zi = leaves_a.MinEdge.z, leaves_a.MaxEdge.z do
511 if a:contains(x+xi, y+yi, z+zi) then
512 local vi = a:index(x+xi, y+yi, z+zi)
513 if data[vi] == c_air or data[vi] == c_ignore then
514 if leaves_buffer[leaves_a:index(xi, yi, zi)] then
515 data[vi] = c_jungleleaves
523 vm:set_data(data)
524 vm:write_to_map(data)
525 vm:update_map()
528 function hades_trees.generate_appletree(pos, check_light, is_apple_tree)
529 local nu = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name
531 local ret = false
532 for _,name in ipairs({"hades_core:dirt", "hades_core:dirt_with_grass"}) do
533 if nu == name then
534 ret = true
535 break
538 if not ret then
539 return
542 local lpos = {x=pos.x, y=pos.y+1, z=pos.z}
543 if not check_node_light(lpos, 8, check_light) then
544 return
547 minetest.log("action", "[hades_trees] A sapling grows into an apple tree at "..minetest.pos_to_string(pos))
548 local vm = minetest.get_voxel_manip()
549 local minp, maxp = vm:read_from_map({x=pos.x-16, y=pos.y, z=pos.z-16}, {x=pos.x+16, y=pos.y+16, z=pos.z+16})
550 local a = VoxelArea:new{MinEdge=minp, MaxEdge=maxp}
551 local data = vm:get_data()
552 if is_apple_tree == nil then
553 is_apple_tree = math.random(1, 4) == 1
556 if not pr_a then
557 local seed = math.random(1,100000)
558 pr_a = PseudoRandom(seed)
560 local th = pr_a:next(4, 6)
561 local x, y, z = pos.x, pos.y, pos.z
562 for yy = y, y+th-1 do
563 local vi = a:index(x, yy, z)
564 if a:contains(x, yy, z) and (data[vi] == c_air or yy == y) then
565 data[vi] = c_tree
568 y = y+th-1 -- (x, y, z) is now last piece of trunk
569 local leaves_a = VoxelArea:new{MinEdge={x=-2, y=-2, z=-2}, MaxEdge={x=2, y=2, z=2}}
570 local leaves_buffer = {}
572 -- Force leaves near the trunk
573 local d = 1
574 for xi = -d, d do
575 for yi = -d, d do
576 for zi = -d, d do
577 leaves_buffer[leaves_a:index(xi, yi, zi)] = true
582 -- Add leaves randomly
583 for iii = 1, 8 do
584 local d = 1
585 local xx = pr_a:next(leaves_a.MinEdge.x, leaves_a.MaxEdge.x - d)
586 local yy = pr_a:next(leaves_a.MinEdge.y, leaves_a.MaxEdge.y - d)
587 local zz = pr_a:next(leaves_a.MinEdge.z, leaves_a.MaxEdge.z - d)
589 for xi = 0, d do
590 for yi = 0, d do
591 for zi = 0, d do
592 leaves_buffer[leaves_a:index(xx+xi, yy+yi, zz+zi)] = true
598 -- Add the leaves
599 for xi = leaves_a.MinEdge.x, leaves_a.MaxEdge.x do
600 for yi = leaves_a.MinEdge.y, leaves_a.MaxEdge.y do
601 for zi = leaves_a.MinEdge.z, leaves_a.MaxEdge.z do
602 if a:contains(x+xi, y+yi, z+zi) then
603 local vi = a:index(x+xi, y+yi, z+zi)
604 if data[vi] == c_air or data[vi] == c_ignore then
605 if leaves_buffer[leaves_a:index(xi, yi, zi)] then
606 if pr_a:next(1, 100) <= 3 then -- is_apple_tree and(zwischen if und pr:next)
607 data[vi] = c_apple
608 else
609 data[vi] = c_leaves
618 vm:set_data(data)
619 vm:write_to_map(data)
620 vm:update_map()