diff --git a/API.md b/API.md index 0d6c9758..c4e3b229 100644 --- a/API.md +++ b/API.md @@ -21,6 +21,7 @@ All nodes can have these fields: * `_mcl_hardness`: Hardness of the block, ranges from 0 to infinity (represented by -1). Determines digging times. Default: 0 * `_mcl_blast_resistance`: How well this block blocks and resists explosions. Default: 0 +* `_mcl_after_falling(pos)`: Called after a falling node finished falling and turned into a node. Use the `mcl_sounds` mod for the sounds. diff --git a/mods/ENTITIES/mcl_falling_nodes/init.lua b/mods/ENTITIES/mcl_falling_nodes/init.lua index bcfdb381..92cca703 100644 --- a/mods/ENTITIES/mcl_falling_nodes/init.lua +++ b/mods/ENTITIES/mcl_falling_nodes/init.lua @@ -1,6 +1,14 @@ local dmes = minetest.get_modpath("mcl_death_messages") ~= nil local hung = minetest.get_modpath("mcl_hunger") ~= nil +local get_falling_depth = function(self) + if not self._startpos then + -- Fallback + self._startpos = self.object:get_pos() + end + return self._startpos.y - vector.round(self.object:get_pos()).y +end + local deal_falling_damage = function(self, dtime) if minetest.get_item_group(self.node.name, "falling_node_damage") == 0 then return @@ -10,6 +18,7 @@ local deal_falling_damage = function(self, dtime) -- TODO: Support smashing other objects, too. local pos = self.object:get_pos() if not self._startpos then + -- Fallback self._startpos = pos end local objs = minetest.get_objects_inside_radius(pos, 1) @@ -128,6 +137,10 @@ minetest.register_entity(":__builtin:falling_node", { elseif staticdata ~= "" then self:set_node({name = staticdata}) end + if not self._startpos then + self._startpos = self.object:get_pos() + end + self._startpos = vector.round(self._startpos) end, on_step = function(self, dtime) @@ -167,6 +180,9 @@ minetest.register_entity(":__builtin:falling_node", { addlevel = bcd.leveled end if minetest.add_node_level(bcp, addlevel) == 0 then + if minetest.registered_nodes[self.node.name]._mcl_after_falling then + minetest.registered_nodes[self.node.name]._mcl_after_falling(bcp, get_falling_depth(self)) + end deal_falling_damage(self, dtime) self.object:remove() return @@ -190,6 +206,9 @@ minetest.register_entity(":__builtin:falling_node", { end if minetest.registered_nodes[self.node.name] then minetest.add_node(np, self.node) + if minetest.registered_nodes[self.node.name]._mcl_after_falling then + minetest.registered_nodes[self.node.name]._mcl_after_falling(np, get_falling_depth(self)) + end if self.meta then local meta = minetest.get_meta(np) meta:from_table(self.meta) @@ -223,6 +242,9 @@ minetest.register_entity(":__builtin:falling_node", { local npos3 = table.copy(npos) npos3.y = npos3.y - 1 minetest.add_node(npos3, self.node) + if minetest.registered_nodes[self.node.name]._mcl_after_falling then + minetest.registered_nodes[self.node.name]._mcl_after_falling(npos3, get_falling_depth(self)) + end deal_falling_damage(self, dtime) self.object:remove() minetest.check_for_falling(npos3) diff --git a/mods/ITEMS/mcl_anvils/init.lua b/mods/ITEMS/mcl_anvils/init.lua index 465a5009..f27ee247 100644 --- a/mods/ITEMS/mcl_anvils/init.lua +++ b/mods/ITEMS/mcl_anvils/init.lua @@ -204,33 +204,49 @@ local function drop_anvil_items(pos, meta) end end --- Roll a virtual dice and with a low chance, damage the anvil by 1 level. +-- Damage the anvil by 1 level. -- Destroy anvil when at highest damage level. -- Returns true if anvil was destroyed. local function damage_anvil(pos) + local node = minetest.get_node(pos) + local new + if node.name == "mcl_anvils:anvil" then + minetest.swap_node(pos, {name="mcl_anvils:anvil_damage_1", param2=node.param2}) + minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dig, {pos=pos, max_hear_distance=16}) + return false + elseif node.name == "mcl_anvils:anvil_damage_1" then + minetest.swap_node(pos, {name="mcl_anvils:anvil_damage_2", param2=node.param2}) + minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dig, {pos=pos, max_hear_distance=16}) + return false + elseif node.name == "mcl_anvils:anvil_damage_2" then + -- Destroy anvil + local meta = minetest.get_meta(pos) + drop_anvil_items(pos, meta) + minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dug, {pos=pos, max_hear_distance=16}) + minetest.remove_node(pos) + return true + end +end + +-- Roll a virtual dice and damage anvil at a low chance. +local function damage_anvil_by_using(pos) local r = math.random(1, 100) -- 12% chance if r <= 12 then - local node = minetest.get_node(pos) - local new - if node.name == "mcl_anvils:anvil" then - minetest.swap_node(pos, {name="mcl_anvils:anvil_damage_1", param2=node.param2}) - minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dig, {pos=pos, max_hear_distance=16}) - return false - elseif node.name == "mcl_anvils:anvil_damage_1" then - minetest.swap_node(pos, {name="mcl_anvils:anvil_damage_2", param2=node.param2}) - minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dig, {pos=pos, max_hear_distance=16}) - return false - elseif node.name == "mcl_anvils:anvil_damage_2" then - -- Destroy anvil - local meta = minetest.get_meta(pos) - drop_anvil_items(pos, meta) - minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dug, {pos=pos, max_hear_distance=16}) - minetest.remove_node(pos) - return true + return damage_anvil(pos) + else + return false + end +end + +local function damage_anvil_by_falling(pos, distance) + local chance + local r = math.random(1, 100) + if distance > 1 then + if r <= (5*distance) then + damage_anvil(pos) end end - return false end local anvildef = { @@ -252,6 +268,7 @@ local anvildef = { sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6000, _mcl_hardness = 5, + _mcl_after_falling = damage_anvil_by_falling, after_dig_node = function(pos, oldnode, oldmetadata, digger) local meta = minetest.get_meta(pos) @@ -301,7 +318,7 @@ local anvildef = { update_anvil_slots(meta) if from_list == "output" then - local destroyed = damage_anvil(pos, player) + local destroyed = damage_anvil_by_using(pos) -- Close formspec if anvil was destroyed if destroyed then --[[ Closing the formspec w/ emptyformname is discouraged. But this is justified @@ -354,7 +371,7 @@ local anvildef = { inv:set_stack("input", 2, input2) end end - local destroyed = damage_anvil(pos, player) + local destroyed = damage_anvil_by_using(pos) -- Close formspec if anvil was destroyed if destroyed then -- See above for justification. @@ -404,7 +421,7 @@ anvildef0._doc_items_usagehelp = "• Tool + Tool: Place two tools of the same type in the input slots. The “health” of the repaired tool is the sum of the “health” of both input tools, plus a 12% bonus.".."\n".. "• Tool + Material: Some tools can also be repaired by combining them with an item that it's made of. For example, iron pickaxes can be repaired with iron ingots. This repairs the tool by 25%.".."\n".. "Armor counts as a tool. It is possible to repair and rename a tool in a single step.".."\n\n".. -"The anvil has limited durability and 3 damage levels: undamaged, slightly damaged and very damaged. Each time you repair or rename something, there is a 12% chance the anvil gets damaged. If a very damaged anvil is damaged again, it is destroyed." +"The anvil has limited durability and 3 damage levels: undamaged, slightly damaged and very damaged. Each time you repair or rename something, there is a 12% chance the anvil gets damaged. Anvils also have a chance of being damaged when they fall by more than 1 block. If a very damaged anvil is damaged again, it is destroyed." local anvildef1 = table.copy(anvildef) anvildef1.description = "Slightly Damaged Anvil"