Fix chorus fruit not working with damage on
[MineClone/MineClone2.git] / mods / ITEMS / mcl_end / chorus_plant.lua
blob882971f19f0ccd1cd55356c40342d0823300386a
1 -- Chorus plants
2 -- This includes chorus flowers, chorus plant stem nodes and chorus fruit
5 --- Plant parts ---
7 local MAX_FLOWER_AGE = 5 -- Maximum age of chorus flower before it dies
9 local chorus_flower_box = {
10 type = "fixed",
11 fixed = {
12 {-0.5, -0.375, -0.375, 0.5, 0.375, 0.375},
13 {-0.375, -0.375, 0.375, 0.375, 0.375, 0.5},
14 {-0.375, -0.375, -0.5, 0.375, 0.375, -0.375},
15 {-0.375, 0.375, -0.375, 0.375, 0.5, 0.375},
16 {-0.375, -0.5, -0.375, 0.375, -0.375, 0.375},
20 minetest.register_node("mcl_end:chorus_flower", {
21 description = "Chorus Flower",
22 _doc_items_longdesc = "A chorus flower is the living part of a chorus plant. It can grow into a tall chorus plant, step by step. When it grows, it may die on old age eventually. It also dies when it is unable to grow.",
23 _doc_items_usagehelp = "Place it and wait for it to grow. It can only be placed on top of end stone, on top of a chorus plant stem, or at the side of exactly a chorus plant stem.",
24 tiles = {
25 "mcl_end_chorus_flower.png",
26 "mcl_end_chorus_flower.png",
27 "mcl_end_chorus_flower.png",
28 "mcl_end_chorus_flower.png",
29 "mcl_end_chorus_flower.png",
30 "mcl_end_chorus_flower.png",
32 drawtype = "nodebox",
33 paramtype = "light",
34 sunlight_propagates = true,
35 node_box = chorus_flower_box,
36 selection_box = { type = "regular" },
37 sounds = mcl_sounds.node_sound_wood_defaults(),
38 groups = {handy=1,axey=1, deco_block = 1, dig_by_piston = 1, destroy_by_lava_flow = 1,},
40 node_placement_prediction = "",
41 on_place = function(itemstack, placer, pointed_thing)
42 local node_under = minetest.get_node(pointed_thing.under)
43 local node_above = minetest.get_node(pointed_thing.above)
44 if placer and not placer:get_player_control().sneak then
45 -- Use pointed node's on_rightclick function first, if present
46 if minetest.registered_nodes[node_under.name] and minetest.registered_nodes[node_under.name].on_rightclick then
47 return minetest.registered_nodes[node_under.name].on_rightclick(pointed_thing.under, node_under, placer, itemstack) or itemstack
48 end
49 end
51 --[[ Part 1: Check placement rules. Placement is legal is one of the following
52 conditions is met:
53 1) On top of end stone or chorus plant
54 2) On top of air and horizontally adjacent to exactly 1 chorus plant ]]
55 local pos
56 if minetest.registered_nodes[node_under.name].buildable_to then
57 pos = pointed_thing.under
58 else
59 pos = pointed_thing.above
60 end
63 local below = {x=pos.x, y=pos.y-1, z=pos.z}
64 local node_below = minetest.get_node(below)
65 local plant_ok = false
66 -- Condition 1
67 if node_below.name == "mcl_end:chorus_plant" or node_below.name == "mcl_end:end_stone" then
68 plant_ok = true
69 -- Condition 2
70 elseif node_below.name == "air" then
71 local around = {
72 { x= 1, y=0, z= 0 },
73 { x=-1, y=0, z= 0 },
74 { x= 0, y=0, z= 1 },
75 { x= 0, y=0, z=-1 },
77 local around_count = 0
78 for a=1, #around do
79 local pos_side = vector.add(pos, around[a])
80 local node_side = minetest.get_node(pos_side)
81 if node_side.name == "mcl_end:chorus_plant" then
82 around_count = around_count + 1
83 if around_count > 1 then
84 break
85 end
86 end
87 end
88 if around_count == 1 then
89 plant_ok = true
90 end
91 end
92 if plant_ok then
93 -- Placement OK! Proceed normally
94 minetest.sound_play(mcl_sounds.node_sound_wood_defaults().place, {pos = pos})
95 return minetest.item_place_node(itemstack, placer, pointed_thing)
96 else
97 return itemstack
98 end
99 end,
100 _mcl_blast_resistance = 2,
101 _mcl_hardness = 0.4,
104 minetest.register_node("mcl_end:chorus_flower_dead", {
105 description = "Dead Chorus Flower",
106 _doc_items_longdesc = "This is a part of a chorus plant. It doesn't grow. Chorus flowers die of old age or when they are unable to grow. A dead chorus flower can be harvested to obtain a fresh chorus flower which is able to grow again.",
107 tiles = {
108 "mcl_end_chorus_flower_dead.png",
109 "mcl_end_chorus_flower_dead.png",
110 "mcl_end_chorus_flower_dead.png",
111 "mcl_end_chorus_flower_dead.png",
112 "mcl_end_chorus_flower_dead.png",
113 "mcl_end_chorus_flower_dead.png",
115 drawtype = "nodebox",
116 paramtype = "light",
117 sunlight_propagates = true,
118 node_box = chorus_flower_box,
119 selection_box = { type = "regular" },
120 sounds = mcl_sounds.node_sound_wood_defaults(),
121 drop = "mcl_end:chorus_flower",
122 groups = {handy=1,axey=1, deco_block = 1, dig_by_piston = 1, destroy_by_lava_flow = 1,},
123 _mcl_blast_resistance = 2,
124 _mcl_hardness = 0.4,
127 minetest.register_node("mcl_end:chorus_plant", {
128 description = "Chorus Plant Stem",
129 _doc_items_longdesc = "A chorus plant stem is the part of a chorus plant which holds the whole plant together. It needs end stone as its soil. Stems are grown from chorus flowers.",
130 tiles = {
131 "mcl_end_chorus_plant.png",
132 "mcl_end_chorus_plant.png",
133 "mcl_end_chorus_plant.png",
134 "mcl_end_chorus_plant.png",
135 "mcl_end_chorus_plant.png",
136 "mcl_end_chorus_plant.png",
138 drawtype = "nodebox",
139 paramtype = "light",
140 sunlight_propagates = true,
141 node_box = {
142 type = "connected",
143 fixed = { -0.25, -0.25, -0.25, 0.25, 0.25, 0.25 }, -- Core
144 connect_top = { -0.1875, 0.25, -0.1875, 0.1875, 0.5, 0.1875 },
145 connect_left = { -0.5, -0.1875, -0.1875, -0.25, 0.1875, 0.1875 },
146 connect_right = { 0.25, -0.1875, -0.1875, 0.5, 0.1875, 0.1875 },
147 connect_bottom = { -0.1875, -0.5, -0.25, 0.1875, -0.25, 0.25 },
148 connect_front = { -0.1875, -0.1875, -0.5, 0.1875, 0.1875, -0.25 },
149 connect_back = { -0.1875, -0.1875, 0.25, 0.1875, 0.1875, 0.5 },
151 connect_sides = { "top", "bottom", "front", "back", "left", "right" },
152 connects_to = {"mcl_end:chorus_plant", "mcl_end:chorus_flower", "mcl_end:chorus_flower_dead", "mcl_end:end_stone"},
153 sounds = mcl_sounds.node_sound_wood_defaults(),
154 drop = {
155 items = {
156 { items = { "mcl_end:chorus_fruit"}, rarity = 2 },
159 groups = {handy=1,axey=1, not_in_creative_inventory = 1, dig_by_piston = 1, destroy_by_lava_flow = 1 },
160 _mcl_blast_resistance = 2,
161 _mcl_hardness = 0.4,
165 --- ABM ---
166 minetest.register_abm({
167 label = "Chorus plant growth",
168 nodenames = { "mcl_end:chorus_flower" },
169 interval = 35.0,
170 chance = 4.0,
171 action = function(pos, node, active_object_count, active_object_count_wider)
172 local above = { x = pos.x, y = pos.y + 1, z = pos.z }
173 local node_above = minetest.get_node(above)
174 local around = {
175 { x=-1, y=0, z= 0 },
176 { x= 1, y=0, z= 0 },
177 { x= 0, y=0, z=-1 },
178 { x= 0, y=0, z= 1 },
180 local air_around = true
181 for a=1, #around do
182 if minetest.get_node(vector.add(above, around[a])).name ~= "air" then
183 air_around = false
184 break
187 local grown = false
188 if node_above.name == "air" and air_around then
189 local branching = false
190 local h = 0
191 for y=1, 4 do
192 local checkpos = {x=pos.x, y=pos.y-y, z=pos.z}
193 local node = minetest.get_node(checkpos)
194 if node.name == "mcl_end:chorus_plant" then
195 h = y
196 if not branching then
197 for a=1, #around do
198 local node_side = minetest.get_node(vector.add(checkpos, around[a]))
199 if node_side.name == "mcl_end:chorus_plant" then
200 branching = true
204 else
205 break
209 local grow_chance
210 if h <= 1 then
211 grow_chance = 100
212 elseif h == 2 and branching == false then
213 grow_chance = 60
214 elseif h == 2 and branching == true then
215 grow_chance = 50
216 elseif h == 3 and branching == false then
217 grow_chance = 40
218 elseif h == 3 and branching == true then
219 grow_chance = 25
220 elseif h == 4 and branching == false then
221 grow_chance = 20
224 if grow_chance then
225 local new_flowers = {}
226 local r = math.random(1, 100)
227 local age = node.param2
228 if r <= grow_chance then
229 table.insert(new_flowers, above)
230 else
231 age = age + 1
232 local branches
233 if branching == false then
234 branches = math.random(1, 4)
235 elseif branching == true then
236 branches = math.random(0, 3)
238 local branch_grown = false
239 for b=1, branches do
240 local next_branch = math.random(1, #around)
241 local branch = vector.add(pos, around[next_branch])
242 local below_branch = vector.add(branch, {x=0,y=-1,z=0})
243 if minetest.get_node(below_branch).name == "air" then
244 table.insert(new_flowers, branch)
249 for _, f in ipairs(new_flowers) do
250 if age >= MAX_FLOWER_AGE then
251 minetest.set_node(f, {name="mcl_end:chorus_flower_dead"})
252 grown = true
253 else
254 minetest.set_node(f, {name="mcl_end:chorus_flower", param2 = age})
255 grown = true
258 if #new_flowers >= 1 then
259 minetest.set_node(pos, {name="mcl_end:chorus_plant"})
260 grown = true
264 if not grown then
265 minetest.set_node(pos, {name = "mcl_end:chorus_flower_dead"})
267 end,
270 --- Chorus fruit ---
272 -- Attempt to randomly teleport the player within a 8×8×8 box around. Rules:
273 -- * Not in solid blocks.
274 -- * Not in liquids.
275 -- * Always on top of a solid block
276 -- * Maximum attempts: 16
278 -- Returns true on success.
279 local random_teleport = function(player)
280 local pos = player:get_pos()
281 -- 16 attempts to find a suitable position
282 for a=1, 16 do
283 -- Teleportation box
284 local x,y,z
285 x = math.random(pos.x-8, pos.x+8)
286 y = math.random(math.ceil(pos.y)-8, math.ceil(pos.y)+8)
287 z = math.random(pos.z-8, pos.z+8)
288 local node_cache = {}
289 local ground_level = false
290 -- Scan nodes from selected position until we hit ground
291 for t=0, 16 do
292 local tpos = {x=x, y=y-t, z=z}
293 local tnode = minetest.get_node(tpos)
294 if tnode.name == "mcl_core:void" then
295 break
297 local tdef = minetest.registered_nodes[tnode.name]
298 table.insert(node_cache, {pos=tpos, node=tnode})
299 if tdef.walkable then
300 ground_level = true
301 break
304 -- Ground found? Then let's check if the player has enough room
305 if ground_level and #node_cache >= 1 then
306 local streak = 0
307 for c=#node_cache, 1, -1 do
308 local tpos = node_cache[c].pos
309 local tnode = node_cache[c].node
310 local tdef = minetest.registered_nodes[tnode.name]
311 -- Player needs a space of 2 nodes on top of each other
312 if not tdef.walkable and tdef.liquidtype == "none" then
313 streak = streak + 1
314 else
315 streak = 0
317 if streak >= 2 then
318 -- JACKPOT! Now we can teleport.
319 local goal = {x=tpos.x, y=tpos.y-1.5, z=tpos.z}
320 player:set_pos(goal)
321 minetest.sound_play({name="mcl_end_teleport", gain=0.8}, {pos=goal, max_hear_distance=16})
322 return true
327 return false
330 -- Randomly teleport player and update hunger
331 local eat_chorus_fruit = function(itemstack, player, pointed_thing)
332 if player and pointed_thing and pointed_thing.type == "node" and not player:get_player_control().sneak then
333 local node_under = minetest.get_node(pointed_thing.under)
334 -- Use pointed node's on_rightclick function first, if present
335 if minetest.registered_nodes[node_under.name] and minetest.registered_nodes[node_under.name].on_rightclick then
336 return minetest.registered_nodes[node_under.name].on_rightclick(pointed_thing.under, node_under, placer, itemstack) or itemstack
339 local count = itemstack:get_count()
340 local new_itemstack = minetest.do_item_eat(0, nil, itemstack, player, pointed_thing)
341 local new_count = new_itemstack:get_count()
342 if count ~= new_count or new_itemstack:get_name() ~= "mcl_end:chorus_fruit" then
343 random_teleport(player)
345 return new_itemstack
348 minetest.register_craftitem("mcl_end:chorus_fruit", {
349 description = "Chorus Fruit",
350 _doc_items_longdesc = "A chorus fruit is an edible fruit from the chorus plant which is home to the End. Eating it teleports you to the top of a random solid block nearby, provided you won't end up inside a liquid or some solid blocks. Teleportation might fail if there are very few or no places to teleport to.",
351 wield_image = "mcl_end_chorus_fruit.png",
352 inventory_image = "mcl_end_chorus_fruit.png",
353 on_place = eat_chorus_fruit,
354 on_secondary_use = eat_chorus_fruit,
355 groups = { food = 2, eatable = 4, can_eat_when_full = 1 },
356 _mcl_saturation = 2.4,
357 stack_max = 64,
360 minetest.register_craftitem("mcl_end:chorus_fruit_popped", {
361 description = "Popped Chorus Fruit",
362 _doc_items_longdesc = doc.sub.items.temp.craftitem,
363 wield_image = "mcl_end_chorus_fruit_popped.png",
364 inventory_image = "mcl_end_chorus_fruit_popped.png",
365 groups = { craftitem = 1 },
366 stack_max = 64,
369 --- Crafting ---
370 minetest.register_craft({
371 type = "cooking",
372 output = "mcl_end:chorus_fruit_popped",
373 recipe = "mcl_end:chorus_fruit",
374 cooktime = 10,