nodes_anvil.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. ---------------------------------------------------------------------------------------
  2. -- simple anvil that can be used to repair tools
  3. ---------------------------------------------------------------------------------------
  4. -- * can be used to repair tools
  5. -- * the hammer gets dammaged a bit at each repair step
  6. ---------------------------------------------------------------------------------------
  7. -- License of the hammer picture: CC-by-SA; done by GloopMaster; source:
  8. -- https://github.com/GloopMaster/glooptest/blob/master/glooptest/textures/glooptest_tool_steelhammer.png
  9. local S = cottages.S
  10. -- disable repair with anvil by setting a message for the item in question
  11. cottages.forbid_repair = {}
  12. -- example for hammer no longer beeing able to repair the hammer
  13. --cottages.forbid_repair["cottages:hammer"] = 'The hammer is too complex for repairing.'
  14. -- the hammer for the anvil
  15. minetest.register_tool("cottages:hammer", {
  16. description = S("Steel hammer for repairing tools on the anvil"),
  17. image = "glooptest_tool_steelhammer.png",
  18. inventory_image = "glooptest_tool_steelhammer.png",
  19. tool_capabilities = {
  20. full_punch_interval = 0.8,
  21. max_drop_level=1,
  22. groupcaps={
  23. -- about equal to a stone pick (it's not intended as a tool)
  24. cracky={times={[2]=2.00, [3]=1.20}, uses=30, maxlevel=1},
  25. },
  26. damage_groups = {fleshy=6},
  27. }
  28. })
  29. local cottages_anvil_formspec =
  30. "size[8,8]"..
  31. "image[7,3;1,1;glooptest_tool_steelhammer.png]"..
  32. -- "list[current_name;sample;0,0.5;1,1;]"..
  33. "list[current_name;input;2.5,1.5;1,1;]"..
  34. -- "list[current_name;material;5,0;3,3;]"..
  35. "list[current_name;hammer;5,3;1,1;]"..
  36. -- "label[0.0,0.0;Sample:]"..
  37. -- "label[0.0,1.0;(Receipe)]"..
  38. "label[2.5,1.0;"..S("Workpiece:").."]"..
  39. -- "label[6.0,-0.5;Materials:]"..
  40. "label[6.0,2.7;"..S("Optional").."]"..
  41. "label[6.0,3.0;"..S("storage for").."]"..
  42. "label[6.0,3.3;"..S("your hammer").."]"..
  43. "label[0,-0.5;"..S("Anvil").."]"..
  44. "label[0,3.0;"..S("Punch anvil with hammer to").."]"..
  45. "label[0,3.3;"..S("repair tool in workpiece-slot.").."]"..
  46. "list[current_player;main;0,4;8,4;]";
  47. minetest.register_node("cottages:anvil", {
  48. drawtype = "nodebox",
  49. description = S("anvil"),
  50. tiles = {"cottages_stone.png"}, -- TODO default_steel_block.png, default_obsidian.png are also nice
  51. paramtype = "light",
  52. paramtype2 = "facedir",
  53. groups = {cracky=2},
  54. -- the nodebox model comes from realtest
  55. node_box = {
  56. type = "fixed",
  57. fixed = {
  58. {-0.5,-0.5,-0.3,0.5,-0.4,0.3},
  59. {-0.35,-0.4,-0.25,0.35,-0.3,0.25},
  60. {-0.3,-0.3,-0.15,0.3,-0.1,0.15},
  61. {-0.35,-0.1,-0.2,0.35,0.1,0.2},
  62. },
  63. },
  64. selection_box = {
  65. type = "fixed",
  66. fixed = {
  67. {-0.5,-0.5,-0.3,0.5,-0.4,0.3},
  68. {-0.35,-0.4,-0.25,0.35,-0.3,0.25},
  69. {-0.3,-0.3,-0.15,0.3,-0.1,0.15},
  70. {-0.35,-0.1,-0.2,0.35,0.1,0.2},
  71. }
  72. },
  73. on_construct = function(pos)
  74. local meta = minetest.get_meta(pos);
  75. meta:set_string("infotext", S("Anvil"));
  76. local inv = meta:get_inventory();
  77. inv:set_size("input", 1);
  78. -- inv:set_size("material", 9);
  79. -- inv:set_size("sample", 1);
  80. inv:set_size("hammer", 1);
  81. meta:set_string("formspec", cottages_anvil_formspec );
  82. end,
  83. after_place_node = function(pos, placer)
  84. local meta = minetest.get_meta(pos);
  85. meta:set_string("owner", placer:get_player_name() or "");
  86. meta:set_string("infotext", S("Anvil (owned by %s)"):format((meta:get_string("owner") or "")));
  87. meta:set_string("formspec",
  88. cottages_anvil_formspec,
  89. "label[2.5,-0.5;"..S("Owner: %s"):format(meta:get_string('owner') or "").."]");
  90. end,
  91. can_dig = function(pos,player)
  92. local meta = minetest.get_meta(pos);
  93. local inv = meta:get_inventory();
  94. local owner = meta:get_string('owner');
  95. if( not( inv:is_empty("input"))
  96. -- or not( inv:is_empty("material"))
  97. -- or not( inv:is_empty("sample"))
  98. or not( inv:is_empty("hammer"))
  99. or not( player )
  100. or ( owner and owner ~= '' and player:get_player_name() ~= owner )) then
  101. return false;
  102. end
  103. return true;
  104. end,
  105. allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
  106. local meta = minetest.get_meta(pos)
  107. if( player and player:get_player_name() ~= meta:get_string('owner' ) and from_list~="input") then
  108. return 0
  109. end
  110. return count;
  111. end,
  112. allow_metadata_inventory_put = function(pos, listname, index, stack, player)
  113. local meta = minetest.get_meta(pos)
  114. if( player and player:get_player_name() ~= meta:get_string('owner' ) and listname~="input") then
  115. return 0;
  116. end
  117. if( listname=='hammer' and stack and stack:get_name() ~= 'cottages:hammer') then
  118. return 0;
  119. end
  120. if( listname=='input'
  121. and( stack:get_wear() == 0
  122. or stack:get_name() == "technic:water_can"
  123. or stack:get_name() == "technic:lava_can" )) then
  124. minetest.chat_send_player( player:get_player_name(),
  125. S('The workpiece slot is for damaged tools only.'));
  126. return 0;
  127. end
  128. if( listname=='input'
  129. and cottages.forbid_repair[ stack:get_name() ]) then
  130. minetest.chat_send_player( player:get_player_name(),
  131. S(cottages.forbid_repair[ stack:get_name() ]));
  132. return 0;
  133. end
  134. return stack:get_count()
  135. end,
  136. allow_metadata_inventory_take = function(pos, listname, index, stack, player)
  137. local meta = minetest.get_meta(pos)
  138. if( player and player:get_player_name() ~= meta:get_string('owner' ) and listname~="input") then
  139. return 0
  140. end
  141. return stack:get_count()
  142. end,
  143. on_punch = function(pos, node, puncher)
  144. if( not( pos ) or not( node ) or not( puncher )) then
  145. return;
  146. end
  147. -- only punching with the hammer is supposed to work
  148. local wielded = puncher:get_wielded_item();
  149. if( not( wielded ) or not( wielded:get_name() ) or wielded:get_name() ~= 'cottages:hammer') then
  150. return;
  151. end
  152. local name = puncher:get_player_name();
  153. local meta = minetest.get_meta(pos);
  154. local inv = meta:get_inventory();
  155. local input = inv:get_stack('input',1);
  156. -- only tools can be repaired
  157. if( not( input )
  158. or input:is_empty()
  159. or input:get_name() == "technic:water_can"
  160. or input:get_name() == "technic:lava_can" ) then
  161. meta:set_string("formspec",
  162. cottages_anvil_formspec,
  163. "label[2.5,-0.5;"..S("Owner: %s"):format(meta:get_string('owner') or "").."]");
  164. return;
  165. end
  166. -- 65535 is max damage
  167. local damage_state = 40-math.floor(input:get_wear()/1638);
  168. -- just to make sure that it really can't get repaired if it should not
  169. -- (if the check of placing the item in the input slot failed somehow)
  170. if( puncher and name and cottages.forbid_repair[ input:get_name() ]) then
  171. minetest.chat_send_player( name,
  172. S(cottages.forbid_repair[ input:get_name() ]));
  173. return;
  174. end
  175. local tool_name = input:get_name();
  176. local hud_image = "";
  177. if( tool_name
  178. and minetest.registered_items[ tool_name ] ) then
  179. if( minetest.registered_items[ tool_name ].inventory_image ) then
  180. hud_image = minetest.registered_items[ tool_name ].inventory_image;
  181. elseif( minetest.registered_items[ tool_name ].textures
  182. and type(minetest.registered_items[ tool_name ].textures)=='table') then
  183. hud_image = minetest.registered_items[ tool_name ].textures[1];
  184. elseif( minetest.registered_items[ tool_name ].textures
  185. and type(minetest.registered_items[ tool_name ].textures)=='string') then
  186. hud_image = minetest.registered_items[ tool_name ].textures;
  187. end
  188. end
  189. local hud1 = puncher:hud_add({
  190. hud_elem_type = "image",
  191. scale = {x = 15, y = 15},
  192. text = hud_image,
  193. position = {x = 0.5, y = 0.5},
  194. alignment = {x = 0, y = 0}
  195. });
  196. local hud2 = nil;
  197. local hud3 = nil;
  198. if( input:get_wear()>0 ) then
  199. hud2 = puncher:hud_add({
  200. hud_elem_type = "statbar",
  201. text = "default_cloud.png^[colorize:#ff0000:256",
  202. number = 40,
  203. direction = 0, -- left to right
  204. position = {x=0.5, y=0.65},
  205. alignment = {x = 0, y = 0},
  206. offset = {x = -320, y = 0},
  207. size = {x=32, y=32},
  208. })
  209. hud3 = puncher:hud_add({
  210. hud_elem_type = "statbar",
  211. text = "default_cloud.png^[colorize:#00ff00:256",
  212. number = damage_state,
  213. direction = 0, -- left to right
  214. position = {x=0.5, y=0.65},
  215. alignment = {x = 0, y = 0},
  216. offset = {x = -320, y = 0},
  217. size = {x=32, y=32},
  218. });
  219. end
  220. minetest.after(2, function()
  221. if( puncher ) then
  222. if(hud1) then puncher:hud_remove(hud1); end
  223. if(hud2) then puncher:hud_remove(hud2); end
  224. if(hud3) then puncher:hud_remove(hud3); end
  225. end
  226. end)
  227. -- tell the player when the job is done
  228. if( input:get_wear() == 0 ) then
  229. -- minetest.chat_send_player( puncher:get_player_name(),
  230. -- S('Your tool has been repaired successfully.'));
  231. return;
  232. end
  233. -- do the actual repair
  234. input:add_wear( -5000 ); -- equals to what technic toolshop does in 5 seconds
  235. inv:set_stack("input", 1, input)
  236. -- damage the hammer slightly
  237. wielded:add_wear( 100 );
  238. puncher:set_wielded_item( wielded );
  239. -- do not spam too much
  240. -- if( math.random( 1,5 )==1 ) then
  241. -- minetest.chat_send_player( puncher:get_player_name(),
  242. -- S('Your workpiece improves.'));
  243. -- end
  244. end,
  245. is_ground_content = false,
  246. })
  247. ---------------------------------------------------------------------------------------
  248. -- crafting receipes
  249. ---------------------------------------------------------------------------------------
  250. minetest.register_craft({
  251. output = "cottages:anvil",
  252. recipe = {
  253. {cottages.craftitem_steel,cottages.craftitem_steel,cottages.craftitem_steel},
  254. {'', cottages.craftitem_steel,'' },
  255. {cottages.craftitem_steel,cottages.craftitem_steel,cottages.craftitem_steel} },
  256. })
  257. -- the castle-mod has an anvil as well - with the same receipe. convert the two into each other
  258. if ( minetest.get_modpath("castle") ~= nil ) then
  259. minetest.register_craft({
  260. output = "cottages:anvil",
  261. recipe = {
  262. {'castle:anvil'},
  263. },
  264. })
  265. minetest.register_craft({
  266. output = "castle:anvil",
  267. recipe = {
  268. {'cottages:anvil'},
  269. },
  270. })
  271. end
  272. minetest.register_craft({
  273. output = "cottages:hammer",
  274. recipe = {
  275. {cottages.craftitem_steel},
  276. {'cottages:anvil'},
  277. {cottages.craftitem_stick} }
  278. })