fun_caves/spec_bomb.lua
2016-07-12 02:36:35 -05:00

318 lines
9.9 KiB
Lua

local function disintigrate(pos, radius, node_name, user_name, dropped)
local node_id = minetest.get_content_id(node_name)
local air = minetest.get_content_id('air')
local minp = vector.subtract(pos, radius)
local maxp = vector.add(pos, radius)
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map(minp, maxp)
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
local count = 0
local drops = {}
local p = {}
for z = minp.z, maxp.z do
p.z = z
for y = minp.y, maxp.y do
p.y = y
local ivm = area:index(minp.x, y, z)
for x = minp.x, maxp.x do
p.x = x
if data[ivm] == node_id and not minetest.is_protected(p, user_name) then
data[ivm] = air
count = count + 1
if count % 50 == 0 then
drops[#drops+1] = table.copy(p)
end
end
ivm = ivm + 1
end
end
end
vm:set_data(data)
vm:write_to_map()
vm:update_map()
count = math.floor(count / 3)
for _, p in pairs(drops) do
if count < 1 then
return
end
local dropitem = ItemStack(dropped or node_name)
local take = math.min(count, dropitem:get_stack_max())
dropitem:set_count(take)
local obj = minetest.add_item(p, dropitem)
if obj then
count = count - take
end
end
end
local function floor(pos, blocks, node_name, user_name)
local p = {y = pos.y}
local count = 0
for r = 1, blocks do
for z = -r, r do
p.z = pos.z + z
for x = -r, r do
p.x = pos.x + x
local node = minetest.get_node_or_nil(p)
if node and (node.name == 'air' or node.name == 'default:water_source') and not minetest.is_protected(p, user_name) then
minetest.set_node(p, {name = node_name})
count = count + 1
if count > blocks then
return
end
end
end
end
end
end
-- Bombs
local nodes = {{'fun_caves:pyramid_1', 'default:sandstone'}, {'fun_caves:tree', 'fun_caves:tree'}, {'default:stone', 'default:cobble'},}
for _, node in pairs(nodes) do
local node_name = node[1]
local comp = node[2] or node_name
local node_texture = minetest.registered_items[node_name].tiles
if type(node_texture) == 'table' then
node_texture = node_texture[1]
end
local newnode = fun_caves.clone_node(node_name)
local _, d_name = node_name:match('(.*:)(.*)')
local bomb_name = "fun_caves:"..d_name..'_bomb'
local d_name_u = d_name:gsub("(%l)(%w*)", function(a,b) return string.upper(a)..b end)
newnode.description = d_name_u.." Bomb"
newnode.tiles = {'tnt_top.png', 'tnt_bottom.png', newnode.tiles[1]}
newnode.inventory_image = '[inventorycube{tnt_top.png{'..node_texture..'{tnt_side.png'
newnode.drop = bomb_name
newnode.on_punch = function(pos, node, puncher, pointed_thing)
if puncher:get_wielded_item():get_name() ~= "default:torch" then
return
end
minetest.after(5, function()
local pos_node = minetest.get_node_or_nil(pos)
if pos_node.name ~= bomb_name then
return
end
disintigrate(pos, 5, node_name, puncher:get_player_name(), comp)
minetest.remove_node(pos)
end)
end
minetest.register_node(bomb_name, newnode)
minetest.register_craft({
output = "fun_caves:"..d_name..'_bomb',
recipe = {
{"", comp, ""},
{comp, "tnt:gunpowder", comp},
{"", comp, ""}
}
})
end
-- Floor bombs
local nodes = {{'default:sandstone', 'default:sandstone_block'}, {'default:wood', 'fun_caves:wood_block'}, {'default:stone', 'default:stone_block'},}
for _, node in pairs(nodes) do
local node_name = node[1]
local comp = node[2] or node_name
local node_texture = minetest.registered_items[node_name].tiles
if type(node_texture) == 'table' then
node_texture = node_texture[1]
end
local _, d_name = node_name:match('(.*:)(.*)')
local bomb_name = "fun_caves:"..d_name..'_floor_bomb'
local d_name_u = d_name:gsub("(%l)(%w*)", function(a,b) return string.upper(a)..b end)
local newnode = fun_caves.clone_node(node_name)
newnode.description = d_name_u.." Floor Bomb"
newnode.inventory_image = '[inventorycube{'..node_texture..'{'..node_texture..'{'..node_texture..'^fun_caves_expand.png'
newnode.drop = bomb_name
newnode.on_punch = function(pos, node, puncher, pointed_thing)
if puncher:get_wielded_item():get_name() ~= "default:torch" then
return
end
minetest.after(5, function()
local pos_node = minetest.get_node_or_nil(pos)
if pos_node.name ~= bomb_name then
return
end
floor(pos, 100, node_name, puncher:get_player_name())
minetest.set_node(pos, {name = node_name})
end)
end
minetest.register_node(bomb_name, newnode)
if not minetest.registered_items[comp] then
newnode = fun_caves.clone_node(node_name)
newnode.description = newnode.description .. ' Block'
minetest.register_node(comp, newnode)
minetest.register_craft({
output = comp,
recipe = {
{node_name, node_name, node_name},
{node_name, node_name, node_name},
{node_name, node_name, node_name}
}
})
end
minetest.register_craft({
output = "fun_caves:"..d_name..'_floor_bomb',
recipe = {
{comp, comp, comp},
{comp, "tnt:gunpowder", comp},
{comp, comp, comp}
}
})
end
local mass_nodes = {'fun_caves:tree', 'default:tree', 'default:jungletree', 'default:acacia_tree', 'default:aspen_tree', 'default:stone', 'default:sandstone', 'default:desert_stone', 'fun_caves:stone_with_algae', 'fun_caves:stone_with_moss', 'fun_caves:stone_with_lichen'}
local mass_tools_list = {'default:axe_bronze', 'default:axe_diamond', 'default:axe_mese', 'default:pick_bronze', 'default:pick_diamond', 'default:pick_mese'}
local mass_tools = {}
for _, tool in pairs(mass_tools_list) do
mass_tools[tool] = true
end
local mass_minerals_list = {'default:gravel'}
local mass_minerals = {}
for _, min in pairs(mass_minerals_list) do
mass_minerals[min] = true
end
for name, _ in pairs(minetest.registered_nodes) do
if name:find('stone_with') then
mass_minerals[name] = true
end
end
local function default_rightclick(pos, node, clicker, itemstack, pointed_thing)
if itemstack:get_definition().type == "node" then
return minetest.item_place_node(itemstack, clicker, pointed_thing)
end
return itemstack
end
for _, node in pairs(mass_nodes) do
minetest.override_item(node, {on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
local tool = itemstack:get_name()
if not mass_tools[tool] then
return default_rightclick(pos, node, clicker, itemstack, pointed_thing)
end
local tool_type, maxr
if tool:find('axe') then
if minetest.get_item_group(node.name, "tree") == 0 then
return default_rightclick(pos, node, clicker, itemstack, pointed_thing)
end
tool_type = 'axe'
maxr = {x = 2, y = 20, z = 2}
elseif tool:find('pick') then
if node.name ~= 'default:sandstone' and minetest.get_item_group(node.name, "stone") == 0 then
return default_rightclick(pos, node, clicker, itemstack, pointed_thing)
end
tool_type = 'pick'
maxr = {x = 2, y = 4, z = 2}
else
return default_rightclick(pos, node, clicker, itemstack, pointed_thing)
end
local player_pos = vector.round(clicker:getpos())
local player_name = clicker:get_player_name()
local inv = clicker:get_inventory()
if not (player_pos and player_name and inv) then
return default_rightclick(pos, node, clicker, itemstack, pointed_thing)
end
pos = vector.round(pos)
local max_nodes = 60
local minp = vector.subtract(pos, 2)
local maxp = vector.add(pos, maxr)
if pos.y >= player_pos.y then
minp.y = player_pos.y
end
local air = minetest.get_content_id('air')
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map(minp, maxp)
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
local drops = {}
local names = {}
local diggable = {}
local tree_like = {}
local leaf_like = {}
local stone_like = {}
local count = 0
local p = {}
for y = minp.y, maxp.y do
p.y = y
for z = minp.z, maxp.z do
p.z = z
local ivm = area:index(minp.x, y, z)
for x = minp.x, maxp.x do
p.x = x
if not names[data[ivm]] then
names[data[ivm]] = minetest.get_name_from_content_id(data[ivm])
end
if not diggable[data[ivm]] then
if tool_type == 'axe' then
diggable[data[ivm]] = minetest.get_item_group(names[data[ivm]], 'choppy') or 0
diggable[data[ivm]] = diggable[data[ivm]] + minetest.get_item_group(names[data[ivm]], 'snappy') or 0
diggable[data[ivm]] = diggable[data[ivm]] + minetest.get_item_group(names[data[ivm]], 'fleshy') or 0
elseif tool_type == 'pick' then
diggable[data[ivm]] = minetest.get_item_group(names[data[ivm]], 'cracky') or 0
end
end
if not stone_like[data[ivm]] then
stone_like[data[ivm]] = minetest.get_item_group(names[data[ivm]], 'stone') or 0
stone_like[data[ivm]] = stone_like[data[ivm]] + (names[data[ivm]] == 'default:sandstone' and 1 or 0)
end
if not tree_like[data[ivm]] then
tree_like[data[ivm]] = minetest.get_item_group(names[data[ivm]], 'tree') or 0
end
if not leaf_like[data[ivm]] then
leaf_like[data[ivm]] = minetest.get_item_group(names[data[ivm]], 'leafdecay') or 0
end
local dig_it
if tool_type == 'axe' then
dig_it = tree_like[data[ivm]] > 0 or leaf_like[data[ivm]] > 0
elseif tool_type == 'pick' then
dig_it = stone_like[data[ivm]] > 0 or mass_minerals[names[data[ivm]]]
end
if count < max_nodes and diggable[data[ivm]] > 0 and dig_it and not minetest.is_protected(p, player_name) then
drops[data[ivm]] = (drops[data[ivm]] or 0) + 1
data[ivm] = air
count = count + 1
end
ivm = ivm + 1
end
end
end
vm:set_data(data)
vm:write_to_map()
vm:update_map()
for id, number in pairs(drops) do
for i = 1, number do
local drops = minetest.get_node_drops(names[id], tool)
minetest.handle_node_drops(pos, drops, clicker)
end
local tp = itemstack:get_tool_capabilities()
local def = ItemStack({name=names[id]}):get_definition()
local dp = minetest.get_dig_params(def.groups, tp)
--print(names[id], dp.wear, number)
itemstack:add_wear(dp.wear * number)
end
return itemstack
end, })
end