From 1e90a52ec8a643dc80a5d667b7ad5b86b8beccb6 Mon Sep 17 00:00:00 2001
From: Duane Robertson <duane@duanerobertson.com>
Date: Wed, 5 Oct 2016 22:32:44 -0500
Subject: [PATCH] Add tools.

---
 init.lua                             |   2 +-
 textures/loud_walking_chainsaw.png   | Bin 0 -> 1137 bytes
 textures/loud_walking_expand.png     | Bin 0 -> 152 bytes
 textures/loud_walking_flare.png      | Bin 0 -> 142 bytes
 textures/loud_walking_flare_gun.png  | Bin 0 -> 2106 bytes
 textures/loud_walking_jackhammer.png | Bin 0 -> 949 bytes
 tools.lua                            | 400 +++++++++++++++++++++++++++
 7 files changed, 401 insertions(+), 1 deletion(-)
 create mode 100644 textures/loud_walking_chainsaw.png
 create mode 100644 textures/loud_walking_expand.png
 create mode 100644 textures/loud_walking_flare.png
 create mode 100644 textures/loud_walking_flare_gun.png
 create mode 100644 textures/loud_walking_jackhammer.png
 create mode 100644 tools.lua

diff --git a/init.lua b/init.lua
index 67dff27..ef38ee4 100644
--- a/init.lua
+++ b/init.lua
@@ -192,7 +192,7 @@ dofile(loud_walking.path .. "/deco_caves.lua")
 --dofile(loud_walking.path .. "/wallhammer.lua")
 dofile(loud_walking.path .. "/mapgen.lua")
 dofile(loud_walking.path .. "/wooden_buckets.lua")
---dofile(loud_walking.path .. "/tools.lua")
+dofile(loud_walking.path .. "/tools.lua")
 --dofile(loud_walking.path .. "/molotov.lua")
 --dofile(loud_walking.path .. "/elixir.lua")
 --dofile(loud_walking.path .. "/chat.lua")
