-
Notifications
You must be signed in to change notification settings - Fork 7
/
kelp_spread.lua
176 lines (167 loc) · 6.8 KB
/
kelp_spread.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
local spread_radius = 4
local spread_density = 12
local max_poss_to_consider = 5
local required_water_column = 6
local function check_column(base_pos)
for i = 1, required_water_column do
local pos = vector.add(base_pos, vector.new(0, i, 0))
local node_info = minetest.get_node(pos)
local node_light = minetest.get_node_light(pos)
if node_info.name ~= "default:water_source" then return false end
if node_light == 0 then return false end
end
return true
end
minetest.register_abm({
label = "kelp spread",
nodenames = {"default:sand_with_kelp"},
interval = 37,
chance = 100,
action = function(pos, node, active_object_count, active_object_count_wider)
-- y between -5 and -10 w/ offset -1 (so y = -6 to y = -10)
local pos0 = vector.subtract(pos, spread_radius)
local pos1 = vector.add(pos, spread_radius)
if #minetest.find_nodes_in_area(pos0, pos1, "default:sand_with_kelp") > spread_density then
return
end
local potential_poss = minetest.find_nodes_in_area(pos0, pos1, "default:sand")
local poss_considered = 0
while #potential_poss > 0 and poss_considered < max_poss_to_consider do
local i = math.random(#potential_poss)
local ppos = table.remove(potential_poss, i)
if check_column(ppos) then
local param2 = math.random(48, 96)
minetest.set_node(ppos, {name = "default:sand_with_kelp", param2 = param2})
end
poss_considered = poss_considered + 1
end
end,
})
local function distance_to_air(pos)
for i = 0, 10 do
local npos = vector.add(pos, vector.new(0, i, 0))
local node_info = minetest.get_node(npos)
if node_info.name == "air" then return i end
end
return 11
end
local function distance_to_sand(pos)
for i = 0, 10 do
local npos = vector.subtract(pos, vector.new(0, i, 0))
local node_info = minetest.get_node(npos)
if node_info.name == "default:sand" then return i end
end
return 11
end
minetest.register_abm({
label = "coral spread",
nodenames = {"default:water_source", "default:coral_skeleton"},
neighbors = {"default:coral_brown", "default:coral_orange"},
interval = 47,
chance = 80,
action = function(pos, node, active_object_count, active_object_count_wider)
if minetest.get_node_light(pos) == 0 then return end
local dta = distance_to_air(pos)
local dts = distance_to_sand(pos)
if 1 >= dta or dta > 8 or dts > 5 then return end
local pos0 = vector.subtract(pos, 1)
local pos1 = vector.add(pos, 1)
local num_neighbors = #minetest.find_nodes_in_area(pos0, pos1,
{
"default:coral_brown",
"default:coral_orange",
"default:coral_skeleton",
"default:coral_cyan",
"default:coral_pink",
"default:coral_green",
}
)
if num_neighbors >= 4 then
local pos_below = vector.subtract(pos, vector.new(0, 1, 0))
local name_below = minetest.get_node(pos_below).name
if name_below == "default:sand" or name_below == "default:coral_skeleton" then
local rv = math.random(3)
if rv == 1 then
minetest.set_node(pos, {name = "default:coral_cyan"})
elseif rv == 2 then
minetest.set_node(pos, {name = "default:coral_pink"})
elseif rv == 3 then
minetest.set_node(pos, {name = "default:coral_green"})
end
else
if minetest.get_node(pos).name == "default:coral_skeleton" then
minetest.set_node(pos, {name = "default:coral_brown"})
else
minetest.set_node(pos, {name = "default:coral_orange"})
end
end
end
end,
})
minetest.register_abm({
label = "coral blobbing",
nodenames = {"default:coral_green", "default:coral_cyan", "default:coral_pink"},
neighbors = {"default:water_source", "default:water_flowing"},
interval = 49,
chance = 40,
action = function(pos, node, active_object_count, active_object_count_wider)
local pos_above = vector.add(pos, vector.new(0, 1, 0))
local name_above = minetest.get_node(pos_above).name
if name_above == "default:coral_green" or name_above == "default:coral_cyan" or name_above == "default:coral_pink" or name_above == "default:coral_brown" or name_above == "default:coral_orange" or name_above == "default:coral_skeleton" then
minetest.set_node(pos, {name = "default:coral_orange"})
return
end
local pos_below = vector.subtract(pos, vector.new(0, 1, 0))
local name_below = minetest.get_node(pos_below).name
if name_below == "default:water_source" then
minetest.set_node(pos, {name = "default:water_source"})
return
end
end,
})
minetest.register_abm({
label = "coral death",
nodenames = {"default:coral_brown", "default:coral_orange"},
interval = 51,
chance = 40,
action = function(pos, node, active_object_count, active_object_count_wider)
local dta = distance_to_air(pos)
local dts = distance_to_sand(pos)
if 1 >= dta or dta > 8 or dts > 5 then
minetest.set_node(pos, {name = "default:water_source"})
return
end
local pos0 = vector.subtract(pos, 2)
local pos1 = vector.add(pos, 2)
local num_neighbors = #minetest.find_nodes_in_area(pos0, pos1,
{
"default:coral_brown",
"default:coral_orange",
"default:coral_skeleton",
"default:coral_cyan",
"default:coral_pink",
"default:coral_green",
}
)
local node_name = minetest.get_node(pos).name
if 2 >= num_neighbors or num_neighbors >= 27 then
minetest.set_node(pos, {name = "default:water_source"})
elseif node_name == "default:coral_orange" then
minetest.set_node(pos, {name = "default:coral_brown"})
elseif node_name == "default:coral_brown" then
if math.random(10) == 1 then
minetest.set_node(pos, {name = "default:coral_skeleton"})
end
end
end,
})
minetest.register_abm({
label = "coral skeleton erosion",
nodenames = {"default:coral_skeleton"},
neighbors = {"default:water_source", "default:water_flowing"},
interval = 53,
chance = 100,
action = function(pos, node, active_object_count, active_object_count_wider)
minetest.set_node(pos, {name = "default:water_source"})
end,
})