1 --here is where tnt is defined
2 local function extreme_tnt(pos,range)
3 local pos = vector.floor(vector.add(pos,0.5))
7 for _,object in ipairs(minetest.get_objects_inside_radius(pos, range)) do
8 if object:is_player() then
10 elseif object:get_luaentity() and object:get_luaentity().name == "__builtin:item" then
20 minetest.after(delay, function(pos,range,x,y,z)
21 local min = vector.add(pos,vector.multiply(vector.new(x,y,z),range))
22 local max = vector.add(pos,vector.multiply(vector.new(x+1,y+1,z+1),range))
23 local vm = minetest.get_voxel_manip()
24 local emin, emax = vm:read_from_map(min,max)
25 local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
26 local data = vm:get_data()
27 local air = minetest.get_content_id("air")
32 --if vector.distance(pos, vector.new(x,y,z)) <= range then
33 --minetest.remove_node(vector.new(x,y,z))
34 data[area:index(x,y,z)] = air
47 minetest.sound_play("tnt_explode", {pos = pos, gain = 1.0, max_hear_distance = range*range*range})
50 minetest.register_globalstep(function(dtime)
52 for _,player in ipairs(minetest.get_connected_players()) do
53 local pos = player:get_pos()
54 pos.y = pos.y + player:get_properties().eye_height
55 local look_dir = player:get_look_dir()
56 look_dir = vector.multiply(look_dir,7)
57 local pos2 = vector.add(pos,look_dir)
59 local ray = minetest.raycast(pos, pos2, false, false)
61 print("------------------------------------------------------------")
62 for pointed_thing in ray do
63 print(minetest.get_node(pointed_thing.under).name)
64 --if pointed_thing then
65 -- return({under=pointed_thing.under,above=pointed_thing.above})
72 --use raycasting to create actual explosion
80 local pos2 = vector.new(0,0,0)
81 function tnt(pos,range)
82 local in_node = minetest.get_node(pos).name
83 local in_water = ( in_node == "main:water" or minetest.get_node(pos).name == "main:waterflow")
84 local min = vector.add(pos,range)
85 local max = vector.subtract(pos,range)
86 local vm = minetest.get_voxel_manip()
87 local emin, emax = vm:read_from_map(min,max)
88 local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
89 local data = vm:get_data()
91 local air = minetest.get_content_id("air")
92 local content_id = minetest.get_name_from_content_id
94 local insert = table.insert
100 if in_water == false then
102 for x=-range, range do
103 for y=-range, range do
104 for z=-range, range do
105 local distance = vector.distance(pos2, vector.new(x,y,z))
106 if distance <= range and distance >= range-1 then
107 ray = minetest.raycast(pos, vector.new(pos.x+x,pos.y+y,pos.z+z), false, false)
109 for pointed_thing in ray do
110 n_pos = area:index(pointed_thing.under.x,pointed_thing.under.y,pointed_thing.under.z)
111 node2 = content_id(data[n_pos])
113 if node2 == "nether:obsidian" or node2 == "nether:bedrock" then
115 elseif node2 == "tnt:tnt" then
117 local obj = minetest.add_entity(vector.new(pointed_thing.under.x,pointed_thing.under.y,pointed_thing.under.z), "tnt:tnt",minetest.serialize({do_ignition_particles=true,timer = math.random()}))
120 minetest.after(0, function(pointed_thing)
121 minetest.check_for_falling(vector.new(pointed_thing.under.x,pointed_thing.under.y+1,pointed_thing.under.z))
123 if math.random()>0.999 then
124 if n ~= "nether:obsidian" and n ~= "nether:bedrock" then
125 local item = minetest.get_node_drops(n, "main:diamondpick")[1]
126 local ppos = vector.new(pointed_thing.under.x,pointed_thing.under.y,pointed_thing.under.z)
127 local obj = minetest.add_item(ppos, item)
129 local power = (range - vector.distance(pos,ppos))*2
130 local dir = vector.subtract(ppos,pos)
131 local force = vector.multiply(dir,power)
132 obj:set_velocity(force)
147 minetest.sound_play("tnt_explode", {pos = pos, gain = 1.0, max_hear_distance = range*range}) --hear twice as far away
149 --throw players and items
150 for _,object in ipairs(minetest.get_objects_inside_radius(pos, range)) do
151 if object:is_player() or (object:get_luaentity() and (object:get_luaentity().name == "__builtin:item" or object:get_luaentity().name == "tnt:tnt" or object:get_luaentity().is_mob == true)) then
153 if not object:is_player() and object:get_luaentity().name == "tnt:tnt" then
154 local in_node = minetest.get_node(object:get_pos()).name
155 if ( in_node == "main:water" or in_node == "main:waterflow") then
159 if do_it == true then
160 local ppos = object:get_pos()
161 if object:is_player() then
164 ray = minetest.raycast(pos, ppos, false, false)
166 for pointed_thing in ray do
167 n_pos = area:index(pointed_thing.under.x,pointed_thing.under.y,pointed_thing.under.z)
168 node2 = content_id(data[n_pos])
169 if node2 == "nether:obsidian" or node2 == "nether:bedrock" then
173 if clear == true then
174 local power = (range - vector.distance(pos,ppos))*10
176 local dir = vector.direction(pos,ppos)
177 local force = vector.multiply(dir,power)
178 if object:is_player() then
180 local hp = object:get_hp()
182 object:set_hp(hp - math.floor(power*2))
184 object:add_player_velocity(force)
185 elseif object:get_luaentity() and (object:get_luaentity().name == "__builtin:item" or object:get_luaentity().name == "tnt:tnt" or object:get_luaentity().is_mob == true) then
186 if object:get_luaentity().name == "tnt:tnt" then
187 object:get_luaentity().shot = true
188 elseif object:get_luaentity().is_mob == true then
189 object:punch(object, 2,
191 full_punch_interval=1.5,
192 damage_groups = {damage=math.floor(power*2)},
194 object:set_velocity(force)
202 --stop client from lagging
203 local particle = range
204 if particle > 15 then
209 minetest.add_particlespawner({
210 amount = particle*particle,
214 minvel = vector.new(-range,-range,-range),
215 maxvel = vector.new(range,range,range),
216 minacc = {x=0, y=0, z=0},
217 maxacc = {x=0, y=0, z=0},
222 collisiondetection = true,
223 collision_removal = true,
225 texture = "smoke.png",
230 minetest.register_entity("tnt:tnt", {
231 initial_properties = {
234 collide_with_objects = false,
235 collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
237 visual_size = {x = 1, y = 1},
238 textures = {"tnt_top.png", "tnt_bottom.png",
239 "tnt_side.png", "tnt_side.png",
240 "tnt_side.png", "tnt_side.png"},
246 timer_max = 5, --this has to be equal to timer
248 get_staticdata = function(self)
249 return minetest.serialize({
252 exploded = self.exploded,
256 on_activate = function(self, staticdata, dtime_s)
257 self.object:set_armor_groups({immortal = 1})
258 self.object:set_velocity({x = math.random(-3,3), y = 3, z = math.random(-3,3)})
259 self.object:set_acceleration({x = 0, y = -9.81, z = 0})
260 if string.sub(staticdata, 1, string.len("return")) == "return" then
261 local data = minetest.deserialize(staticdata)
262 if data and type(data) == "table" then
263 self.range = data.range
264 self.timer = data.timer
265 self.exploded = data.exploded
268 if self.timer == self.timer_max then
269 minetest.add_particlespawner({
272 minpos = vector.new(0,0.5,0),
273 minpos = vector.new(0,0.5,0),
274 minvel = vector.new(-0.5,1,-0.5),
275 maxvel = vector.new(0.5,5,0.5),
276 minacc = {x=0, y=0, z=0},
277 maxacc = {x=0, y=0, z=0},
282 collisiondetection = false,
284 texture = "smoke.png",
285 attached = self.object,
287 minetest.sound_play("tnt_ignite", {object = self.object, gain = 1.0, max_hear_distance = self.range*self.range*self.range})
291 on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
292 local obj = minetest.add_item(self.object:get_pos(), "tnt:tnt")
296 sound_played = false,
297 on_step = function(self, dtime)
298 self.timer = self.timer - dtime
299 if not self.shot or not self.redstone_activated then
300 local vel = self.object:getvelocity()
301 vel = vector.multiply(vel,-0.05)
302 self.object:add_velocity(vector.new(vel.x,0,vel.z))
304 if self.timer <= 0 then
305 if not self.range then
308 tnt(self.object:get_pos(),self.range)
315 minetest.register_node("tnt:tnt", {
316 description = "Cobblestone",
317 tiles = {"tnt_top.png", "tnt_bottom.png",
318 "tnt_side.png", "tnt_side.png",
319 "tnt_side.png", "tnt_side.png"},
320 groups = {stone = 2, hard = 1, pickaxe = 2, hand = 4, redstone_activation = 1},
321 sounds = main.stoneSound(),
322 redstone_activation = function(pos)
323 local obj = minetest.add_entity(pos,"tnt:tnt")
325 obj:get_luaentity().range = range
326 obj:get_luaentity().redstone_activated = true
327 minetest.remove_node(pos)
329 on_punch = function(pos, node, puncher, pointed_thing)
330 local obj = minetest.add_entity(pos,"tnt:tnt")
332 obj:get_luaentity().range = range
333 minetest.remove_node(pos)
337 minetest.register_node("tnt:uranium_tnt", {
338 description = "Cobblestone",
339 tiles = {"tnt_top.png^[colorize:green:100", "tnt_bottom.png^[colorize:green:100",
340 "tnt_side.png^[colorize:green:100", "tnt_side.png^[colorize:green:100",
341 "tnt_side.png^[colorize:green:100", "tnt_side.png^[colorize:green:100"},
342 groups = {stone = 2, hard = 1, pickaxe = 2, hand = 4},
343 sounds = main.stoneSound(),
344 on_punch = function(pos, node, puncher, pointed_thing)
345 local obj = minetest.add_entity(pos,"tnt:tnt")
347 obj:get_luaentity().range = range
348 obj:get_luaentity().timer = 7
349 obj:get_luaentity().extreme = true
351 minetest.remove_node(pos)
355 minetest.register_node("tnt:uh_oh", {
356 description = "Cobblestone",
357 tiles = {"tnt_top.png", "tnt_bottom.png",
358 "tnt_side.png", "tnt_side.png",
359 "tnt_side.png", "tnt_side.png"},
360 groups = {stone = 2, hard = 1, pickaxe = 2, hand = 4},
361 sounds = main.stoneSound(),
362 on_construct = function(pos)
364 for x=-range, range do
365 for y=-range, range do
366 for z=-range, range do
367 minetest.add_node(vector.new(pos.x+x,pos.y+y,pos.z+z),{name="tnt:tnt"})
376 minetest.register_craft({
379 {"mob:gunpowder", "main:sand", "mob:gunpowder"},
380 {"main:sand", "mob:gunpowder", "main:sand"},
381 {"mob:gunpowder", "main:sand", "mob:gunpowder"},