init.lua 8.3 KB

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