init.lua 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. tnt = {}
  2. local enable_tnt = true
  3. local tnt_radius = 3
  4. function tnt.burn(pos)
  5. local name = minetest.get_node(pos).name
  6. local group = minetest.get_item_group(name, "tnt")
  7. if group > 0 then
  8. minetest.sound_play("tnt_ignite", {pos = pos}, true)
  9. -- Some nodes in group 'tnt' don't have a "_burning" variant.
  10. local bnam = name .. "_burning"
  11. local ndef = minetest.registered_nodes[bnam]
  12. if ndef then
  13. minetest.add_node(pos, {name = bnam})
  14. end
  15. minetest.get_node_timer(pos):start(1)
  16. elseif name == "tnt:gunpowder" then
  17. minetest.add_node(pos, {name = "tnt:gunpowder_burning"})
  18. end
  19. end
  20. reload.register_file("tnt:boom", minetest.get_modpath("tnt") .. "/tnt_boom.lua")
  21. reload.register_file("tnt:cdp", minetest.get_modpath("tnt") .. "/cdp.lua")
  22. minetest.register_node("tnt:boom", {
  23. drawtype = "airlike",
  24. light_source = default.LIGHT_MAX - 1,
  25. walkable = false,
  26. drop = "",
  27. groups = utility.dig_groups("item"),
  28. pointable = false,
  29. buildable_to = true,
  30. on_construct = function(pos)
  31. minetest.get_node_timer(pos):start(0.5)
  32. end,
  33. on_timer = function(pos, elapsed)
  34. minetest.remove_node(pos)
  35. end,
  36. -- Unaffected by explosions.
  37. on_blast = function() end,
  38. })
  39. -- overriden to add additional functionality in real_torch
  40. minetest.register_node("tnt:gunpowder", {
  41. description = "Gun Powder",
  42. drawtype = "raillike",
  43. paramtype = "light",
  44. is_ground_content = false,
  45. sunlight_propagates = true,
  46. walkable = false,
  47. tiles = {
  48. "tnt_gunpowder_straight.png",
  49. "tnt_gunpowder_curved.png",
  50. "tnt_gunpowder_t_junction.png",
  51. "tnt_gunpowder_crossing.png",
  52. },
  53. inventory_image = "tnt_gunpowder_inventory.png",
  54. wield_image = "tnt_gunpowder_inventory.png",
  55. selection_box = {
  56. type = "fixed",
  57. fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
  58. },
  59. groups = utility.dig_groups("bigitem", {
  60. attached_node = 1,
  61. connect_to_raillike = minetest.raillike_group("gunpowder"),
  62. }),
  63. sounds = default.node_sound_leaves_defaults(),
  64. on_punch = function(pos, node, puncher)
  65. local wielded = puncher:get_wielded_item():get_name()
  66. if minetest.get_item_group(wielded, "torch") ~= 0 then
  67. tnt.burn(pos)
  68. minetest.log("action", puncher:get_player_name() ..
  69. " ignites tnt:gunpowder at " ..
  70. minetest.pos_to_string(pos))
  71. end
  72. end,
  73. on_blast = function(pos)
  74. minetest.set_node(pos, {name = "tnt:gunpowder_burning"})
  75. end,
  76. })
  77. minetest.register_node("tnt:gunpowder_burning", {
  78. drawtype = "raillike",
  79. paramtype = "light",
  80. sunlight_propagates = true,
  81. walkable = false,
  82. light_source = 5,
  83. tiles = {{
  84. name = "tnt_gunpowder_burning_straight_animated.png",
  85. animation = {
  86. type = "vertical_frames",
  87. aspect_w = 16,
  88. aspect_h = 16,
  89. length = 1,
  90. }
  91. },
  92. {
  93. name = "tnt_gunpowder_burning_curved_animated.png",
  94. animation = {
  95. type = "vertical_frames",
  96. aspect_w = 16,
  97. aspect_h = 16,
  98. length = 1,
  99. }
  100. },
  101. {
  102. name = "tnt_gunpowder_burning_t_junction_animated.png",
  103. animation = {
  104. type = "vertical_frames",
  105. aspect_w = 16,
  106. aspect_h = 16,
  107. length = 1,
  108. }
  109. },
  110. {
  111. name = "tnt_gunpowder_burning_crossing_animated.png",
  112. animation = {
  113. type = "vertical_frames",
  114. aspect_w = 16,
  115. aspect_h = 16,
  116. length = 1,
  117. }
  118. }},
  119. selection_box = {
  120. type = "fixed",
  121. fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
  122. },
  123. drop = "",
  124. groups = utility.dig_groups("bigitem", {attached_node = 1, connect_to_raillike = minetest.raillike_group("gunpowder")}),
  125. sounds = default.node_sound_leaves_defaults(),
  126. on_timer = function(pos, elapsed)
  127. for dx = -1, 1 do
  128. for dz = -1, 1 do
  129. for dy = -1, 1 do
  130. if not (dx == 0 and dz == 0) then
  131. tnt.burn({
  132. x = pos.x + dx,
  133. y = pos.y + dy,
  134. z = pos.z + dz,
  135. })
  136. end
  137. end
  138. end
  139. end
  140. minetest.remove_node(pos)
  141. end,
  142. -- Unaffected by explosions.
  143. on_blast = function() end,
  144. on_construct = function(pos)
  145. minetest.sound_play("tnt_gunpowder_burning", {pos = pos, gain = 2}, true)
  146. minetest.get_node_timer(pos):start(1)
  147. end,
  148. })
  149. minetest.register_craftitem("tnt:tnt_stick", {
  150. description = "TNT Stick",
  151. inventory_image = "tnt_tnt_stick.png",
  152. groups = {flammable = 5},
  153. })
  154. minetest.register_craft({
  155. output = "tnt:gunpowder 6",
  156. type = "shapeless",
  157. recipe = {"default:coal_lump", "default:gravel", "sulfur:dust"}
  158. })
  159. if enable_tnt then
  160. minetest.register_craft({
  161. output = "tnt:tnt_stick",
  162. recipe = {
  163. {"default:paper", "tnt:gunpowder", "default:paper"},
  164. }
  165. })
  166. minetest.register_craft({
  167. output = "tnt:tnt",
  168. recipe = {
  169. {"group:wood", "tnt:tnt_stick", "group:wood"},
  170. {"tnt:tnt_stick", "tnt:tnt_stick", "tnt:tnt_stick"},
  171. {"group:wood", "tnt:tnt_stick", "group:wood"},
  172. }
  173. })
  174. minetest.register_abm({
  175. label = "TNT ignition",
  176. nodenames = {"group:tnt", "tnt:gunpowder"},
  177. neighbors = {"group:igniter"},
  178. interval = 4 * default.ABM_TIMER_MULTIPLIER,
  179. chance = 1 * default.ABM_CHANCE_MULTIPLIER,
  180. action = tnt.burn,
  181. })
  182. end
  183. minetest.register_privilege("tnt",
  184. {description="Player can place TNT anywhere.", give_to_singleplayer=false})
  185. function tnt.register_tnt(def)
  186. local name
  187. if not def.name:find(':') then
  188. name = "tnt:" .. def.name
  189. else
  190. name = def.name
  191. def.name = def.name:match(":([%w_]+)")
  192. end
  193. if not def.tiles then def.tiles = {} end
  194. local tnt_top = def.tiles.top or def.name .. "_top.png"
  195. local tnt_bottom = def.tiles.bottom or def.name .. "_bottom.png"
  196. local tnt_side = def.tiles.side or def.name .. "_side.png"
  197. local tnt_burning = def.tiles.burning or def.name .. "_top_burning_animated.png"
  198. if not def.damage_radius then def.damage_radius = def.radius * 2 end
  199. minetest.register_node(":" .. name, {
  200. description = def.description,
  201. tiles = {tnt_top, tnt_bottom, tnt_side},
  202. is_ground_content = false,
  203. groups = utility.dig_groups("bigitem", {tnt = 1}),
  204. sounds = default.node_sound_wood_defaults(),
  205. on_punch = function(pos, node, puncher)
  206. local wielded = puncher:get_wielded_item():get_name()
  207. if minetest.get_item_group(wielded, "torch") ~= 0 then
  208. minetest.add_node(pos, {name = name .. "_burning"})
  209. minetest.log("action", puncher:get_player_name() ..
  210. " ignites " .. node.name .. " at " ..
  211. minetest.pos_to_string(pos))
  212. end
  213. end,
  214. on_finish_collapse = function(pos, node)
  215. local igniter = minetest.find_node_near(pos, 1, "group:igniter")
  216. if igniter then
  217. minetest.add_node(pos, {name = name .. "_burning"})
  218. end
  219. end,
  220. on_construct = function(pos)
  221. local igniter = minetest.find_node_near(pos, 1, "group:igniter")
  222. if igniter then
  223. minetest.add_node(pos, {name = name .. "_burning"})
  224. end
  225. end,
  226. -- TNT chain reactions.
  227. on_blast = function(pos)
  228. minetest.after(0.3, function()
  229. tnt.boom(pos, def)
  230. end)
  231. end,
  232. on_place = function(itemstack, placer, pointed_thing)
  233. local pos = pointed_thing.under
  234. if not placer then return end
  235. if not placer:is_player() then return end
  236. local pname = placer:get_player_name()
  237. -- Players without the TNT priv go through checks.
  238. if not minetest.check_player_privs(placer, {tnt=true}) then
  239. -- 8/2/22: There's no in-game explanation for why one can't mine
  240. -- with TNT at the surface level. Disable this code, and rely on
  241. -- city blocks to prevent TNT mining.
  242. --[[
  243. if (pos.y > -100 and pos.y < 1000) then
  244. minetest.chat_send_player(pname, "# Server: Use of TNT near the Overworld's ground level is forbidden.")
  245. return itemstack
  246. end
  247. --]]
  248. if city_block:in_no_tnt_zone(pos) then
  249. minetest.chat_send_player(pname, "# Server: Too close to a residential zone for blasting!")
  250. return itemstack
  251. end
  252. end
  253. -- All checks passed.
  254. return minetest.item_place(itemstack, placer, pointed_thing)
  255. end,
  256. })
  257. minetest.register_node(":" .. name .. "_burning", {
  258. tiles = {
  259. {
  260. name = tnt_burning,
  261. animation = {
  262. type = "vertical_frames",
  263. aspect_w = 16,
  264. aspect_h = 16,
  265. length = 1,
  266. }
  267. },
  268. tnt_bottom, tnt_side
  269. },
  270. light_source = 5,
  271. drop = "",
  272. sounds = default.node_sound_wood_defaults(),
  273. groups = {falling_node = 1},
  274. on_timer = function(pos, elapsed)
  275. tnt.boom(pos, def)
  276. end,
  277. -- Unaffected by explosions.
  278. on_blast = function() end,
  279. on_construct = function(pos)
  280. minetest.sound_play("tnt_ignite", {pos = pos}, true)
  281. minetest.get_node_timer(pos):start(5)
  282. minetest.check_for_falling(pos)
  283. end,
  284. })
  285. end
  286. tnt.register_tnt({
  287. name = "tnt:tnt",
  288. description = "Explosive TNT",
  289. radius = tnt_radius,
  290. })