-
Notifications
You must be signed in to change notification settings - Fork 12
/
cocos_palm.lua
339 lines (325 loc) · 10.6 KB
/
cocos_palm.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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
-- © 2016, Rogier <[email protected]>
-- Translation support
local S = minetest.get_translator("moretrees")
-- Some constants
local coconut_drop_ichance = 8
-- Make the cocos palm fruit trunk a real trunk (it is generated as a fruit)
local trunk = minetest.registered_nodes["moretrees:palm_trunk"]
local ftrunk = {}
local gftrunk = {}
for k,v in pairs(trunk) do
ftrunk[k] = v
gftrunk[k] = v
end
ftrunk.tiles = {}
gftrunk.tiles = {}
for k,v in pairs(trunk.tiles) do
ftrunk.tiles[k] = v
gftrunk.tiles[k] = v
end
ftrunk.drop = "moretrees:palm_trunk"
gftrunk.drop = "moretrees:palm_trunk"
ftrunk.after_destruct = function(pos, oldnode)
local coconuts = minetest.find_nodes_in_area(
{x=pos.x-1, y=pos.y, z=pos.z-1},
{x=pos.x+1, y=pos.y, z=pos.z+1},
{"group:moretrees_coconut"}
)
for _,coconutpos in pairs(coconuts) do
-- minetest.dig_node(coconutpos) does not cause nearby coconuts to be dropped :-( ...
--minetest.dig_node(coconutpos)
local items = minetest.get_node_drops(minetest.get_node(coconutpos).name)
minetest.swap_node(coconutpos, {name = "air"})
for _, itemname in pairs(items) do
minetest.add_item(coconutpos, itemname)
end
end
end
-- Make the different trunk types distinguishable (but barely)
ftrunk.tiles[1] = "moretrees_palm_trunk_top.png^[transformR90"
gftrunk.tiles[1] = "moretrees_palm_trunk_top.png^[transformR180"
gftrunk.description = gftrunk.description.." (gen)"
minetest.register_node("moretrees:palm_fruit_trunk", ftrunk)
minetest.register_node("moretrees:palm_fruit_trunk_gen", gftrunk)
local coconut_regrow_abm_spec = {
nodenames = { "moretrees:palm_fruit_trunk" },
interval = moretrees.coconut_flower_interval,
chance = moretrees.coconut_flower_chance,
action = function(pos, node, active_object_count, active_object_count_wider)
local coconuts = minetest.find_nodes_in_area(
{x=pos.x-1, y=pos.y, z=pos.z-1},
{x=pos.x+1, y=pos.y, z=pos.z+1},
"group:moretrees_coconut"
)
-- Expected growth interval increases exponentially with number of coconuts already hanging.
-- Also: if more coconuts are hanging, the chance of picking an empty spot decreases as well...
if math.random(2^#coconuts) <= 2 then
-- Grow in area of 3x3 round trunk
local dx=math.floor(math.random(3)-2)
local dz=math.floor(math.random(3)-2)
local coconutpos = {x=pos.x+dx, y=pos.y, z=pos.z+dz}
local coconutnode = minetest.get_node(coconutpos)
if coconutnode.name == "air" then
minetest.swap_node(coconutpos, {name="moretrees:coconut_0"})
end
end
end
}
if moretrees.coconuts_regrow then
minetest.register_abm(coconut_regrow_abm_spec)
end
-- Spawn initial coconuts
-- Spawn initial coconuts
-- (Instead of coconuts, a generated-palm fruit trunk is generated with the tree. This
-- ABM converts the trunk to a regular fruit trunk, and spawns some coconuts)
minetest.register_abm({
nodenames = { "moretrees:palm_fruit_trunk_gen" },
interval = 6,
chance = 1,
min_y = -16,
max_y = 48,
label = "converts palm trunk to a regular fruit trunk, and spawns some coconuts",
action = function(pos, node, active_object_count, active_object_count_wider)
minetest.swap_node(pos, {name="moretrees:palm_fruit_trunk"})
local poslist = minetest.find_nodes_in_area(
{x=pos.x-1, y=pos.y, z=pos.z-1},
{x=pos.x+1, y=pos.y, z=pos.z+1},
"air"
)
local genlist = {}
for k,v in pairs(poslist) do
genlist[k] = {x = math.random(100), pos = v}
end
table.sort(genlist, function(a, b) return a.x < b.x; end)
local count = 0
for _, gen in pairs(genlist) do
minetest.swap_node(gen.pos, {name = "moretrees:coconut_3"})
count = count + 1
if count == 4 then
break
end
end
end,
})
-- Register coconuts, and make them regrow
local coconut_growfn = function(pos, elapsed)
local node = minetest.get_node(pos)
local delay = moretrees.coconut_grow_interval
if not node then
return
elseif not moretrees.coconuts_regrow then
-- Regrowing has been turned off. Make coconust grow instantly
minetest.swap_node(pos, {name="moretrees:coconut_3"})
return
elseif node.name == "moretrees:coconut_3" then
-- Drop coconuts (i.e. remove them), so that new coconuts can grow.
-- Coconuts will drop as items with a small chance
if math.random(coconut_drop_ichance) == 1 then
if moretrees.coconut_item_drop_ichance > 0
and math.random(moretrees.coconut_item_drop_ichance) == 1 then
local items = minetest.get_node_drops(minetest.get_node(pos).name)
for _, itemname in pairs(items) do
minetest.add_item(pos, itemname)
end
end
minetest.swap_node(pos, {name = "air"})
end
else
-- Grow coconuts to the next stage
local offset = string.len("moretrees:coconut_x")
local n = string.sub(node.name, offset)
minetest.swap_node(pos, {name=string.sub(node.name, 1, offset-1)..n+1})
end
-- Don't catch up when elapsed time is large. Regular visits are needed for growth...
local timer = minetest.get_node_timer(pos)
timer:start(delay + math.random(moretrees.coconut_grow_interval))
end
local coconut_starttimer = function(pos, elapsed)
local timer = minetest.get_node_timer(pos)
local base_interval = moretrees.coconut_grow_interval * 2 / 3
timer:set(base_interval + math.random(base_interval), elapsed or 0)
end
for _,suffix in ipairs({"_0", "_1", "_2", "_3", ""}) do
local name
if suffix == "_0" then
name = S("Coconut Flower")
else
name = S("Coconut")
end
local drop = ""
local coco_group = 1
local tile = "moretrees_coconut"..suffix..".png"
local timerfn = coconut_growfn
local constructfn = coconut_starttimer
if suffix == "_3" then
drop = "moretrees:coconut"
tile = "moretrees_coconut.png"
elseif suffix == "" then
drop = nil
coco_group = nil
timerfn = nil
constructfn = nil
end
local coconutdef = {
description = name,
tiles = {tile},
drawtype = "plantlike",
paramtype = "light",
sunlight_propagates = true,
walkable = false,
is_ground_content = false,
groups = { fleshy=3, dig_immediate=3, flammable=2, moretrees_coconut=coco_group },
inventory_image = tile.."^[transformR180",
wield_image = tile.."^[transformR180",
sounds = xcompat.sounds.node_sound_default(),
drop = drop,
selection_box = {
type = "fixed",
fixed = {-0.3, -0.3, -0.3, 0.3, 0.3, 0.3}
},
on_timer = timerfn,
on_construct = constructfn,
}
minetest.register_node("moretrees:coconut"..suffix, coconutdef)
end
-- convert exisiting cocos palms. This is a bit tricky...
-- Try to make sure that this is indeed a generated tree, and not manually-placed trunks and/or coconuts
if moretrees.coconuts_convert_existing_palms then
local spec = {
name = "moretrees:convert_existing_cocos_palms_to_regrow_coconuts",
nodenames = "moretrees:coconut",
action = function(pos, node, active_object_count, active_object_count_wider)
local trunks
local cvtrunks
local leaves
local coconuts
-- One regular trunk must be adjacent to the coconut
trunks = minetest.find_nodes_in_area(
{x=pos.x-1, y=pos.y, z=pos.z-1},
{x=pos.x+1, y=pos.y, z=pos.z+1},
"moretrees:palm_trunk"
)
if #trunks ~= 1 then
return
end
local tpos = trunks[1]
-- 1 or 2 other trunks must be one level below to the trunk being converted.
trunks = minetest.find_nodes_in_area(
{x=tpos.x-1, y=tpos.y-1, z=tpos.z-1},
{x=tpos.x+1, y=tpos.y-1, z=tpos.z+1},
"moretrees:palm_trunk"
)
if #trunks < 1 or #trunks > 2 then
return
end
-- 1 or 2 other trunks must be two levels below to the trunk being converted.
trunks = minetest.find_nodes_in_area(
{x=tpos.x-1, y=tpos.y-2, z=tpos.z-1},
{x=tpos.x+1, y=tpos.y-2, z=tpos.z+1},
"moretrees:palm_trunk"
)
if #trunks < 1 or #trunks > 2 then
return
end
-- 1 or 2 trunks must at the level of the trunk being converted.
cvtrunks = minetest.find_nodes_in_area(
{x=tpos.x-1, y=tpos.y, z=tpos.z-1},
{x=tpos.x+1, y=tpos.y, z=tpos.z+1},
"moretrees:palm_trunk"
)
if #cvtrunks < 1 or #cvtrunks > 2 then
return
end
-- No trunks may be one level above the trunk being converted.
trunks = minetest.find_nodes_in_area(
{x=tpos.x-1, y=tpos.y+1, z=tpos.z-1},
{x=tpos.x+1, y=tpos.y+1, z=tpos.z+1},
"moretrees:palm_trunk"
)
if #trunks ~= 0 then
return
end
-- Leaves must be one level above the trunk being converted.
leaves = minetest.find_nodes_in_area(
{x=tpos.x-1, y=tpos.y+1, z=tpos.z-1},
{x=tpos.x+1, y=tpos.y+1, z=tpos.z+1},
"moretrees:palm_leaves"
)
if #leaves == 0 then
return
end
-- Leaves must be two levels above the trunk being converted.
leaves = minetest.find_nodes_in_area(
{x=tpos.x-1, y=tpos.y+2, z=tpos.z-1},
{x=tpos.x+1, y=tpos.y+2, z=tpos.z+1},
"moretrees:palm_leaves"
)
if #leaves == 0 then
return
end
-- No cocos fruit trunk may already be adjacent to the coconut
trunks = minetest.find_nodes_in_area(
{x=pos.x-1, y=pos.y, z=pos.z-1},
{x=pos.x+1, y=pos.y, z=pos.z+1},
"moretrees:palm_fruit_trunk"
)
if #trunks ~= 0 then
return
end
-- No cocos fruit trunk may be adjacent to or below the trunk being converted.
trunks = minetest.find_nodes_in_area(
{x=tpos.x-1, y=tpos.y-2, z=tpos.z-1},
{x=tpos.x+1, y=tpos.y, z=tpos.z+1},
"moretrees:palm_fruit_trunk"
)
if #trunks ~= 0 then
return
end
-- Convert trunk and all coconuts nearby. Maybe convert 2 trunks, just in case...
for _, tpos_1 in pairs(cvtrunks) do
minetest.swap_node(tpos_1, {name = "moretrees:palm_fruit_trunk"})
coconuts = minetest.find_nodes_in_area(
{x=tpos_1.x-1, y=tpos_1.y, z=tpos_1.z-1},
{x=tpos_1.x+1, y=tpos_1.y, z=tpos_1.z+1},
"moretrees:coconut"
)
for _, coconutpos in pairs(coconuts) do
minetest.swap_node(coconutpos, {name = "moretrees:coconut_3"})
end
end
end,
}
if minetest.register_lbm then
minetest.register_lbm(spec)
else
spec.interval = 3691
spec.chance = 10
minetest.register_abm(spec)
end
end
-- If regrowing was previously disabled, but is enabled now, make sure timers are started for existing coconuts
if moretrees.coconuts_regrow then
local spec = {
name = "moretrees:restart_coconut_regrow_timer",
nodenames = "group:moretrees_coconut",
action = function(pos, node, active_object_count, active_object_count_wider)
local timer = minetest.get_node_timer(pos)
if not timer:is_started() then
coconut_starttimer(pos)
else
local timeout = timer:get_timeout()
local elapsed = timer:get_elapsed()
if timeout - elapsed > moretrees.coconut_grow_interval * 4/3 then
coconut_starttimer(pos, math.random(moretrees.coconut_grow_interval * 4/3))
end
end
end,
}
if minetest.register_lbm then
minetest.register_lbm(spec)
else
spec.interval = 3659
spec.chance = 10
minetest.register_abm(spec)
end
end