Merge branch 'master' into death_msg
@ -743,6 +743,7 @@ minetest.register_node(
|
||||
end
|
||||
return true
|
||||
end,
|
||||
_rp_blast_resistance = 1,
|
||||
|
||||
-- Drop is handled in on_dig
|
||||
drop = "",
|
||||
|
@ -112,6 +112,7 @@ local bookshelf_def = {
|
||||
write_name = function(pos, text)
|
||||
-- TODO: Bring back container naming
|
||||
end,
|
||||
_rp_blast_resistance = 2,
|
||||
}
|
||||
minetest.register_node(":rp_default:bookshelf", bookshelf_def)
|
||||
|
||||
|
@ -23,6 +23,9 @@ minetest.register_chatcommand("hp", {
|
||||
return false, S("Player @1 does not exist.", targetname)
|
||||
end
|
||||
hp = minetest.parse_relative_number(hp, target:get_hp())
|
||||
if not hp then
|
||||
return false, S("Invalid health!")
|
||||
end
|
||||
if hp < 0 then
|
||||
hp = 0
|
||||
end
|
||||
|
@ -7,6 +7,7 @@ minetest.register_node("rp_decor:barrel", {
|
||||
on_place = minetest.rotate_node,
|
||||
groups = { choppy = 2, level = -1, creative_decoblock = 1, flammable = 2 },
|
||||
sounds = rp_sounds.node_sound_planks_defaults(),
|
||||
_rp_blast_resistance = 1,
|
||||
})
|
||||
|
||||
crafting.register_craft({
|
||||
|
@ -56,6 +56,7 @@ minetest.register_node(
|
||||
end
|
||||
]]
|
||||
end,
|
||||
_rp_blast_resistance = 2,
|
||||
})
|
||||
minetest.register_node(
|
||||
"rp_default:chest_painted",
|
||||
@ -82,6 +83,7 @@ minetest.register_node(
|
||||
item_drop.drop_items_from_container(pos, {"main"})
|
||||
end,
|
||||
drop = "rp_default:chest",
|
||||
_rp_blast_resistance = 2,
|
||||
})
|
||||
|
||||
local xstart = rp_formspec.default.start_point.x
|
||||
|
@ -92,6 +92,7 @@ register_fence("rp_default:fence", {
|
||||
wield_image = "default_fence.png",
|
||||
groups = {choppy = 3, oddly_breakable_by_hand = 2, level = -2, fence = 1},
|
||||
sounds = sounds_wood_fence,
|
||||
_rp_blast_resistance = 0.5,
|
||||
})
|
||||
register_fence("rp_default:fence_oak", {
|
||||
description = S("Oak Fence"),
|
||||
@ -104,6 +105,7 @@ register_fence("rp_default:fence_oak", {
|
||||
wield_image = "default_fence_oak.png",
|
||||
groups = {choppy = 3, oddly_breakable_by_hand = 2, level = -2, fence = 1},
|
||||
sounds = sounds_wood_fence,
|
||||
_rp_blast_resistance = 0.5,
|
||||
})
|
||||
register_fence("rp_default:fence_birch", {
|
||||
description = S("Birch Fence"),
|
||||
@ -116,4 +118,5 @@ register_fence("rp_default:fence_birch", {
|
||||
wield_image = "default_fence_birch.png",
|
||||
groups = {choppy = 3, oddly_breakable_by_hand = 2, level = -2, fence = 1},
|
||||
sounds = sounds_wood_fence,
|
||||
_rp_blast_resistance = 0.5,
|
||||
})
|
||||
|
@ -192,6 +192,7 @@ minetest.register_node(
|
||||
allow_metadata_inventory_take = check_take,
|
||||
after_dig_node = after_dig_node,
|
||||
on_blast = on_blast,
|
||||
_rp_blast_resistance = 2,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -227,6 +228,7 @@ minetest.register_node(
|
||||
allow_metadata_inventory_take = check_take,
|
||||
after_dig_node = after_dig_node,
|
||||
on_blast = on_blast,
|
||||
_rp_blast_resistance = 2,
|
||||
})
|
||||
|
||||
local function swap_node(pos, name)
|
||||
|
@ -15,6 +15,7 @@ minetest.register_node(
|
||||
groups = {cracky = 2, stone = 1, ore = 1},
|
||||
drop = "rp_default:lump_sulfur",
|
||||
sounds = rp_sounds.node_sound_stone_defaults(),
|
||||
_rp_blast_resistance = 1,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -25,6 +26,7 @@ minetest.register_node(
|
||||
groups = {cracky = 2, stone = 1, ore = 1},
|
||||
drop = "rp_default:sheet_graphite",
|
||||
sounds = rp_sounds.node_sound_stone_defaults(),
|
||||
_rp_blast_resistance = 1,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -35,6 +37,7 @@ minetest.register_node(
|
||||
groups = {cracky = 2, stone = 1, ore = 1},
|
||||
drop = "rp_default:lump_coal",
|
||||
sounds = rp_sounds.node_sound_stone_defaults(),
|
||||
_rp_blast_resistance = 1,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -45,6 +48,7 @@ minetest.register_node(
|
||||
groups = {cracky = 2, stone = 1, magnetic = 1, ore = 1},
|
||||
drop = "rp_default:lump_iron",
|
||||
sounds = rp_sounds.node_sound_stone_defaults(),
|
||||
_rp_blast_resistance = 1,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -55,6 +59,7 @@ minetest.register_node(
|
||||
groups = {cracky = 1, stone = 1, ore = 1},
|
||||
drop = "rp_default:lump_tin",
|
||||
sounds = rp_sounds.node_sound_stone_defaults(),
|
||||
_rp_blast_resistance = 1,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -65,6 +70,7 @@ minetest.register_node(
|
||||
groups = {cracky = 1, stone = 1, ore = 1},
|
||||
drop = "rp_default:lump_copper",
|
||||
sounds = rp_sounds.node_sound_stone_defaults(),
|
||||
_rp_blast_resistance = 1,
|
||||
})
|
||||
|
||||
-- Stonelike
|
||||
@ -77,6 +83,7 @@ minetest.register_node(
|
||||
groups = {cracky = 2, stone = 1},
|
||||
drop = "rp_default:cobble",
|
||||
sounds = rp_sounds.node_sound_stone_defaults(),
|
||||
_rp_blast_resistance = 1,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -88,6 +95,7 @@ minetest.register_node(
|
||||
groups = {cracky = 3, stone = 1},
|
||||
sounds = rp_sounds.node_sound_stone_defaults(),
|
||||
is_ground_content = false,
|
||||
_rp_blast_resistance = 2,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -98,6 +106,7 @@ minetest.register_node(
|
||||
is_ground_content = false,
|
||||
groups = {cracky = 1, stone = 1},
|
||||
sounds = rp_sounds.node_sound_stone_defaults(),
|
||||
_rp_blast_resistance = 6,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -118,6 +127,7 @@ minetest.register_node(
|
||||
tiles = {"default_block_coal.png"},
|
||||
groups = {cracky = 3},
|
||||
sounds = rp_sounds.node_sound_coal_defaults(),
|
||||
_rp_blast_resistance = 1,
|
||||
})
|
||||
|
||||
local make_metal_sounds = function(pitch)
|
||||
@ -145,6 +155,7 @@ minetest.register_node(
|
||||
groups = {cracky = 2, magnetic = 1},
|
||||
sounds = make_metal_sounds(default.METAL_PITCH_WROUGHT_IRON),
|
||||
is_ground_content = false,
|
||||
_rp_blast_resistance = 8,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -155,6 +166,7 @@ minetest.register_node(
|
||||
groups = {cracky = 2},
|
||||
sounds = make_metal_sounds(default.METAL_PITCH_STEEL),
|
||||
is_ground_content = false,
|
||||
_rp_blast_resistance = 9,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -165,6 +177,7 @@ minetest.register_node(
|
||||
groups = {cracky = 1},
|
||||
sounds = make_metal_sounds(default.METAL_PITCH_CARBON_STEEL),
|
||||
is_ground_content = false,
|
||||
_rp_blast_resistance = 9.25,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -175,6 +188,7 @@ minetest.register_node(
|
||||
groups = {cracky = 1},
|
||||
sounds = make_metal_sounds(default.METAL_PITCH_BRONZE),
|
||||
is_ground_content = false,
|
||||
_rp_blast_resistance = 9.5,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -185,6 +199,7 @@ minetest.register_node(
|
||||
groups = {cracky = 2},
|
||||
sounds = make_metal_sounds(default.METAL_PITCH_COPPER),
|
||||
is_ground_content = false,
|
||||
_rp_blast_resistance = 7,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -195,6 +210,7 @@ minetest.register_node(
|
||||
groups = {cracky = 2},
|
||||
sounds = make_metal_sounds(default.METAL_PITCH_TIN),
|
||||
is_ground_content = false,
|
||||
_rp_blast_resistance = 8.5,
|
||||
})
|
||||
|
||||
-- Soil
|
||||
@ -450,6 +466,7 @@ minetest.register_node(
|
||||
is_ground_content = false,
|
||||
groups = {cracky = 2, paintable = 2},
|
||||
sounds = rp_sounds.node_sound_stone_defaults(),
|
||||
_rp_blast_resistance = 2,
|
||||
})
|
||||
minetest.register_node(
|
||||
"rp_default:brick_painted",
|
||||
@ -464,6 +481,7 @@ minetest.register_node(
|
||||
paramtype2 = "color",
|
||||
palette = "rp_paint_palette_256.png",
|
||||
drop = "rp_default:brick",
|
||||
_rp_blast_resistance = 2,
|
||||
})
|
||||
|
||||
-- Sand
|
||||
@ -489,6 +507,7 @@ minetest.register_node(
|
||||
dug = {name="rp_sounds_dug_stone", gain=0.9, pitch=1.4},
|
||||
dig = {name="rp_sounds_dig_stone", gain=0.5, pitch=1.4},
|
||||
}),
|
||||
_rp_blast_resistance = 0.5,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -502,6 +521,7 @@ minetest.register_node(
|
||||
dug = {name="rp_sounds_dug_stone", gain=0.9, pitch=1.2},
|
||||
dig = {name="rp_sounds_dig_stone", gain=0.5, pitch=1.2},
|
||||
}),
|
||||
_rp_blast_resistance = 1,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -515,6 +535,7 @@ minetest.register_node(
|
||||
dug = {name="rp_sounds_dug_stone", gain=0.9, pitch=1.2},
|
||||
dig = {name="rp_sounds_dig_stone", gain=0.5, pitch=1.2},
|
||||
}),
|
||||
_rp_blast_resistance = 6,
|
||||
})
|
||||
|
||||
-- Glass
|
||||
@ -532,6 +553,7 @@ minetest.register_node(
|
||||
is_ground_content = false,
|
||||
sounds = rp_sounds.node_sound_glass_defaults(),
|
||||
drop = "rp_default:glass",
|
||||
_rp_blast_resistance = 0.2,
|
||||
})
|
||||
minetest.register_node(
|
||||
"rp_default:glass_painted",
|
||||
@ -550,6 +572,7 @@ minetest.register_node(
|
||||
is_ground_content = false,
|
||||
sounds = rp_sounds.node_sound_glass_defaults(),
|
||||
drop = "rp_default:glass",
|
||||
_rp_blast_resistance = 0.2,
|
||||
})
|
||||
|
||||
|
||||
@ -564,6 +587,7 @@ minetest.register_node(
|
||||
groups = {planks = 1, wood = 1, choppy = 3, oddly_breakable_by_hand = 3, paintable = 2},
|
||||
is_ground_content = false,
|
||||
sounds = rp_sounds.node_sound_planks_defaults(),
|
||||
_rp_blast_resistance = 0.5,
|
||||
})
|
||||
minetest.register_node(
|
||||
"rp_default:planks_painted",
|
||||
@ -579,6 +603,7 @@ minetest.register_node(
|
||||
palette = "rp_paint_palette_256.png",
|
||||
drop = "rp_default:planks",
|
||||
paramtype2 = "color",
|
||||
_rp_blast_resistance = 0.5,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -589,6 +614,7 @@ minetest.register_node(
|
||||
groups = {planks = 1, wood = 1, choppy = 3, oddly_breakable_by_hand = 3, paintable = 2},
|
||||
is_ground_content = false,
|
||||
sounds = rp_sounds.node_sound_planks_defaults(),
|
||||
_rp_blast_resistance = 0.5,
|
||||
})
|
||||
minetest.register_node(
|
||||
"rp_default:planks_oak_painted",
|
||||
@ -603,6 +629,7 @@ minetest.register_node(
|
||||
palette = "rp_paint_palette_256.png",
|
||||
drop = "rp_default:planks_oak",
|
||||
paramtype2 = "color",
|
||||
_rp_blast_resistance = 0.5,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -613,6 +640,7 @@ minetest.register_node(
|
||||
groups = {planks = 1, wood = 1, choppy = 3, oddly_breakable_by_hand = 3, paintable=2},
|
||||
is_ground_content = false,
|
||||
sounds = rp_sounds.node_sound_planks_defaults(),
|
||||
_rp_blast_resistance = 0.5,
|
||||
})
|
||||
minetest.register_node(
|
||||
"rp_default:planks_birch_painted",
|
||||
@ -627,6 +655,7 @@ minetest.register_node(
|
||||
palette = "rp_paint_palette_256.png",
|
||||
drop = "rp_default:planks_birch",
|
||||
paramtype2 = "color",
|
||||
_rp_blast_resistance = 0.5,
|
||||
})
|
||||
|
||||
|
||||
@ -641,6 +670,7 @@ minetest.register_node(
|
||||
groups = {wood = 1, choppy = 2, oddly_breakable_by_hand = 1, paintable = 2},
|
||||
is_ground_content = false,
|
||||
sounds = rp_sounds.node_sound_planks_defaults(),
|
||||
_rp_blast_resistance = 0.75,
|
||||
})
|
||||
minetest.register_node(
|
||||
"rp_default:frame_painted",
|
||||
@ -655,6 +685,7 @@ minetest.register_node(
|
||||
is_ground_content = false,
|
||||
sounds = rp_sounds.node_sound_planks_defaults(),
|
||||
drop = "rp_default:frame",
|
||||
_rp_blast_resistance = 0.75,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -665,6 +696,7 @@ minetest.register_node(
|
||||
groups = {wood = 1, choppy = 1, paintable = 2},
|
||||
is_ground_content = false,
|
||||
sounds = rp_sounds.node_sound_planks_defaults(),
|
||||
_rp_blast_resistance = 5,
|
||||
})
|
||||
minetest.register_node(
|
||||
"rp_default:reinforced_frame_painted",
|
||||
@ -678,6 +710,7 @@ minetest.register_node(
|
||||
is_ground_content = false,
|
||||
sounds = rp_sounds.node_sound_planks_defaults(),
|
||||
drop = "rp_default:reinforced_frame",
|
||||
_rp_blast_resistance = 5,
|
||||
})
|
||||
|
||||
|
||||
@ -694,6 +727,7 @@ minetest.register_node(
|
||||
groups = {snappy=2, fall_damage_add_percent=-10},
|
||||
is_ground_content = false,
|
||||
sounds = rp_sounds.node_sound_grass_defaults(),
|
||||
_rp_blast_resistance = 0.5,
|
||||
})
|
||||
minetest.register_node(
|
||||
"rp_default:dried_reed_block",
|
||||
@ -707,6 +741,7 @@ minetest.register_node(
|
||||
groups = {snappy=2, fall_damage_add_percent=-15},
|
||||
is_ground_content = false,
|
||||
sounds = rp_sounds.node_sound_straw_defaults(),
|
||||
_rp_blast_resistance = 0.5,
|
||||
})
|
||||
|
||||
-- Hay
|
||||
|
@ -38,6 +38,7 @@ minetest.register_node(
|
||||
post_effect_color = {a = 90, r = 40, g = 40, b = 100},
|
||||
groups = {water = 1, flowing_water = 1, liquid = 1, not_in_creative_inventory=1,},
|
||||
sounds = rp_sounds.node_sound_water_defaults(),
|
||||
_rp_blast_resistance = 4,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -74,6 +75,7 @@ minetest.register_node(
|
||||
post_effect_color = {a=90, r=40, g=40, b=100},
|
||||
groups = {water=1, liquid=1},
|
||||
sounds = rp_sounds.node_sound_water_defaults(),
|
||||
_rp_blast_resistance = 4,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -112,6 +114,7 @@ minetest.register_node(
|
||||
post_effect_color = {a=40, r=40, g=70, b=100},
|
||||
groups = {water=1, flowing_water = 1, river_water = 1, liquid=1, not_in_creative_inventory=1,},
|
||||
sounds = rp_sounds.node_sound_water_defaults(),
|
||||
_rp_blast_resistance = 4,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -150,6 +153,7 @@ minetest.register_node(
|
||||
post_effect_color = {a=40, r=40, g=70, b=100},
|
||||
groups = {water = 1, river_water = 1, liquid = 1},
|
||||
sounds = rp_sounds.node_sound_water_defaults(),
|
||||
_rp_blast_resistance = 4,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -188,6 +192,7 @@ minetest.register_node(
|
||||
post_effect_color = {a=220, r=50, g=40, b=70},
|
||||
groups = {water=1, flowing_water = 1, swamp_water = 1, liquid=1, not_in_creative_inventory=1,},
|
||||
sounds = rp_sounds.node_sound_water_defaults(),
|
||||
_rp_blast_resistance = 4,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -225,4 +230,5 @@ minetest.register_node(
|
||||
post_effect_color = {a=220, r=50, g=40, b=70},
|
||||
groups = {water = 1, swamp_water = 1, liquid = 1},
|
||||
sounds = rp_sounds.node_sound_water_defaults(),
|
||||
_rp_blast_resistance = 4,
|
||||
})
|
||||
|
@ -80,6 +80,7 @@ minetest.register_node(
|
||||
_on_degrow = function(pos, node)
|
||||
return degrow_tall(pos, 1, node.name)
|
||||
end,
|
||||
_rp_blast_resistance = 0.5,
|
||||
})
|
||||
|
||||
-- Papyrus
|
||||
@ -145,6 +146,7 @@ minetest.register_node(
|
||||
_on_degrow = function(pos, node)
|
||||
return degrow_tall(pos, 1, node.name)
|
||||
end,
|
||||
_rp_blast_resistance = 0.1,
|
||||
})
|
||||
|
||||
-- Vine
|
||||
|
@ -159,6 +159,7 @@ minetest.register_node(
|
||||
tiles = {"default_tree_top.png", "default_tree_top.png", "default_tree.png"},
|
||||
groups = {choppy = 2,tree = 1,oddly_breakable_by_hand = 1},
|
||||
sounds = snd_tree,
|
||||
_rp_blast_resistance = 1,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -168,6 +169,7 @@ minetest.register_node(
|
||||
tiles = {"default_tree_oak_top.png", "default_tree_oak_top.png", "default_tree_oak.png"},
|
||||
groups = {choppy = 2, tree = 1, oddly_breakable_by_hand = 1},
|
||||
sounds = snd_tree,
|
||||
_rp_blast_resistance = 1,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -177,6 +179,7 @@ minetest.register_node(
|
||||
tiles = {"default_tree_birch_top.png", "default_tree_birch_top.png", "default_tree_birch.png"},
|
||||
groups = {choppy = 2, tree = 1, oddly_breakable_by_hand = 1},
|
||||
sounds = snd_tree,
|
||||
_rp_blast_resistance = 1,
|
||||
})
|
||||
|
||||
-- Leaves
|
||||
|
@ -35,6 +35,7 @@ Also adds a craftitem (with identifier `name`) which the players can use.
|
||||
* `is_painted`: Set to true if this door is painted (see `rp_paint` mod)
|
||||
* `can_paint`: Set to true if this door can be painted (see `rp_paint` mod)
|
||||
* `can_unpaint`: Set to true if this door is painted and its color can be removed (see `rp_paint` mod)
|
||||
* `_rp_blast_resistance`: Blast resistance of door nodes (see `rp_explosion` mod) (default: 0)
|
||||
|
||||
#### Painted doors
|
||||
|
||||
|
@ -446,6 +446,8 @@ function door.register_door(name, def)
|
||||
_rp_unpainted_node_name = unpainted_name and unpainted_name.."_b_1",
|
||||
_rp_painted_node_name = painted_name and painted_name.."_b_1",
|
||||
_rp_paint_particle_node = def.paint_particle_node,
|
||||
-- Additional fields for rp_explosions mod
|
||||
_rp_blast_resistance = def._rp_blast_resistance,
|
||||
})
|
||||
|
||||
-- Door segment: top, state 1
|
||||
@ -516,6 +518,8 @@ function door.register_door(name, def)
|
||||
_rp_unpainted_node_name = unpainted_name and unpainted_name.."_t_1",
|
||||
_rp_painted_node_name = painted_name and painted_name.."_t_1",
|
||||
_rp_paint_particle_node = def.paint_particle_node,
|
||||
-- Additional fields for rp_explosions mod
|
||||
_rp_blast_resistance = def._rp_blast_resistance,
|
||||
})
|
||||
|
||||
-- Door segment: bottom, state 2
|
||||
@ -586,6 +590,8 @@ function door.register_door(name, def)
|
||||
_rp_unpainted_node_name = unpainted_name and unpainted_name.."_b_2",
|
||||
_rp_painted_node_name = painted_name and painted_name.."_b_2",
|
||||
_rp_paint_particle_node = def.paint_particle_node,
|
||||
-- Additional fields for rp_explosions mod
|
||||
_rp_blast_resistance = def._rp_blast_resistance,
|
||||
})
|
||||
|
||||
-- Door segment: top, state 2
|
||||
@ -655,6 +661,8 @@ function door.register_door(name, def)
|
||||
_rp_unpainted_node_name = unpainted_name and unpainted_name.."_t_2",
|
||||
_rp_painted_node_name = painted_name and painted_name.."_t_2",
|
||||
_rp_paint_particle_node = def.paint_particle_node,
|
||||
-- Additional fields for rp_explosions mod
|
||||
_rp_blast_resistance = def._rp_blast_resistance,
|
||||
})
|
||||
|
||||
end
|
||||
@ -690,6 +698,7 @@ door.register_door(
|
||||
sounds = sounds_wood_door,
|
||||
sunlight = false,
|
||||
can_paint = true,
|
||||
_rp_blast_resistance = 0.1,
|
||||
})
|
||||
door.register_door(
|
||||
"rp_door:door_wood_painted",
|
||||
@ -706,6 +715,7 @@ door.register_door(
|
||||
is_painted = true,
|
||||
can_unpaint = true,
|
||||
paint_particle_node = false,
|
||||
_rp_blast_resistance = 0.1,
|
||||
})
|
||||
|
||||
crafting.register_craft(
|
||||
@ -729,6 +739,7 @@ door.register_door(
|
||||
sounds = sounds_wood_door,
|
||||
sunlight = false,
|
||||
can_paint = true,
|
||||
_rp_blast_resistance = 0.1,
|
||||
})
|
||||
door.register_door(
|
||||
"rp_door:door_wood_oak_painted",
|
||||
@ -745,6 +756,7 @@ door.register_door(
|
||||
is_painted = true,
|
||||
can_unpaint = true,
|
||||
paint_particle_node = false,
|
||||
_rp_blast_resistance = 0.1,
|
||||
})
|
||||
|
||||
|
||||
@ -769,6 +781,7 @@ door.register_door(
|
||||
sounds = sounds_wood_door,
|
||||
sunlight = false,
|
||||
can_paint = true,
|
||||
_rp_blast_resistance = 0.1,
|
||||
})
|
||||
door.register_door(
|
||||
"rp_door:door_wood_birch_painted",
|
||||
@ -785,6 +798,7 @@ door.register_door(
|
||||
is_painted = true,
|
||||
can_unpaint = true,
|
||||
paint_particle_node = false,
|
||||
_rp_blast_resistance = 0.1,
|
||||
})
|
||||
|
||||
|
||||
@ -816,6 +830,7 @@ door.register_door(
|
||||
sunlight = false,
|
||||
sound_open_door = "door_open_stone",
|
||||
sound_close_door = "door_close_stone",
|
||||
_rp_blast_resistance = 0.2,
|
||||
})
|
||||
|
||||
door.toggle_door = function(pos)
|
||||
|
23
mods/rp_explosions/API.md
Normal file
@ -0,0 +1,23 @@
|
||||
# `rp_explosions`
|
||||
This mod provides helper functions to create explosions.
|
||||
|
||||
## Blast resistance
|
||||
|
||||
This mod expects nodes to specify a blast resistance value. The higher it is, the harder
|
||||
it is for the node to break by explosions.
|
||||
|
||||
To specify the blast resistance, add `_rp_blast_resistance = <number>` to the node definition.
|
||||
|
||||
The default blast resistance is 0. At blast resistance 1000000 or higher, the node becomes indestructible.
|
||||
|
||||
## `rp_explosions.explode(pos, strength, info, puncher)`
|
||||
* `pos`: position, initial position of the explosion
|
||||
* `strength`: number, radius of the explosion
|
||||
* `info`: table, contains these optional fields:
|
||||
* `drop_chance`: number, if specified becomes the drop chance of all nodes in the explosion (default: 1.0 / strength)
|
||||
* `max_blast_resistance`: integer, if specified the explosion will treat all non-indestructible nodes as having a blast resistance of no more than this value
|
||||
* `sound`: bool, if true, the explosion will play a sound (default: true)
|
||||
* `particles`: bool, if true, the explosion will create particles (default: true)
|
||||
* `griefing`: bool, if true, the explosion will destroy nodes (default: true)
|
||||
* `grief_protected`: bool, if true, the explosion will also destroy nodes which have been protected (default: false)
|
||||
* `puncher`: (optional) entity, will be used as source for damage done by the explosion
|
11
mods/rp_explosions/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# `rp_explosions`: Explosion API mod for Repixture.
|
||||
|
||||
This mod handles explosions.
|
||||
|
||||
## Credits / License
|
||||
|
||||
This mod originally was created by Elias Astrom <ryvnf@riseup.net> for MineClone 2
|
||||
and is released under the LGPLv2.1 license.
|
||||
|
||||
Texture license: CC BY-SA 4.0
|
||||
|
493
mods/rp_explosions/init.lua
Normal file
@ -0,0 +1,493 @@
|
||||
--[[
|
||||
Explosion API mod for Repixture.
|
||||
|
||||
This mod is based on the Minetest explosion API mod, but has been changed
|
||||
to have the same explosion mechanics as Minecraft and work with Repixture.
|
||||
The computation-intensive parts of the mod has been optimized to allow for
|
||||
larger explosions and faster world updating.
|
||||
|
||||
This mod originally was created by Elias Astrom <ryvnf@riseup.net> and is released
|
||||
under the LGPLv2.1 license.
|
||||
--]]
|
||||
|
||||
local PARTICLES = true
|
||||
|
||||
rp_explosions = {}
|
||||
|
||||
local explosions_griefing = minetest.settings:get_bool("rp_explosions_griefing", true)
|
||||
|
||||
local math = math
|
||||
local vector = vector
|
||||
local table = table
|
||||
|
||||
local hash_node_position = minetest.hash_node_position
|
||||
local get_objects_inside_radius = minetest.get_objects_inside_radius
|
||||
local get_position_from_hash = minetest.get_position_from_hash
|
||||
local get_node_drops = minetest.get_node_drops
|
||||
local get_name_from_content_id = minetest.get_name_from_content_id
|
||||
local get_voxel_manip = minetest.get_voxel_manip
|
||||
local bulk_set_node = minetest.bulk_set_node
|
||||
local check_for_falling = minetest.check_for_falling
|
||||
local add_item = minetest.add_item
|
||||
local pos_to_string = minetest.pos_to_string
|
||||
|
||||
-- Saved sphere explosion shapes for various radiuses
|
||||
local sphere_shapes = {}
|
||||
|
||||
-- Saved node definitions in table using cid-keys for faster look-up.
|
||||
local node_blastres = {}
|
||||
local node_on_blast = {}
|
||||
local node_walkable = {}
|
||||
|
||||
-- The step length for the rays (Minecraft uses 0.3)
|
||||
local STEP_LENGTH = 0.3
|
||||
|
||||
-- How many rays to compute entity exposure to explosion
|
||||
local N_EXPOSURE_RAYS = 16
|
||||
|
||||
-- Nodes having a blast resistance of this value or higher are treated as
|
||||
-- indestructible
|
||||
local INDESTRUCT_BLASTRES = 1000000
|
||||
|
||||
minetest.register_on_mods_loaded(function()
|
||||
-- Store blast resistance values by content ids to improve performance.
|
||||
for name, def in pairs(minetest.registered_nodes) do
|
||||
local id = minetest.get_content_id(name)
|
||||
node_blastres[id] = def._rp_blast_resistance or 0
|
||||
node_on_blast[id] = def.on_blast
|
||||
node_walkable[id] = def.walkable
|
||||
end
|
||||
end)
|
||||
|
||||
-- Compute the rays which make up a sphere with radius. Returns a list of rays
|
||||
-- which can be used to trace explosions. This function is not efficient
|
||||
-- (especially for larger radiuses), so the generated rays for various radiuses
|
||||
-- should be cached and reused.
|
||||
--
|
||||
-- Should be possible to improve by using a midpoint circle algorithm multiple
|
||||
-- times to create the sphere, currently uses more of a brute-force approach.
|
||||
--
|
||||
-- TODO: Improve performance by using a midpoint circle algorithm multiple times
|
||||
local function compute_sphere_rays(radius)
|
||||
local rays = {}
|
||||
local sphere = {}
|
||||
|
||||
local function add_ray(pos)
|
||||
sphere[hash_node_position(pos)] = pos
|
||||
end
|
||||
|
||||
for y = -radius, radius do
|
||||
for z = -radius, radius do
|
||||
for x = -radius, 0 do
|
||||
local d = x * x + y * y + z * z
|
||||
if d <= radius * radius then
|
||||
add_ray(vector.new(x, y, z))
|
||||
add_ray(vector.new(-x, y, z))
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for x = -radius, radius do
|
||||
for z = -radius, radius do
|
||||
for y = -radius, 0 do
|
||||
local d = x * x + y * y + z * z
|
||||
if d <= radius * radius then
|
||||
add_ray(vector.new(x, y, z))
|
||||
add_ray(vector.new(x, -y, z))
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for x = -radius, radius do
|
||||
for y = -radius, radius do
|
||||
for z = -radius, 0 do
|
||||
local d = x * x + y * y + z * z
|
||||
if d <= radius * radius then
|
||||
add_ray(vector.new(x, y, z))
|
||||
add_ray(vector.new(x, y, -z))
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, pos in pairs(sphere) do
|
||||
rays[#rays + 1] = vector.normalize(pos)
|
||||
end
|
||||
|
||||
return rays
|
||||
end
|
||||
|
||||
-- Add particles from explosion
|
||||
--
|
||||
-- Parameters:
|
||||
-- pos - The position of the explosion
|
||||
-- radius - The radius of the explosion
|
||||
local function add_explosion_particles(pos, radius)
|
||||
if not PARTICLES then
|
||||
return
|
||||
end
|
||||
minetest.add_particlespawner(
|
||||
{
|
||||
amount = 128,
|
||||
time = 0.6,
|
||||
pos = {
|
||||
min = vector.subtract(pos, radius / 2),
|
||||
max = vector.add(pos, radius / 2),
|
||||
},
|
||||
vel = {
|
||||
min = vector.new(-20, -20, -20),
|
||||
max = vector.new(20, 20, 20),
|
||||
},
|
||||
acc = vector.zero(),
|
||||
exptime = { min = 0.2, max = 1.0 },
|
||||
size = { min = 16, max = 24 },
|
||||
drag = vector.new(1,1,1),
|
||||
texture = {
|
||||
name = "rp_tnt_smoke_anim_1.png", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = -1 },
|
||||
name = "rp_tnt_smoke_anim_2.png", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = -1 },
|
||||
name = "rp_tnt_smoke_anim_1.png^[transformFX", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = -1 },
|
||||
name = "rp_tnt_smoke_anim_2.png^[transformFX", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = -1 },
|
||||
},
|
||||
})
|
||||
minetest.add_particlespawner({
|
||||
amount = 1,
|
||||
time = 0.01,
|
||||
pos = pos,
|
||||
vel = vector.zero(),
|
||||
acc = vector.zero(),
|
||||
exptime = 1,
|
||||
size = radius*10,
|
||||
texture = "rp_tnt_smoke_ball_big.png",
|
||||
animation = { type = "vertical_frames", aspect_w = 32, aspect_h = 32, length = -1, },
|
||||
})
|
||||
minetest.add_particlespawner({
|
||||
amount = 4,
|
||||
time = 0.25,
|
||||
pos = pos,
|
||||
vel = vector.zero(),
|
||||
acc = vector.zero(),
|
||||
exptime = { min = 0.6, max = 0.9 },
|
||||
size = { min = 8, max = 12 },
|
||||
radius = { min = 0.5, max = math.max(0.6, radius*0.75) },
|
||||
texture = "rp_tnt_smoke_ball_medium.png",
|
||||
animation = { type = "vertical_frames", aspect_w = 32, aspect_h = 32, length = -1, },
|
||||
})
|
||||
minetest.add_particlespawner({
|
||||
amount = 28,
|
||||
time = 0.5,
|
||||
pos = pos,
|
||||
vel = vector.zero(),
|
||||
acc = vector.zero(),
|
||||
exptime = { min = 0.5, max = 0.8 },
|
||||
size = { min = 6, max = 8 },
|
||||
radius = { min = 1, max = math.max(1.1, radius+1) },
|
||||
texture = "rp_tnt_smoke_ball_small.png",
|
||||
animation = { type = "vertical_frames", aspect_w = 32, aspect_h = 32, length = -1, },
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
-- Traces the rays of an explosion, and updates the environment.
|
||||
--
|
||||
-- Parameters:
|
||||
-- pos - Where the rays in the explosion should start from
|
||||
-- strength - The strength of each ray
|
||||
-- raydirs - The directions for each ray
|
||||
-- radius - The maximum distance each ray will go
|
||||
-- info - Table containing information about explosion
|
||||
-- direct - direct source object of the damage (optional)
|
||||
-- source - indirect source object of the damage (optional)
|
||||
--
|
||||
-- Values in info:
|
||||
-- drop_chance - The chance that destroyed nodes will drop their items
|
||||
-- griefing - If true, the explosion will destroy nodes (default: true)
|
||||
-- max_blast_resistance - The explosion will treat all non-indestructible nodes
|
||||
-- as having a blast resistance of no more than this
|
||||
-- value
|
||||
-- grief_protected - If true, the explosion will also destroy nodes which have
|
||||
-- been protected
|
||||
--
|
||||
-- Note that this function has been optimized, it contains code which has been
|
||||
-- inlined to avoid function calls and unnecessary table creation. This was
|
||||
-- measured to give a significant performance increase.
|
||||
local function trace_explode(pos, strength, raydirs, radius, info, direct, source)
|
||||
local vm = get_voxel_manip()
|
||||
|
||||
local emin, emax = vm:read_from_map(vector.subtract(pos, radius),
|
||||
vector.add(pos, radius))
|
||||
local emin_x = emin.x
|
||||
local emin_y = emin.y
|
||||
local emin_z = emin.z
|
||||
|
||||
local ystride = (emax.x - emin_x + 1)
|
||||
local zstride = ystride * (emax.y - emin_y + 1)
|
||||
|
||||
local data = vm:get_data()
|
||||
local destroy = {}
|
||||
|
||||
local drop_chance = info.drop_chance
|
||||
local max_blast_resistance = info.max_blast_resistance
|
||||
local grief_protected = info.grief_protected
|
||||
|
||||
-- Trace rays for environment destruction
|
||||
if info.griefing and explosions_griefing then
|
||||
for i = 1, #raydirs do
|
||||
local rpos_x = pos.x
|
||||
local rpos_y = pos.y
|
||||
local rpos_z = pos.z
|
||||
local rdir_x = raydirs[i].x
|
||||
local rdir_y = raydirs[i].y
|
||||
local rdir_z = raydirs[i].z
|
||||
local rstr = (0.7 + math.random() * 0.6) * strength
|
||||
|
||||
for r = 0, math.ceil(radius * (1.0 / STEP_LENGTH)) do
|
||||
local npos_x = math.floor(rpos_x + 0.5)
|
||||
local npos_y = math.floor(rpos_y + 0.5)
|
||||
local npos_z = math.floor(rpos_z + 0.5)
|
||||
local npos = { x = npos_x, y = npos_y, z = npos_z }
|
||||
local idx = (npos_z - emin_z) * zstride + (npos_y - emin_y) * ystride +
|
||||
npos_x - emin_x + 1
|
||||
|
||||
local cid = data[idx]
|
||||
local br = node_blastres[cid] or INDESTRUCT_BLASTRES
|
||||
if br < INDESTRUCT_BLASTRES and br > max_blast_resistance then
|
||||
br = max_blast_resistance
|
||||
end
|
||||
|
||||
local hash = hash_node_position(npos)
|
||||
|
||||
rpos_x = rpos_x + STEP_LENGTH * rdir_x
|
||||
rpos_y = rpos_y + STEP_LENGTH * rdir_y
|
||||
rpos_z = rpos_z + STEP_LENGTH * rdir_z
|
||||
|
||||
rstr = rstr - 0.75 * STEP_LENGTH - (br + 0.3) * STEP_LENGTH
|
||||
|
||||
if rstr <= 0 then
|
||||
break
|
||||
end
|
||||
|
||||
if cid ~= minetest.CONTENT_AIR then
|
||||
if not minetest.is_protected(npos, "") or grief_protected then
|
||||
destroy[hash] = idx
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Entities in radius of explosion
|
||||
local punch_radius = 2 * strength
|
||||
local objs = get_objects_inside_radius(pos, punch_radius)
|
||||
|
||||
-- Trace rays for entity damage
|
||||
for _, obj in pairs(objs) do
|
||||
local ent = obj:get_luaentity()
|
||||
|
||||
-- Ignore items to lower lag
|
||||
if (obj:is_player() or (ent and ent.name ~= "__builtin:item")) and obj:get_hp() > 0 then
|
||||
local opos = obj:get_pos()
|
||||
local collisionbox = nil
|
||||
|
||||
if obj:is_player() then
|
||||
local props = obj:get_properties()
|
||||
collisionbox = props.collisionbox or { -0.3, 0.0, -0.3, 0.3, 1.77, 0.3 }
|
||||
elseif ent and ent.name then
|
||||
local props = obj:get_properties()
|
||||
collisionbox = props.collisionbox
|
||||
end
|
||||
|
||||
if collisionbox then
|
||||
-- Create rays from random points in the collision box
|
||||
local x1 = collisionbox[1]
|
||||
local y1 = collisionbox[2]
|
||||
local z1 = collisionbox[3]
|
||||
local x2 = collisionbox[4]
|
||||
local y2 = collisionbox[5]
|
||||
local z2 = collisionbox[6]
|
||||
local x_len = math.abs(x2 - x1)
|
||||
local y_len = math.abs(y2 - y1)
|
||||
local z_len = math.abs(z2 - z1)
|
||||
|
||||
-- Move object position to the center of its bounding box
|
||||
opos.x = opos.x + 0.5 * (x1 + x2)
|
||||
opos.y = opos.y + 0.5 * (y1 + y2)
|
||||
opos.z = opos.z + 0.5 * (z1 + z2)
|
||||
|
||||
-- Count number of rays from collision box which are unobstructed
|
||||
local count = N_EXPOSURE_RAYS
|
||||
|
||||
for i = 1, N_EXPOSURE_RAYS do
|
||||
local rpos_x = opos.x + math.random() * x_len - x_len / 2
|
||||
local rpos_y = opos.y + math.random() * y_len - y_len / 2
|
||||
local rpos_z = opos.z + math.random() * z_len - z_len / 2
|
||||
local rdir_x = pos.x - rpos_x
|
||||
local rdir_y = pos.y - rpos_y
|
||||
local rdir_z = pos.z - rpos_z
|
||||
local rdir_len = math.hypot(rdir_x, math.hypot(rdir_y, rdir_z))
|
||||
rdir_x = rdir_x / rdir_len
|
||||
rdir_y = rdir_y / rdir_len
|
||||
rdir_z = rdir_z / rdir_len
|
||||
|
||||
for i = 0, rdir_len / STEP_LENGTH do
|
||||
rpos_x = rpos_x + rdir_x * STEP_LENGTH
|
||||
rpos_y = rpos_y + rdir_y * STEP_LENGTH
|
||||
rpos_z = rpos_z + rdir_z * STEP_LENGTH
|
||||
local npos_x = math.floor(rpos_x + 0.5)
|
||||
local npos_y = math.floor(rpos_y + 0.5)
|
||||
local npos_z = math.floor(rpos_z + 0.5)
|
||||
local idx = (npos_z - emin_z) * zstride + (npos_y - emin_y) * ystride +
|
||||
npos_x - emin_x + 1
|
||||
|
||||
|
||||
local cid = data[idx]
|
||||
local walkable = node_walkable[cid]
|
||||
|
||||
if walkable then
|
||||
count = count - 1
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Punch entity with damage depending on explosion exposure and
|
||||
-- distance to explosion
|
||||
local exposure = count / N_EXPOSURE_RAYS
|
||||
local punch_vec = vector.subtract(opos, pos)
|
||||
local punch_len = vector.length(punch_vec)
|
||||
local punch_dir = vector.normalize(punch_vec)
|
||||
local impact = (1 - punch_len / punch_radius) * exposure
|
||||
if impact < 0 then
|
||||
impact = 0
|
||||
end
|
||||
local damage = (impact * impact + impact) * ((4 / punch_len) * punch_radius)
|
||||
|
||||
local punch_source
|
||||
if source then
|
||||
punch_source = source
|
||||
else
|
||||
punch_source = obj
|
||||
end
|
||||
obj:punch(punch_source, 1000000, { full_punch_interval = 0, damage_groups = { fleshy = damage } }, punch_dir )
|
||||
|
||||
if obj:is_player() or ent._rp_explosions_knockback then
|
||||
obj:add_velocity(vector.multiply(punch_dir, impact * 20))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local airs = {}
|
||||
|
||||
-- Remove destroyed blocks and drop items
|
||||
for hash, idx in pairs(destroy) do
|
||||
local do_drop = math.random() <= drop_chance
|
||||
local on_blast = node_on_blast[data[idx]]
|
||||
local remove = true
|
||||
|
||||
if do_drop or on_blast then
|
||||
local npos = get_position_from_hash(hash)
|
||||
if on_blast then
|
||||
on_blast(npos, 1.0, do_drop)
|
||||
remove = false
|
||||
else
|
||||
local name = get_name_from_content_id(data[idx])
|
||||
local drop = get_node_drops(name, "")
|
||||
|
||||
for _, item in ipairs(drop) do
|
||||
if type(item) ~= "string" then
|
||||
item = item:get_name() .. item:get_count()
|
||||
end
|
||||
add_item(npos, item)
|
||||
end
|
||||
end
|
||||
end
|
||||
if remove then
|
||||
table.insert(airs, get_position_from_hash(hash))
|
||||
end
|
||||
end
|
||||
-- We use bulk_set_node instead of LVM because we want to have on_destruct and
|
||||
-- on_construct being called
|
||||
if #airs > 0 then
|
||||
bulk_set_node(airs, { name = "air" })
|
||||
end
|
||||
-- Update falling nodes
|
||||
for a = 1, #airs do
|
||||
local p = airs[a]
|
||||
check_for_falling(vector.offset(p, 0, 1, 0))
|
||||
end
|
||||
|
||||
-- Log explosion
|
||||
minetest.log("action", "Explosion at " .. pos_to_string(pos) .. " with strength " .. strength .. " and radius " ..
|
||||
radius)
|
||||
end
|
||||
|
||||
-- Create an explosion with strength at pos.
|
||||
--
|
||||
-- Parameters:
|
||||
-- pos - The position where the explosion originates from
|
||||
-- strength - The blast strength of the explosion (a TNT explosion uses 4)
|
||||
-- info - Table containing information about explosion
|
||||
-- direct - direct source object of the damage (optional)
|
||||
-- source - indirect source object of the damage (optional)
|
||||
--
|
||||
-- Values in info:
|
||||
-- drop_chance - If specified becomes the drop chance of all nodes in the
|
||||
-- explosion (default: 1.0 / strength)
|
||||
-- max_blast_resistance - If specified the explosion will treat all
|
||||
-- non-indestructible nodes as having a blast resistance
|
||||
-- of no more than this value
|
||||
-- sound - If true, the explosion will play a sound (default: true)
|
||||
-- particles - If true, the explosion will create particles (default: true)
|
||||
-- griefing - If true, the explosion will destroy nodes (default: true)
|
||||
-- grief_protected - If true, the explosion will also destroy nodes which have
|
||||
-- been protected (default: false)
|
||||
---@param pos Vector
|
||||
---@param strength number
|
||||
---@param info {drop_chance: number, max_blast_resistance: number, sound: boolean, particles: boolean, griefing: boolean, grief_protected: boolean}
|
||||
---@param direct? ObjectRef
|
||||
---@param source? ObjectRef
|
||||
function rp_explosions.explode(pos, strength, info, direct, source)
|
||||
if info == nil then
|
||||
info = {}
|
||||
end
|
||||
|
||||
-- The maximum blast radius (in the air)
|
||||
local radius = math.ceil(1.3 * strength / (0.3 * 0.75) * 0.3)
|
||||
|
||||
if not sphere_shapes[radius] then
|
||||
sphere_shapes[radius] = compute_sphere_rays(radius)
|
||||
end
|
||||
local shape = sphere_shapes[radius]
|
||||
|
||||
-- Default values
|
||||
if info.drop_chance == nil then info.drop_chance = 1 / strength end
|
||||
if info.particles == nil then info.particles = true end
|
||||
if info.sound == nil then info.sound = true end
|
||||
if info.griefing == nil then info.griefing = true end
|
||||
if info.grief_protected == nil then info.grief_protected = false end
|
||||
if info.max_blast_resistance == nil then
|
||||
info.max_blast_resistance = INDESTRUCT_BLASTRES
|
||||
end
|
||||
|
||||
-- Don't do drops in creative mode
|
||||
if minetest.is_creative_enabled("") then
|
||||
info.drop_chance = 0
|
||||
end
|
||||
|
||||
trace_explode(pos, strength, shape, radius, info, direct, source)
|
||||
|
||||
if info.particles then
|
||||
add_explosion_particles(pos, radius)
|
||||
end
|
||||
if info.sound then
|
||||
minetest.sound_play("tnt_explode", {
|
||||
pos = pos, gain = 1.0,
|
||||
max_hear_distance = strength * 16
|
||||
}, true)
|
||||
end
|
||||
end
|
2
mods/rp_explosions/mod.conf
Normal file
@ -0,0 +1,2 @@
|
||||
name = rp_explosions
|
||||
description = A common API to create explosions.
|
Before Width: | Height: | Size: 167 B After Width: | Height: | Size: 167 B |
Before Width: | Height: | Size: 167 B After Width: | Height: | Size: 167 B |
Before Width: | Height: | Size: 531 B After Width: | Height: | Size: 531 B |
Before Width: | Height: | Size: 386 B After Width: | Height: | Size: 386 B |
Before Width: | Height: | Size: 288 B After Width: | Height: | Size: 288 B |
@ -576,6 +576,7 @@ minetest.register_node(
|
||||
drop = "rp_gold:lump_gold",
|
||||
is_ground_content = true,
|
||||
sounds = rp_sounds.node_sound_stone_defaults(),
|
||||
_rp_blast_resistance = 1,
|
||||
})
|
||||
|
||||
local make_metal_sounds = function(pitch)
|
||||
@ -603,6 +604,7 @@ minetest.register_node(
|
||||
groups = {cracky = 2},
|
||||
sounds = make_metal_sounds(gold.PITCH),
|
||||
is_ground_content = false,
|
||||
_rp_blast_resistance = 8,
|
||||
})
|
||||
|
||||
-- Ores
|
||||
|
@ -372,6 +372,7 @@ minetest.register_node("rp_itemshow:showcase", {
|
||||
on_punch = function(pos, node, puncher)
|
||||
update_item(pos, node, true)
|
||||
end,
|
||||
_rp_blast_resistance = 0.4,
|
||||
})
|
||||
|
||||
-- automatically restore entities lost from frames/showcases
|
||||
|
@ -431,6 +431,7 @@ minetest.register_node(
|
||||
player:set_wielded_item(itemstack)
|
||||
end
|
||||
end,
|
||||
_rp_blast_resistance = 2,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -445,6 +446,7 @@ minetest.register_node(
|
||||
drop = "rp_jewels:jewel",
|
||||
groups = {choppy=1, tree=1, ore=1},
|
||||
sounds = rp_sounds.node_sound_wood_defaults(),
|
||||
_rp_blast_resistance = 1,
|
||||
})
|
||||
|
||||
crafting.register_craft(
|
||||
|
@ -374,6 +374,7 @@ local chest_def = {
|
||||
]]
|
||||
end,
|
||||
on_blast = function() end,
|
||||
_rp_blast_resistance = 2,
|
||||
}
|
||||
|
||||
minetest.register_node("rp_locks:chest", chest_def)
|
||||
|
@ -146,6 +146,7 @@ minetest.register_node(
|
||||
groups = {cracky = 1, mineral_natural=1},
|
||||
light_source = LUMIEN_BLOCK_LIGHT,
|
||||
sounds = get_sounds(),
|
||||
_rp_blast_resistance = 3,
|
||||
})
|
||||
|
||||
minetest.register_node(
|
||||
@ -156,6 +157,7 @@ minetest.register_node(
|
||||
groups = {cracky = 1},
|
||||
light_source = LUMIEN_BLOCK_LIGHT,
|
||||
sounds = get_sounds(),
|
||||
_rp_blast_resistance = 6,
|
||||
})
|
||||
|
||||
-- Ores
|
||||
@ -168,6 +170,7 @@ minetest.register_node(
|
||||
groups = {cracky = 1, stone = 1, ore=1},
|
||||
drop = "rp_lumien:block",
|
||||
sounds = rp_sounds.node_sound_stone_defaults(),
|
||||
_rp_blast_resistance = 1,
|
||||
})
|
||||
|
||||
minetest.register_ore(
|
||||
|
@ -117,6 +117,7 @@ rp_mobs.register_mob("rp_mobs_mobs:boar", {
|
||||
end,
|
||||
on_death = rp_mobs.on_death_default,
|
||||
on_punch = rp_mobs_mobs.on_punch_make_hostile,
|
||||
_rp_explosions_knockback = true,
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -65,7 +65,7 @@ local function explode(mob)
|
||||
local pos = mob.object:get_pos()
|
||||
mob.object:set_armor_groups({immortal=1})
|
||||
pos.y = pos.y - 1
|
||||
tnt.boom_notnt(pos, EXPLODE_RADIUS, nil, nil, mob.object)
|
||||
rp_explosions.explode(pos, EXPLODE_RADIUS, {grief_protected=true}, mob)
|
||||
mob.object:remove()
|
||||
minetest.log("action", "[rp_mobs_mobs] "..mob.name.." exploded at "..minetest.pos_to_string(pos, 1))
|
||||
end
|
||||
@ -215,6 +215,7 @@ rp_mobs.register_mob("rp_mobs_mobs:mineturtle", {
|
||||
end,
|
||||
on_death = rp_mobs.on_death_default,
|
||||
on_punch = rp_mobs.on_punch_default,
|
||||
_rp_explosions_knockback = true,
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -296,6 +296,7 @@ rp_mobs.register_mob("rp_mobs_mobs:sheep", {
|
||||
|
||||
on_death = rp_mobs.on_death_default,
|
||||
on_punch = rp_mobs.on_punch_default,
|
||||
_rp_explosions_knockback = true,
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -106,6 +106,7 @@ rp_mobs.register_mob("rp_mobs_mobs:skunk", {
|
||||
end,
|
||||
on_death = rp_mobs.on_death_default,
|
||||
on_punch = rp_mobs_mobs.on_punch_make_hostile,
|
||||
_rp_explosions_knockback = true,
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -1472,6 +1472,7 @@ rp_mobs.register_mob("rp_mobs_mobs:villager", {
|
||||
end
|
||||
end
|
||||
end,
|
||||
_rp_explosions_knockback = true,
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -103,6 +103,7 @@ rp_mobs.register_mob("rp_mobs_mobs:walker", {
|
||||
end,
|
||||
on_death = rp_mobs.on_death_default,
|
||||
on_punch = rp_mobs.on_punch_default,
|
||||
_rp_explosions_knockback = true,
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
name = rp_mobs_mobs
|
||||
title = Repixture Mobs
|
||||
description = Repixture Mobs: Mob definitions, behavior, graphics, models, sounds
|
||||
depends = rp_mobs, rp_pathfinder, rp_achievements, rp_tnt, rp_door, rp_creative
|
||||
depends = rp_mobs, rp_pathfinder, rp_achievements, rp_explosions, rp_door, rp_creative
|
||||
optional_depends = rp_nav
|
||||
|
@ -194,6 +194,9 @@ function partialblocks.register_material(name, desc_slab, desc_stair, node, grou
|
||||
end
|
||||
return itemstack
|
||||
end,
|
||||
|
||||
-- for rp_explosions
|
||||
_rp_blast_resistance = nodedef._rp_blast_resistance,
|
||||
})
|
||||
|
||||
if register_crafts then
|
||||
@ -282,6 +285,9 @@ function partialblocks.register_material(name, desc_slab, desc_stair, node, grou
|
||||
use_texture_alpha = nodedef.use_texture_alpha,
|
||||
is_ground_content = nodedef.is_ground_content,
|
||||
drop = drop_stair,
|
||||
|
||||
-- for rp_explosions
|
||||
_rp_blast_resistance = nodedef._rp_blast_resistance,
|
||||
})
|
||||
|
||||
if register_crafts then
|
||||
|
@ -54,6 +54,7 @@ local register_spikes = function(name, def)
|
||||
damage_per_second = def.damage_per_second,
|
||||
sounds = make_metal_sounds(def.pitch),
|
||||
_rp_node_death_message = { NS("You were impaled by spikes.") },
|
||||
_rp_blast_resistance = def._rp_blast_resistance,
|
||||
}
|
||||
minetest.register_node(name, spikedef)
|
||||
|
||||
@ -78,6 +79,7 @@ register_spikes("rp_spikes:spikes_copper", {
|
||||
damage_per_second = 2,
|
||||
craftitem = "rp_default:ingot_copper",
|
||||
pitch = mod_default and default.METAL_PITCH_COPPER,
|
||||
_rp_blast_resistance = 1.75,
|
||||
})
|
||||
register_spikes("rp_spikes:spikes_wrought_iron", {
|
||||
description = S("Wrought Iron Spikes"),
|
||||
@ -87,6 +89,7 @@ register_spikes("rp_spikes:spikes_wrought_iron", {
|
||||
craftitem = "rp_default:ingot_wrought_iron",
|
||||
groups_plus = { magnetic = 1 },
|
||||
pitch = mod_default and default.METAL_PITCH_WROUGHT_IRON,
|
||||
_rp_blast_resistance = 2,
|
||||
})
|
||||
register_spikes("rp_spikes:spikes_steel", {
|
||||
description = S("Steel Spikes"),
|
||||
@ -95,6 +98,7 @@ register_spikes("rp_spikes:spikes_steel", {
|
||||
damage_per_second = 4,
|
||||
craftitem = "rp_default:ingot_steel",
|
||||
pitch = mod_default and default.METAL_PITCH_STEEL,
|
||||
_rp_blast_resistance = 2.25,
|
||||
})
|
||||
register_spikes("rp_spikes:spikes_carbon_steel", {
|
||||
description = S("Carbon Steel Spikes"),
|
||||
@ -103,6 +107,7 @@ register_spikes("rp_spikes:spikes_carbon_steel", {
|
||||
damage_per_second = 5,
|
||||
craftitem = "rp_default:ingot_carbon_steel",
|
||||
pitch = mod_default and default.METAL_PITCH_CARBON_STEEL,
|
||||
_rp_blast_resistance = 2.5,
|
||||
})
|
||||
register_spikes("rp_spikes:spikes_bronze", {
|
||||
description = S("Bronze Spikes"),
|
||||
@ -111,5 +116,6 @@ register_spikes("rp_spikes:spikes_bronze", {
|
||||
damage_per_second = 6,
|
||||
craftitem = "rp_default:ingot_bronze",
|
||||
pitch = mod_default and default.METAL_PITCH_BRONZE,
|
||||
_rp_blast_resistance = 3,
|
||||
})
|
||||
|
||||
|
@ -8,8 +8,8 @@ local S = minetest.get_translator("rp_tnt")
|
||||
local TNT_TIMER = 2.0
|
||||
|
||||
-- For performance debugging
|
||||
local TNT_NO_PARTICLES = false
|
||||
local TNT_NO_SOUNDS = false
|
||||
local TNT_NO_PARTICLES = false
|
||||
|
||||
tnt = {}
|
||||
|
||||
@ -207,69 +207,6 @@ local function add_node_break_effects(pos, node, node_tile)
|
||||
})
|
||||
end
|
||||
|
||||
local function add_explosion_effects(pos, radius)
|
||||
if TNT_NO_PARTICLES then
|
||||
return
|
||||
end
|
||||
minetest.add_particlespawner(
|
||||
{
|
||||
amount = 128,
|
||||
time = 0.6,
|
||||
pos = {
|
||||
min = vector.subtract(pos, radius / 2),
|
||||
max = vector.add(pos, radius / 2),
|
||||
},
|
||||
vel = {
|
||||
min = vector.new(-20, -20, -20),
|
||||
max = vector.new(20, 20, 20),
|
||||
},
|
||||
acc = vector.zero(),
|
||||
exptime = { min = 0.2, max = 1.0 },
|
||||
size = { min = 16, max = 24 },
|
||||
drag = vector.new(1,1,1),
|
||||
texture = {
|
||||
name = "rp_tnt_smoke_anim_1.png", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = -1 },
|
||||
name = "rp_tnt_smoke_anim_2.png", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = -1 },
|
||||
name = "rp_tnt_smoke_anim_1.png^[transformFX", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = -1 },
|
||||
name = "rp_tnt_smoke_anim_2.png^[transformFX", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = -1 },
|
||||
},
|
||||
})
|
||||
minetest.add_particlespawner({
|
||||
amount = 1,
|
||||
time = 0.01,
|
||||
pos = pos,
|
||||
vel = vector.zero(),
|
||||
acc = vector.zero(),
|
||||
exptime = 1,
|
||||
size = radius*10,
|
||||
texture = "rp_tnt_smoke_ball_big.png",
|
||||
animation = { type = "vertical_frames", aspect_w = 32, aspect_h = 32, length = -1, },
|
||||
})
|
||||
minetest.add_particlespawner({
|
||||
amount = 4,
|
||||
time = 0.25,
|
||||
pos = pos,
|
||||
vel = vector.zero(),
|
||||
acc = vector.zero(),
|
||||
exptime = { min = 0.6, max = 0.9 },
|
||||
size = { min = 8, max = 12 },
|
||||
radius = { min = 0.5, max = math.max(0.6, radius*0.75) },
|
||||
texture = "rp_tnt_smoke_ball_medium.png",
|
||||
animation = { type = "vertical_frames", aspect_w = 32, aspect_h = 32, length = -1, },
|
||||
})
|
||||
minetest.add_particlespawner({
|
||||
amount = 28,
|
||||
time = 0.5,
|
||||
pos = pos,
|
||||
vel = vector.zero(),
|
||||
acc = vector.zero(),
|
||||
exptime = { min = 0.5, max = 0.8 },
|
||||
size = { min = 6, max = 8 },
|
||||
radius = { min = 1, max = math.max(1.1, radius+1) },
|
||||
texture = "rp_tnt_smoke_ball_small.png",
|
||||
animation = { type = "vertical_frames", aspect_w = 32, aspect_h = 32, length = -1, },
|
||||
})
|
||||
end
|
||||
|
||||
local function emit_fuse_smoke(pos)
|
||||
if TNT_NO_PARTICLES then
|
||||
@ -330,72 +267,8 @@ local function play_tnt_sound(pos, sound)
|
||||
}, true)
|
||||
end
|
||||
|
||||
-- TNT ground removal
|
||||
|
||||
function tnt.explode(pos, radius)
|
||||
local pos = vector.round(pos)
|
||||
local vm = VoxelManip()
|
||||
local pr = PseudoRandom(os.time())
|
||||
local p1 = vector.subtract(pos, radius)
|
||||
local p2 = vector.add(pos, radius)
|
||||
local minp, maxp = vm:read_from_map(p1, p2)
|
||||
local area = VoxelArea:new({MinEdge = minp, MaxEdge = maxp})
|
||||
local data = vm:get_data()
|
||||
|
||||
local drops = {}
|
||||
local p = {}
|
||||
|
||||
local c_air = minetest.get_content_id("air")
|
||||
|
||||
local destroyed_nodes = {}
|
||||
local on_blasts = {}
|
||||
|
||||
for z = -radius, radius do
|
||||
for y = -radius, radius do
|
||||
local vi = area:index(pos.x + (-radius), pos.y + y, pos.z + z)
|
||||
for x = -radius, radius do
|
||||
if (x * x) + (y * y) + (z * z) <= (radius * radius) + pr:next(-radius, radius) then
|
||||
local cid = data[vi]
|
||||
p.x = pos.x + x
|
||||
p.y = pos.y + y
|
||||
p.z = pos.z + z
|
||||
if cid ~= c_air then
|
||||
local destroy, fail_reason = check_destroy(drops, p, cid)
|
||||
if destroy == true then
|
||||
data[vi] = minetest.CONTENT_AIR
|
||||
local pp = {x=p.x, y=p.y, z=p.z}
|
||||
table.insert(destroyed_nodes, {vi=vi, pos=pp})
|
||||
elseif destroy == false and fail_reason == "on_blast" then
|
||||
local pp = {x=p.x, y=p.y, z=p.z}
|
||||
table.insert(on_blasts, {pos=pp, cid=cid})
|
||||
end
|
||||
end
|
||||
end
|
||||
vi = vi + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
vm:set_data(data)
|
||||
vm:write_to_map()
|
||||
|
||||
for i=1, #on_blasts do
|
||||
local pp = on_blasts[i].pos
|
||||
local cid = on_blasts[i].cid
|
||||
local def = cid_data[cid]
|
||||
def.on_blast(vector.new(pp), 1)
|
||||
end
|
||||
|
||||
for i=1, #destroyed_nodes do
|
||||
local pp = destroyed_nodes[i].pos
|
||||
local vi = destroyed_nodes[i].vi
|
||||
minetest.check_for_falling(pp)
|
||||
if mod_attached then
|
||||
rp_attached.detach_from_node(pp)
|
||||
end
|
||||
end
|
||||
|
||||
return drops
|
||||
function tnt.explode(pos, radius, sound, remove_nodes, causer)
|
||||
rp_explosions.explode(pos, radius, {sound=sound, griefing=remove_nodes}, causer)
|
||||
end
|
||||
|
||||
-- TNT node explosion
|
||||
@ -415,20 +288,19 @@ local function rawboom(pos, radius, sound, remove_nodes, is_tnt, igniter)
|
||||
end
|
||||
end
|
||||
if remove_nodes then
|
||||
local drops = tnt.explode(pos, radius, sound)
|
||||
play_tnt_sound(pos, sound)
|
||||
tnt.explode(pos, radius, sound, remove_nodes, igniter)
|
||||
--play_tnt_sound(pos, sound)
|
||||
if is_tnt then
|
||||
minetest.log("verbose", "[rp_tnt] TNT exploded at "..minetest.pos_to_string(pos, 0))
|
||||
else
|
||||
minetest.log("verbose", "[rp_tnt] Explosion at "..minetest.pos_to_string(pos, 0))
|
||||
end
|
||||
entity_physics(pos, radius, is_tnt, igniter)
|
||||
eject_drops(drops, pos, radius)
|
||||
--entity_physics(pos, radius, is_tnt, igniter)
|
||||
--eject_drops(drops, pos, radius)
|
||||
else
|
||||
entity_physics(pos, radius, is_tnt, igniter)
|
||||
play_tnt_sound(pos, sound)
|
||||
--entity_physics(pos, radius, is_tnt, igniter)
|
||||
--play_tnt_sound(pos, sound)
|
||||
end
|
||||
add_explosion_effects(pos, radius)
|
||||
end
|
||||
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
name = rp_tnt
|
||||
depends = rp_sounds, rp_crafting, rp_achievements
|
||||
depends = rp_explosions, rp_sounds, rp_crafting, rp_achievements
|
||||
optional_depends = rp_attached, rp_itemdef_defaults, rp_death_messages
|
||||
|