From 9004ab3322f8c4288c1197a963c887be8e14ec92 Mon Sep 17 00:00:00 2001 From: Zefram Date: Thu, 3 Jul 2014 19:42:29 +0100 Subject: [PATCH] Handheld prospecting tool The new tool will say whether a target block type is present in a specified region, to allow for more targeted digging. It is deliberately quite weak, with several limitations: only stores enough charge for a small number of shots; target can only be set by pointing at an example node; range is limited; accuracy is less than 100%. Some of these limitations should probably be ameliorated, but not entirely eliminated, in the future when we have a better idea of game balance. The inventory image is only a placeholder. --- technic/sounds/technic_prospector_hit.ogg | Bin 0 -> 4698 bytes technic/sounds/technic_prospector_miss.ogg | Bin 0 -> 4481 bytes technic/textures/technic_prospector.png | Bin 0 -> 367 bytes technic/tools/init.lua | 1 + technic/tools/prospector.lua | 126 +++++++++++++++++++++ 5 files changed, 127 insertions(+) create mode 100644 technic/sounds/technic_prospector_hit.ogg create mode 100644 technic/sounds/technic_prospector_miss.ogg create mode 100644 technic/textures/technic_prospector.png create mode 100644 technic/tools/prospector.lua diff --git a/technic/sounds/technic_prospector_hit.ogg b/technic/sounds/technic_prospector_hit.ogg new file mode 100644 index 0000000000000000000000000000000000000000..3a8ad2d137ae3a9016a076c8f39dfed257da7e2b GIT binary patch literal 4698 zcmai1e>~IM|37|@Tz4XkyL_fBn<%R(tCW#2cCmT;c}LMgYf`hDZdX?}a+h3p%_?{K z(zT*X?z&M_QXf((iTp~^tsDArrQ5xxl)mTvM!A1|&g1O8*ZXyzub=0<&N=VE_;@bR z1yhat=5Ibq{>V97remw~^|l?ci6WGtlYSok10dZ^2m3##6NpNFY^WqUQukFT!z|*% zjJ8*AQjIel4Npu?SRA+`p0qVFHWX7%@*^#Ep}EjtCsDX@2^+&HaT z7QqW^&j9lb;?jVq8)Q+QT}hE=b`)iAYaRknfql$WOR0>Bvy+nD!{rhOcSvP3ATJT+ z;XS7x-i!n|%EZl+K6Y_4l{|49BTBs);dsa!B1u2@JXatoXF#yMt8b9RkTFD*UU8zx zG8$aYSxNO>DLEN`xLms{ndO;XAn|h@vysL#Q>`X#*fV|eB!zIrcRIzX6NFh zS>?JQ9RPi3hVI2(?W0(CI|S*f7WU5QQA)lwCJu9mZ%f=bPL@n0`RJ0aI9aBY^7C_vfs-Y;t zWRh~w>}oA=M0wj=o^DW?Uxn1did}gH2dW@tP?4Bh;IDy{Z_O^wPyQ%RgsQ?G&l;Z+ zRTk)L>BSo5PpyrR3cULCfeQZ-g5j_v!+1ULSqC=Wr{dZM6G-dLV{Mi`Won09jBO+; z&u4dr5=s;+ape5%9G1gm!gYZM&MwoE<2(I`&9=)T>}aN*D9T_tmX#jMS$f0ix0~2w z<%{y)%vPDw8t`6=DjGOkp=)QjV3;vjAUP8nDX6I8u&8PU#{|nC3Fh9@(0Wr|FseB= zn|eaE!^E+4GMyxJY5)lQi+IO;-lzVGc-x#DJR5fB_NA`vTyI3o?^22*&Zb3mXY#aZ zeXx&-H-;iPfbv#{ZJ`e4ahe$e#8?^QgetCuK{={uW;h%@IGd`5uhc=6qQ!4O zb+FBk0@p{q4*Ypi=$pI&-T^#JCbAFG*_LFsg?FGOugk)_BcFbY?iw6|ur1jgAxMN3 z8&Q(k%h+s7glplA%t5$HHd4jEO&9irAbnOyM>RicG%ZXi?pwz0L0{ph7{2nVg?)!U zszSO#kly8R)HOJT7mV;Dpysc65nV`FXByPp!DaW%K@cU<)4@lS;+PbqFO=8Qg+z3w z^>${)bf#S?Jz1O7eCpIMr_0ArFCMS`^SQ#WJpgs6V_h)94yzJ!#lk2H@2)vWhtiuX zhFa2M#QdJFb$7(xNIoAmna}6#XKGh3gdd$oUUA8>Qnct6R&r9Z5{itxNqnSuisZ>(c8}mp}xKpUd$nJU&8a+pb&%? z#_!Q0VWVl#iQh-l`Uyyv7N$I_LwR(gHcdS|D<7%OgdPkY7V^UPJRW*iw=_i@1!Xli z>rSmczda>u4Xk-XA^^Gp6ur!>avXT14+v6~R{%5HQUbREsx*(&K#<;KP_0EAPik2v zhqIp`$zv=ei@s!0iq%0Z|6*yUCsmWliQHPzQ4qP`RoWIwQC9`A_Lr$`q6Dt%bC}mu z2jvV0wE`Qs$#6U>fmMvp ztSuU-%AeL5#MuuA{8==pDoOLClbPULGCPh!zG@YBs-nuqi#ln%!z!-gB5Is`Rn9tq z8b442x5FYBqaELJFBrZ(o#aO#q~k^cE2Jj<`Fsynt^B?;oNDjIF#;F{`; zEZ1}vtb*&-N>I+|CbANpuZD|SE^6~Q0$OLJ=;g&jow4PvgZCx)D`za@PSuP)-2IYT z9VxiwK1PxTX*wcBBj{yvKTUgIG6FA{U*#|cZKWfZjWzXWVxv^@M@lWlvnVJI<`(Y>A5&SL=E*k#PcW1l_x^}NYJ z^s@)$8>qBw>o1lsS+aPEv$ON!#m;-^4htO|D2|I3IlE@$1W}AMN&ht$16|*d?u(C7 z7I~4?a_@rB7cMK$xj*s(7iqhqZco<-TmS2xBfSyD=om7 zAVLo^9s^s(1MR+tMhi!G{=EBASP)lb2uiUiF#!N5l@ZaAh#vT+S&4EA6Ca%2d3o-I zmN>7pJz5N&YBUAK{?1S*-v4F*%11NM*NG!*sz1NHjWpVnHT?cT(Q&uW0IZ!EEoJZM zab4hc-Vx>5);>7<`Q@FY(LsogX0o^2fQPeYfB|L6mI<~l5KSmhZglgs^335kSp|>i zpq?=konBhsV+_7sy%uHexwobT#%Vjay?A$B@n#t2xtU=C%E%u=9boyV69#_v$&ojc zZjYdI^Qn!zPXfT_k_qG#K3h}06M79(qJ5WyrR4CxR1?Q8adp9YTg>UYw^L3J`f9(e z#4<7hH|ZHI^{*f9f%>=Kp*lXIn;_Z?O~{5BNJy&Ooj`i5HR=b5zW1PJAGmPf{p^C_ z31#rI!du_`wq||$%Ov(zT@TJC-~qpyyBG2vj6M3#txKx@OZ{zat#n0}O=Wp*<%M}q zKji%VUGrjp{_fqWyVt#4%Rf~4s`*(e-?jF`vbGP_Pd~gqU^MD3e?qu^@;!V*!KY5I zjE?wc^w?Qo(yCMVHahpjLp|kt>+Ahmmo2h((9k_u6sT_iG*{jFJK*i|&t9*M0`*VY zV^Ch<+rn*2F7L#RgMRH6%3Vw5jJ&CW4Zz(B*&G!1EP6Qb@=i+p-m%wxK5TQ#8Ea^~ zNf)f{oi~MAa(NqW+_Yc2W{a!{vZmXEa$`U^o_HKpzvo`zOQO#mnJ9rp^!l9!-oJe2$>oA=a@8+Q343Lhcz5clgNI$5l!cV-vWCy`} zuc$!!ieJH=(QmW8JV<%t6A9Ka=0V)m11&=bG!G}1Jivie>jm@Y6Tri7?r*;*nVTUz zmDXeP6WmxPnk9)`USfs#dHb7EwQYyP$^I^flY`~oKdPMTzB(@Cb|LN0S!Rzm?K9FB nZ8NzJOzRhiYgURA)>hrQ2~c(a*!fLv&OP&;Z_YV$ z=H9vS85t7b047>f*8R6J5&u&892bDwv_2;-ONA+L`QKxI0OUvDZ2w1b@tEaQ!z{58 zkx3EYnf&sV_PL{-W)2)p%G!|mZhTG#b!}GK3L7~!mKqky4rRkmWlGXBSE)Z%tW#%X zC~{dC9U1yV?P0C6$JwK1hX$LMLvdb+KTZ2vms{9#)Uvzf;LkRbLDY$UnZ>{bInsE#N$B^8@8 zi>*ba1Z`oX1IULJ0H@(ZOBO6KEV{TH?Qc_tdAR z-N^SU4sFk$OmaS1=(*pui92k(U7hS%B{Xwq8DpBa=)Wj#QrtF$W445gUXEyx#fm`;UJ z*)I1wMkz)g?6&?yYsD9rI-nHaIXYw{PC;xqTasbCQN+TXt8TCem#vx9#a?OtVWYh9 zyP>ZB8YBN+&)v*g!+Zk0d?O-c*c0vmq6mRH5)w0cNh=C0BV4B%yA2@x2KbeEe!zizfyXAT6=gTkK(4+-2H@ z%OUYkIPpG_Vv?YjgZ509i{~lDa}~Yea>-mdx_oM)!Uh{Iv}Nh!_NG z#dVvD8#Wi$Z!W!Cq|e-2QQuJY&bhh=#}3~Af8E_y;4}boX-jfwOAwj>fr2f&`5sty zDgR{C1UVt+FLUfM_V`4?geKLO6ZLXL zJ}|Ma*oM6%RdqF0mh$d4R-R$jR`)OCj@0&dF$;`VB0GK0X@ni^(OJRM8k}I#@IVar z75fakos!cXdygjQ<_6C)b#j+9e04=EG}lQ#5Sm(+XWur$+jC5lH13;OrsdgRo1qbK zfj{?}OJ&n>Q6vC9_dwiOIzw7F%UXt<D^rBKEpXKW8ZFXmI>antVTn3 z?1*vq+Z)qXU& zFYkJvE~PK;RQ=b-)}1?e@SDSpzaM`0_hbLMZ;0((iaBIiBt}Jv%}R+{Df1EZPe&~k z0*M;3ENMAE=V0ZUtkw3D@6T$Y~- z;joS-2Jh3rM<{&INkdp2Nn8e9Qz~=`H0gy)=_Yb?u({lj1_uVDYg;?^ zsFy>Knvlq6fqZ6T{lvB?>>$xY1&l3lJsAeF*X7!0X|LN@dYQhD-)kV+ziUZuUm zvLp%Dm?2dhyDtIR0SDrQY)G}ve5a3>Ij7b;ok{QXO+VPw>>tgtPj2x|Z#scZPVdwU zcVd(8Y=w`*W#&6o(#F<~fox^#f2vfM8k(h&rLCA(txn0RUruN)!N@xjge6VQQdtRi z+r;F>&5$bFJO&3KRh%%qg`8a)K2|0D1`cGeF^^QK9?W`Ca2UXz@_)A$JR^uvK_mN_D- zCh#3xJ|sO!HtosrnD5F8FX1}Z7z{8|t4i1eQ|%RLT)B!UjBRKhNNY4|5)ffihkrV( zsXl3=xv%O2Shv2}jobl>Fl$a{lB)Z}co~w-?vtt>o~Z0gYYeyE&=5}@A*CN|9lQCr zhpZN9_Jzo&RBeLUB2_)Y4wF0B<2N*q-~n@G3D+8+ee|QtDgZvwID$n5JKt}l?VDce zJOhiC;0mb3G`PS5}gjuVhEz}`G zn=Jv8MyGTv>||>jWznZ3la?rCVmO#vA|GBRvOKBNPw5b3QU{l60%t&C;SrP)0ZWz4 zWB8%ItG;rb5s+`I-zWe`?JFeP_wl;e84ZC1c6|e1$SPzs3yAHvfLqMTA6@4ycwET1aTC99KjMOYNPtuT-U8sX6Va=OvbeC* zdC9iZE-~;l4BJs~(gmChbXc^Avu#(6`Ny809^<^>A!VZB@pzjA>k#1aw$C2?Nx6Lx z`|QE=KZHI__w#?39>ie4PG<(e#t5PZF@qSa_ww2=^$Lb`dEgNB}k0$DKXhjGJF9sWE1WJ-3x5pf`PpM7nJ&f2U0cDGG>kc#T^VawB^Wf5krw4 z$9KQZb@R6;0CXk&TROzVfq-Ke?C6jWXmiD2#K{>!e&1e45U5-EWFHO(KDySnONOHj zMLKMb7HynA1p@iMJ$DA4b5|cZEd*feJq*PeiUh}N>LO;P+SbK}ZF{jEPzO>Ol`ml0 zw?1pr%Wwn3kshDE;acj}A3%Ot-SMMc7ANrKv$l-~z{-oRAf?`~&JiAMCK~mk2Z#w2 zjEnu~7*`p_<%9dwhyS`~){E|-VA|N@xPa*ZBZG0$hJ2jcw!e{%XYYahX>*UxJ5G2N zg@F<#X9W5Glsf<gKZ) zM=*2kz@;Y_eKD?Gw#5W*`jz_fQxJ9N#}{!MzrRi)e*SfV!fA50}HR&%f}U;QqNlEk~D?Nx4y*Xr)r-6b~)Y=EIc>0 z;EXr&`rC5{Fn7c=|% z7MNXdWwbdNfPmySn6fiJL>Byf@F5=aZpt|j`ci-`)7rm3{LmMC^mOpXGKaFxfUmaC zyFxnP2&l8|$kc^m2e<{Usvms929H2^l*@uB$J`fVe-J!x$-WQ+Jf))&J= zc(TtfFE0NlS|^sn)ksY#hR-O?cI*r`W{7rDC&Z>*_YGpo9AZQL{Ss7J;Zion`CC2u{LMgn!C HokZ|oc%Pgc literal 0 HcmV?d00001 diff --git a/technic/textures/technic_prospector.png b/technic/textures/technic_prospector.png new file mode 100644 index 0000000000000000000000000000000000000000..2f9ee6ca86a8fb039374171a020c8fc14456e736 GIT binary patch literal 367 zcmV-#0g(QQP)sxI4QvkOdXC=fg4BFa`3y{2l62j@b+<%)5 z8zO0ONW2yVnFAqlDW>IF-{mPZIkqQ1Ts5TyV&cX=R^P%uu`U?kFs|>^$!kIMA@Pt= z;-%JKDgFT<#6x1W!~x+(frYb-R zga`2u)d6xLngHZLG@FW3E9hlodGin~LXD>BYzRo@AeG|`uxyBs_#3Z>w68W?xF-Mr N002ovPDHLkV1m!Bk;wo6 literal 0 HcmV?d00001 diff --git a/technic/tools/init.lua b/technic/tools/init.lua index 60327a5..b8d9127 100644 --- a/technic/tools/init.lua +++ b/technic/tools/init.lua @@ -13,6 +13,7 @@ dofile(path.."/cans.lua") dofile(path.."/chainsaw.lua") dofile(path.."/tree_tap.lua") dofile(path.."/sonic_screwdriver.lua") +dofile(path.."/prospector.lua") if minetest.get_modpath("screwdriver") then -- compatibility alias diff --git a/technic/tools/prospector.lua b/technic/tools/prospector.lua new file mode 100644 index 0000000..686e0a7 --- /dev/null +++ b/technic/tools/prospector.lua @@ -0,0 +1,126 @@ +local S = technic.getter + +technic.register_power_tool("technic:prospector", 15000) + +local function get_metadata(toolstack) + local m = minetest.deserialize(toolstack:get_metadata()) + if not m then m = {} end + if not m.charge then m.charge = 0 end + if not m.target then m.target = "" end + if not m.look_depth then m.look_depth = 7 end + if not m.look_radius then m.look_radius = 1 end + return m +end + +minetest.register_tool("technic:prospector", { + description = S("Prospector"), + inventory_image = "technic_prospector.png", + wear_represents = "technic_RE_charge", + on_refill = technic.refill_RE_charge, + on_use = function(toolstack, user, pointed_thing) + if not user or not user:is_player() or user.is_fake_player then return end + if pointed_thing.type ~= "node" then return end + local toolmeta = get_metadata(toolstack) + local look_diameter = toolmeta.look_radius * 2 + 1 + local charge_to_take = toolmeta.look_depth * (toolmeta.look_depth + 1) * look_diameter * look_diameter + if toolmeta.charge < charge_to_take then return end + if toolmeta.target == "" then + minetest.chat_send_player(user:get_player_name(), "Right-click to set target block type") + return + end + toolmeta.charge = toolmeta.charge - charge_to_take + toolstack:set_metadata(minetest.serialize(toolmeta)) + technic.set_RE_wear(toolstack, toolmeta.charge, technic.power_tools[toolstack:get_name()]) + local start_pos = pointed_thing.under + local forward = minetest.facedir_to_dir(minetest.dir_to_facedir(user:get_look_dir(), true)) + local right = forward.x ~= 0 and { x=0, y=1, z=0 } or (forward.y ~= 0 and { x=0, y=0, z=1 } or { x=1, y=0, z=0 }) + local up = forward.x ~= 0 and { x=0, y=0, z=1 } or (forward.y ~= 0 and { x=1, y=0, z=0 } or { x=0, y=1, z=0 }) + local base_pos = vector.add(start_pos, vector.multiply(vector.add(right, up), - toolmeta.look_radius)) + local found = false + for f = 0, toolmeta.look_depth-1 do + for r = 0, look_diameter-1 do + for u = 0, look_diameter-1 do + if minetest.get_node(vector.add(vector.add(vector.add(base_pos, vector.multiply(forward, f)), vector.multiply(right, r)), vector.multiply(up, u))).name == toolmeta.target then found = true end + end + end + end + if math.random() < 0.02 then found = not found end + minetest.chat_send_player(user:get_player_name(), minetest.registered_nodes[toolmeta.target].description.." is "..(found and "present" or "absent").." in "..look_diameter.."x"..look_diameter.."x"..toolmeta.look_depth.." region") + minetest.sound_play("technic_prospector_"..(found and "hit" or "miss"), { pos = vector.add(user:getpos(), { x = 0, y = 1, z = 0 }), gain = 1.0, max_hear_distance = 10 }) + return toolstack + end, + on_place = function(toolstack, user, pointed_thing) + if not user or not user:is_player() or user.is_fake_player then return end + local toolmeta = get_metadata(toolstack) + local pointed + if pointed_thing.type == "node" then + local pname = minetest.get_node(pointed_thing.under).name + local pdef = minetest.registered_nodes[pname] + if pdef and (pdef.groups.not_in_creative_inventory or 0) == 0 and pname ~= toolmeta.target then + pointed = pname + end + end + local look_diameter = toolmeta.look_radius * 2 + 1 + minetest.show_formspec(user:get_player_name(), "technic:prospector_control", + "size[7,8.5]".. + "item_image[0,0;1,1;"..toolstack:get_name().."]".. + "label[1,0;"..minetest.formspec_escape(toolstack:get_definition().description).."]".. + (toolmeta.target ~= "" and + "label[0,1.5;Current target:]".. + "label[0,2;"..minetest.formspec_escape(minetest.registered_nodes[toolmeta.target].description).."]".. + "item_image[0,2.5;1,1;"..toolmeta.target.."]" or + "label[0,1.5;No target set]").. + (pointed and + "label[3.5,1.5;May set new target:]".. + "label[3.5,2;"..minetest.formspec_escape(minetest.registered_nodes[pointed].description).."]".. + "item_image[3.5,2.5;1,1;"..pointed.."]".. + "button_exit[3.5,3.65;2,0.5;target_"..pointed..";Set target]" or + "label[3.5,1.5;No new target available]").. + "label[0,4.5;Region cross section:]".. + "label[0,5;"..look_diameter.."x"..look_diameter.."]".. + "label[3.5,4.5;Set region cross section:]".. + "button_exit[3.5,5.15;1,0.5;look_radius_0;1x1]".. + "button_exit[4.5,5.15;1,0.5;look_radius_1;3x3]".. + "button_exit[5.5,5.15;1,0.5;look_radius_3;7x7]".. + "label[0,6;Region depth:]".. + "label[0,6.5;"..toolmeta.look_depth.."]".. + "label[3.5,6;Set region depth:]".. + "button_exit[3.5,6.65;1,0.5;look_depth_7;7]".. + "button_exit[4.5,6.65;1,0.5;look_depth_14;14]".. + "button_exit[5.5,6.65;1,0.5;look_depth_21;21]".. + "label[0,7.5;Accuracy:]".. + "label[0,8;98%]") + return + end, +}) + +minetest.register_on_player_receive_fields(function(user, formname, fields) + if formname ~= "technic:prospector_control" then return false end + if not user or not user:is_player() or user.is_fake_player then return end + local toolstack = user:get_wielded_item() + if toolstack:get_name() ~= "technic:prospector" then return true end + local toolmeta = get_metadata(toolstack) + for field, value in pairs(fields) do + if field:sub(1, 7) == "target_" then + toolmeta.target = field:sub(8) + end + if field:sub(1, 12) == "look_radius_" then + toolmeta.look_radius = field:sub(13) + end + if field:sub(1, 11) == "look_depth_" then + toolmeta.look_depth = field:sub(12) + end + end + toolstack:set_metadata(minetest.serialize(toolmeta)) + user:set_wielded_item(toolstack) + return true +end) + +minetest.register_craft({ + output = "technic:prospector", + recipe = { + {"moreores:pick_silver", "moreores:mithril_block", "pipeworks:teleport_tube_1"}, + {"technic:brass_ingot", "technic:control_logic_unit", "technic:brass_ingot"}, + {"", "technic:brass_ingot", ""}, + } +})