init.lua 8.6 KB

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