diff --git a/textures/loud_walking_chainsaw.png b/textures/loud_walking_chainsaw.png
new file mode 100644
index 0000000000000000000000000000000000000000..ec8d57b4ce8a6ca840fd496d25995a786ea6934d
GIT binary patch
literal 1137
zcmV-%1djWOP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800006VoOIv0RI60
z0RN!9r;`8x010qNS#tmY4#WTe4-x@Giw3m-000McNliru;0F!~A}ag0u6O_d1O7=w
zK~z}7y_QRCR8<_tf9KpgGq*F-&a{PgO6!B#Hxd#kqM?%bU?FWJh>r!2m>>&NC$UN6
zLPJ<UV$dKlK6aR>Y0w0si&_>Mr3z)ChJ*lGnkdjHly=(Av@<YsAAc9a!{yNQ@~v)8
zZod1=`M&eN2NtL!N4`Wv0NA?qh5mKx9!u8MEo<d|skXKTfMhcH$NBT;@}r}p&W;`1
z{{qbB<|b9Dk6tK1dwYihR9#(dZAZrnqpGS(x3#q`udc3M(%bt6z5~q6%m6SypS1x@
z(^QsaVOdswaBxuj4iJyW0f@z70f1;UDv?N3a=Dz*+S)3<1B60B0Cn@`O;ZF_C={5U
zPKoQfW>Zs>{{Ryc695tj1oDn!OE#NDM06|`w?{@s{4b$tngDp7CxJi!5m8EMw7xe_
zbD;pSSPVe9t`h>3Qc6TTnVz0;4MY2X3S8F%5YsemKmfEhlx10gwzhV;565sC0NZwo
zBqGXnT@{H$yfbIc_}_tWI0ArWg%rgM#4t3DV;2gAy#EnIqeXyBCS%-Q^E~m==}fSt
zrN#dUGMTwsAm#u6n69XZsZ3_h{|IcmP&ClWz1;z=6_yorQmHBbBdDyb1R$MG>)Rc0
z99ynkn{Z}lXZ;6o92bC!ii+ZPdp2dE5Dk^#$jYAG;@cpSy+9B?|MjA(e*~4Yix&CG
zF_oAZVR&<Ded4X1M@#i9sVp*d>*Y;%*XCYUI{duEFQu1WYSfdFx$EdMS7Bxabr7|v
z0CzwJS?f$1uXCL$bJBfARufewTtB9;s)bY;)VuJ-F&^AK&iJBrK!#Z34XJH}$n}rz
zJGJV>o2Pl4a4v;hxeU4>oSlMCPJyeiH$2P}i&{dpiQm;j^7Y;ylVz4W_2-4-2M;(o
zr9b`(Rlf{wXjrubwy%MJLb)DZsQ^aFgD2GI9eDr4f7f?C`St@%tuI~t<#Nrd8}sF6
zP*~Ck<8#na4RdL{@C?V^`<n}keiQEN>$~&Z+gY`L&z5>`{n|(6+fV!C`(#XHKXUas
zY}w3<zRZC`hYkU-vppQN=QH1=uKdHvSI*HHALT^Np2E(dda{*(Te_!O$WDyEi*a!(
zQ1Nu5J)OB0n27DO6Y>GSG0&RJ6ovd*w$+^ADE_G#fY*Bavpt))+?jgb9=fHU%xITS
z5!}@n05@i@zEc)7X=rFjZ0uTX=zV-AV{|viDfj(fuxr;YJuoovk%$x$i9}byC^rF=
zhull93kEoR_^=1Kxm@-KrBrfwc(`~Cl6&)AFhFN#Cnslxp`qj5hSnPzmp5+s`Kf3K
zSO(;|AF2vL$BLDTP-XdN&o2GR?N+CyhXLs!SgOZ=zdww~y+A@q00000NkvXXu0mjf
Ddk_{Q

literal 0
HcmV?d00001

diff --git a/textures/loud_walking_expand.png b/textures/loud_walking_expand.png
new file mode 100644
index 0000000000000000000000000000000000000000..9962ba7eea9c380d3017da249aa858acff321c2e
GIT binary patch
literal 152
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP|(ZM
z#WBR<bh3@2#*g`ooDqBK&!1>uU$8p8g;U^C$7KZx=DR6LCi4YE{`4=JDB;Yp>UcVb
w<~kWxW-gCDw=Q9!rJge%ojKx>S;odtx54&q=fWkiKvNk!UHx3vIVCg!03wwv>;M1&

literal 0
HcmV?d00001

diff --git a/textures/loud_walking_flare.png b/textures/loud_walking_flare.png
new file mode 100644
index 0000000000000000000000000000000000000000..e2e045bbf9a9904baed8a581392760d30750a906
GIT binary patch
literal 142
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b
z3=G`DAk4@xYmNj^kiEpy*OmPNyC92-s_lmZUx7l>o-U3d7N?UFBv=p2{%L2b$(rHT
foGD^pV8Fm&eVhHa#KZs2KxGV`u6{1-oD!M<0pcYJ

literal 0
HcmV?d00001

diff --git a/textures/loud_walking_flare_gun.png b/textures/loud_walking_flare_gun.png
new file mode 100644
index 0000000000000000000000000000000000000000..c7dc74b356d94f9a7c552420f477f39a4cfda599
GIT binary patch
literal 2106
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

literal 0
HcmV?d00001

diff --git a/textures/loud_walking_jackhammer.png b/textures/loud_walking_jackhammer.png
new file mode 100644
index 0000000000000000000000000000000000000000..0b3accce6f08f41d3b0a1cc9d075a78836656cf9
GIT binary patch
literal 949
zcmV;m14{gfP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800006VoOIv0RI60
z0RN!9r;`8x010qNS#tmY4c7nw4c7reD4Tcy000McNliru;0F!~GAGZ(z?1+0142ne
zK~z}7#g<QK9aR*@zjN=r$(xxs@6k4CN}AXfMUi$}6rl?jrun0^*a{YFi6x+*7PX6l
z72H+)gGx8u2ufc-)KnT;lG<b=CA3|sSSVCMEoqw?V_x$9%zHEU-s9rc@LW3cIysA3
z40GoG=DXiF=K?Y6m)~v+0GPh?1HbcO(K<6ZD-g3{H4*@3w!lD7_qxozTj>F`a3roI
z0K9rxBY+l+wFF2gL}CEuWEzNgi*kzznNkN>SS+nB+6W^PhGDufd}8Nz{n^;L6Ch&O
zmM0JFeNw0HfqdRymO_wi+toEm!SYJ^_1Vi;mDc)|Bmh=?_p_&zl1bhXTY>jap0<Oa
zet;Pi1i`KopL}km22dQI!LcKULdS86jYbu&>t1^M&6iYhd?p<L27wvWP<}y5kHg5r
z^!Mj1rJYz&jGf<G*B)abCA8M)-EozI-+gknmN~T)RO@-%yxkSn8a@EvPHAVlF*FQh
zG6u#ZI~K$TFaq_4jEoU$13(05Et&2Kkn=blfM*AG0{}`Tg`V!E+|rT;Fr547)6D%(
z!Sc=BnE%rV%fjPYW7d+!L}4K8OtdRf;!1Z{T@|+ebbl0x{u)H#f$z|@K?>ieZLZVo
z_dJ5{o1T1LP(HT^b@!q60*s8l1^{^e)jk3M$H5j!Vob{Bo=a&U2w$x)EN-FBIlTDR
zQ`ELC7#P~qoLF`S=g*D<04leJ1Er!&Enr!%8#vh-+-#tv)XTZPpF06y@BSB1uT=m5
z7bYj-Ps7&ck;5<lTFBkmn9W8Vl?u^+&Y?_}=hfFAeWSm;P<n9X^cSZ#w`Cj;4DK-i
z$QT1-7{<U50M}s<F$6JOhvC=;0K+gGBFgpmKg~kQ=0{9TP<#cZCRROicy#n&Pd6Tp
z6dgbQUWZyKLuw5O>A?4t`uN>ByKhtDgM|`bzj*O{u{|CbY<eK;xH$XmmjHm;{P4Ar
zBi1A33M^v)A%JX$u6})L?vKo-AGZU*zUK~7wbC3+7p9VUprtvS8-m?C38zyVDWoDI
zK?EiO2?1qoteJnGJ@d^Nx5WdkW%o`tRe7dkng9u4Gl0L1L7`fc^8-VV&Hy+5_n+_|
XDg;B|kt5M>00000NkvXXu0mjfIajPK

literal 0
HcmV?d00001

diff --git a/tools.lua b/tools.lua
new file mode 100644
index 0000000..cac26c1
--- /dev/null
+++ b/tools.lua
@@ -0,0 +1,400 @@
+local function floor(pos, blocks, node_name, user_name)
+	if not (pos and blocks and node_name and user_name and type(blocks) == 'number' and type(node_name) == 'string' and type(user_name) == 'string') then
+		return
+	end
+
+	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
+
+
+if minetest.get_modpath('tnt') then
+	-- Floor bombs
+	local nodes = {{'default:sandstone', 'default:sandstone_block'}, {'default:wood', 'loud_walking: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
+		if not minetest.registered_items[node_name] or (not minetest.registered_items[comp] and not comp:find('^loud_walking')) then
+			break
+		end
+
+		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 = "loud_walking:"..d_name..'_floor_bomb'
+		local d_name_u = d_name:gsub("(%l)(%w*)", function(a,b) return string.upper(a)..b end)
+
+		local newnode = loud_walking.clone_node(node_name)
+		newnode.description = d_name_u.." Floor Bomb"
+		newnode.inventory_image = '[inventorycube{'..node_texture..'{'..node_texture..'{'..node_texture..'^loud_walking_expand.png'
+		newnode.drop = bomb_name
+		newnode.on_punch = function(pos, node, puncher, pointed_thing)
+			if not (pos and puncher) then
+				return
+			end
+
+			local wield = puncher:get_wielded_item()
+			if not wield or wield:get_name() ~= "default:torch" then
+				return
+			end
+
+			minetest.after(5, function()
+				local pos_node = minetest.get_node_or_nil(pos)
+				if not (pos_node and 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 = loud_walking.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 = "loud_walking:"..d_name..'_floor_bomb',
+			recipe = {
+				{comp, comp, comp},
+				{comp, "tnt:gunpowder", comp},
+				{comp, comp, comp}
+			}
+		})
+	end
+end
+
+local function power(player, pos, tool_type, max)
+	if not (player and pos and tool_type) then
+		return
+	end
+
+	local player_pos = vector.round(player:getpos())
+	local player_name = player:get_player_name()
+	local inv = player:get_inventory()
+	pos = vector.round(pos)
+	local node = minetest.get_node_or_nil(pos)
+	if not (node and player_pos and player_name and inv) then
+		return
+	end
+
+	local maxr, node_type
+	if tool_type == 'axe' then
+		node_type = 'choppy'
+		maxr = {x = 2, y = 20, z = 2}
+	elseif tool_type == 'pick' then
+		node_type = 'cracky'
+		maxr = {x = 2, y = 4, z = 2}
+	else
+		return
+	end
+
+	if minetest.get_item_group(node.name, node_type) == 0 then
+		return
+	end
+
+	local max_nodes = max or 60
+	local minp = vector.subtract(pos, 2)
+	local maxp = vector.add(pos, maxr)
+	local yloop_a, yloop_b, yloop_c
+	if pos.y >= player_pos.y then
+		minp.y = player_pos.y
+		yloop_a, yloop_b, yloop_c = minp.y, maxp.y, 1
+		if node_type == 'cracky' and pos.y - player_pos.y < 3 then
+			maxp.y = player_pos.y + 3
+		end
+	else
+		maxp.y = player_pos.y
+		yloop_a, yloop_b, yloop_c = maxp.y, minp.y, -1
+	end
+
+	local air = minetest.get_content_id('air')
+	local vm = minetest.get_voxel_manip()
+	if not vm then
+		return
+	end
+
+	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 = yloop_a, yloop_b, yloop_c 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
+					diggable[data[ivm]] = minetest.get_item_group(names[data[ivm]], node_type) or 0
+					if node_type == 'choppy' then
+						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
+					end
+
+					if names[data[ivm]] and names[data[ivm]]:find('^door') then
+						diggable[data[ivm]] = 0
+					end
+				end
+
+				if count < max_nodes and diggable[data[ivm]] > 0 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()
+
+	local tool = player:get_wielded_item()
+	for id, number in pairs(drops) do
+		for i = 1, number do
+			local drops = minetest.get_node_drops(names[id], tool:get_name())
+			minetest.handle_node_drops(pos, drops, player)
+		end
+
+		local tp = tool:get_tool_capabilities()
+		local def = ItemStack({name=names[id]}):get_definition()
+		local dp = minetest.get_dig_params(def.groups, tp)
+		if not dp then
+			return
+		end
+
+		tool:add_wear(dp.wear * number)
+	end
+
+	return tool
+end
+
+minetest.register_tool("loud_walking:chainsaw", {
+	description = "Chainsaw",
+	inventory_image = "loud_walking_chainsaw.png",
+	tool_capabilities = {
+		full_punch_interval = 1.0,
+		max_drop_level=1,
+		groupcaps={
+			choppy={times={[1]=2.50, [2]=1.40, [3]=1.00}, uses=80, maxlevel=2},
+		},
+		damage_groups = {fleshy=4},
+	},
+	on_use = function(itemstack, user, pointed_thing)
+		if not (user and pointed_thing) then
+			return
+		end
+
+		minetest.sound_play('chainsaw', {
+			object = user,
+			gain = 0.1,
+			max_hear_distance = 30
+		})
+
+		return power(user, pointed_thing.under, 'axe')
+	end,
+})
+
+minetest.register_tool("loud_walking:jackhammer", {
+	description = "Jackhammer",
+	inventory_image = "loud_walking_jackhammer.png",
+	tool_capabilities = {
+		full_punch_interval = 1.0,
+		max_drop_level=1,
+		groupcaps={
+			cracky = {times={[1]=4.00, [2]=1.60, [3]=0.80}, uses=80, maxlevel=2},
+		},
+		damage_groups = {fleshy=4},
+	},
+	on_use = function(itemstack, user, pointed_thing)
+		if not (user and pointed_thing) then
+			return
+		end
+
+		minetest.sound_play('jackhammer', {
+			object = user,
+			gain = 0.1,
+			max_hear_distance = 30
+		})
+
+		return power(user, pointed_thing.under, 'pick')
+	end,
+})
+
+minetest.register_craft({
+	output = 'loud_walking:chainsaw',
+	recipe = {
+		{'', 'default:diamond', ''},
+		{'', 'default:steelblock', ''},
+		{'default:copper_ingot', 'default:coalblock', ''},
+	}
+})
+
+minetest.register_craft({
+	output = 'loud_walking:chainsaw',
+	recipe = {
+		{'', '', ''},
+		{'', 'loud_walking:chainsaw', ''},
+		{'', 'default:steelblock', 'default:coalblock'},
+	}
+})
+
+minetest.register_craft({
+	output = 'loud_walking:jackhammer',
+	recipe = {
+		{'default:copper_ingot', 'default:coalblock', ''},
+		{'', 'default:steelblock', ''},
+		{'', 'default:diamond', ''},
+	}
+})
+
+minetest.register_craft({
+	output = 'loud_walking:jackhammer',
+	recipe = {
+		{'', '', ''},
+		{'', 'loud_walking:jackhammer', ''},
+		{'', 'default:steelblock', 'default:coalblock'},
+	}
+})
+
+
+local function flares(player)
+	local dir = player:get_look_dir()
+	local pos = player:getpos()
+	if not pos then
+		return
+	end
+	pos.x = pos.x + dir.x * 10
+	pos.y = pos.y + dir.y * 10
+	pos.z = pos.z + dir.z * 10
+	pos = vector.round(pos)
+
+	local air = minetest.get_content_id('air')
+	local flare = minetest.get_content_id('loud_walking:flare')
+	local vm = minetest.get_voxel_manip()
+	if not vm then
+		return
+	end
+
+	local r = 8
+	local minp = vector.subtract(pos, r)
+	local maxp = vector.add(pos, r)
+	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
+	for i = 1, 50 do
+		local x = pos.x + math.random(2 * r + 1) - r - 1
+		local y = pos.y + math.random(2 * r + 1) - r - 1
+		local z = pos.z + math.random(2 * r + 1) - r - 1
+		local ivm = area:index(x, y, z)
+		if data[ivm] == air then
+			data[ivm] = flare
+			count = count + 1
+		end
+	end
+	vm:set_data(data)
+	vm:calc_lighting(minp, maxp)
+	vm:update_liquids()
+	vm:write_to_map()
+	vm:update_map()
+
+	return count
+end
+
+minetest.register_node("loud_walking:flare", {
+	description = "Fungal tree fruit",
+	drawtype = "plantlike",
+	visual_scale = 0.75,
+	tiles = {"loud_walking_flare.png"},
+	paramtype = "light",
+	sunlight_propagates = true,
+	light_source = 15,
+	walkable = false,
+	diggable = false,
+	pointable = false,
+	is_ground_content = false,
+})
+
+minetest.register_tool("loud_walking:flare_gun", {
+	description = "Flare Gun",
+	inventory_image = "loud_walking_flare_gun.png",
+	tool_capabilities = {
+		full_punch_interval = 1.2,
+		max_drop_level=0,
+		groupcaps={
+			snappy={times={[2]=1.6, [3]=0.40}, uses=10, maxlevel=1},
+		},
+		damage_groups = {fleshy=2},
+	},
+	on_use = function(itemstack, user, pointed_thing)
+		if not user then
+			return
+		end
+
+		local count = flares(user)
+		itemstack:add_wear(count * 400)
+		return itemstack
+	end,
+})
+
+minetest.register_craft({
+	output = 'loud_walking:flare_gun',
+	recipe = {
+		{'', '', ''},
+		{'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'},
+		{'', 'tnt:gunpowder', 'group:stick'},
+	}
+})
+
+minetest.register_craft({
+	output = 'loud_walking:flare_gun',
+	recipe = {
+		{'', '', ''},
+		{'', 'loud_walking:flare_gun', ''},
+		{'', 'tnt:gunpowder', ''},
+	}
+})
-- 
GitLab