Damage anvil after falling

Wuzzy 2018-02-05 19:58:31 +01:00
parent 32561ec658
commit 30be3e742f
3 changed files with 62 additions and 22 deletions

1
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_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_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. Use the `mcl_sounds` mod for the sounds.

@ -1,6 +1,14 @@
local dmes = minetest.get_modpath("mcl_death_messages") ~= nil local dmes = minetest.get_modpath("mcl_death_messages") ~= nil
local hung = minetest.get_modpath("mcl_hunger") ~= 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) local deal_falling_damage = function(self, dtime)
if minetest.get_item_group(self.node.name, "falling_node_damage") == 0 then if minetest.get_item_group(self.node.name, "falling_node_damage") == 0 then
return return
@ -10,6 +18,7 @@ local deal_falling_damage = function(self, dtime)
-- TODO: Support smashing other objects, too. -- TODO: Support smashing other objects, too.
local pos = self.object:get_pos() local pos = self.object:get_pos()
if not self._startpos then if not self._startpos then
-- Fallback
self._startpos = pos self._startpos = pos
end end
local objs = minetest.get_objects_inside_radius(pos, 1) local objs = minetest.get_objects_inside_radius(pos, 1)
@ -128,6 +137,10 @@ minetest.register_entity(":__builtin:falling_node", {
elseif staticdata ~= "" then elseif staticdata ~= "" then
self:set_node({name = staticdata}) self:set_node({name = staticdata})
end end
if not self._startpos then
self._startpos = self.object:get_pos()
end
self._startpos = vector.round(self._startpos)
end, end,
on_step = function(self, dtime) on_step = function(self, dtime)
@ -167,6 +180,9 @@ minetest.register_entity(":__builtin:falling_node", {
addlevel = bcd.leveled addlevel = bcd.leveled
end end
if minetest.add_node_level(bcp, addlevel) == 0 then 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) deal_falling_damage(self, dtime)
self.object:remove() self.object:remove()
return return
@ -190,6 +206,9 @@ minetest.register_entity(":__builtin:falling_node", {
end end
if minetest.registered_nodes[self.node.name] then if minetest.registered_nodes[self.node.name] then
minetest.add_node(np, self.node) 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 if self.meta then
local meta = minetest.get_meta(np) local meta = minetest.get_meta(np)
meta:from_table(self.meta) meta:from_table(self.meta)
@ -223,6 +242,9 @@ minetest.register_entity(":__builtin:falling_node", {
local npos3 = table.copy(npos) local npos3 = table.copy(npos)
npos3.y = npos3.y - 1 npos3.y = npos3.y - 1
minetest.add_node(npos3, self.node) 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) deal_falling_damage(self, dtime)
self.object:remove() self.object:remove()
minetest.check_for_falling(npos3) minetest.check_for_falling(npos3)

@ -204,33 +204,49 @@ local function drop_anvil_items(pos, meta)
end end
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. -- Destroy anvil when at highest damage level.
-- Returns true if anvil was destroyed. -- Returns true if anvil was destroyed.
local function damage_anvil(pos) 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) local r = math.random(1, 100)
-- 12% chance -- 12% chance
if r <= 12 then if r <= 12 then
local node = minetest.get_node(pos) return damage_anvil(pos)
local new else
if node.name == "mcl_anvils:anvil" then return false
minetest.swap_node(pos, {name="mcl_anvils:anvil_damage_1", param2=node.param2}) end
minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dig, {pos=pos, max_hear_distance=16}) end
return false
elseif node.name == "mcl_anvils:anvil_damage_1" then local function damage_anvil_by_falling(pos, distance)
minetest.swap_node(pos, {name="mcl_anvils:anvil_damage_2", param2=node.param2}) local chance
minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dig, {pos=pos, max_hear_distance=16}) local r = math.random(1, 100)
return false if distance > 1 then
elseif node.name == "mcl_anvils:anvil_damage_2" then if r <= (5*distance) then
-- Destroy anvil damage_anvil(pos)
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
end end
return false
end end
local anvildef = { local anvildef = {
@ -252,6 +268,7 @@ local anvildef = {
sounds = mcl_sounds.node_sound_metal_defaults(), sounds = mcl_sounds.node_sound_metal_defaults(),
_mcl_blast_resistance = 6000, _mcl_blast_resistance = 6000,
_mcl_hardness = 5, _mcl_hardness = 5,
_mcl_after_falling = damage_anvil_by_falling,
after_dig_node = function(pos, oldnode, oldmetadata, digger) after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
@ -301,7 +318,7 @@ local anvildef = {
update_anvil_slots(meta) update_anvil_slots(meta)
if from_list == "output" then if from_list == "output" then
local destroyed = damage_anvil(pos, player) local destroyed = damage_anvil_by_using(pos)
-- Close formspec if anvil was destroyed -- Close formspec if anvil was destroyed
if destroyed then if destroyed then
--[[ Closing the formspec w/ emptyformname is discouraged. But this is justified --[[ Closing the formspec w/ emptyformname is discouraged. But this is justified
@ -354,7 +371,7 @@ local anvildef = {
inv:set_stack("input", 2, input2) inv:set_stack("input", 2, input2)
end end
end end
local destroyed = damage_anvil(pos, player) local destroyed = damage_anvil_by_using(pos)
-- Close formspec if anvil was destroyed -- Close formspec if anvil was destroyed
if destroyed then if destroyed then
-- See above for justification. -- 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 + 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".. "• 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".. "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) local anvildef1 = table.copy(anvildef)
anvildef1.description = "Slightly Damaged Anvil" anvildef1.description = "Slightly Damaged Anvil"