]> git.lizzy.rs Git - Crafter.git/blob - mods/tnt/init.lua
248a69dc4b60fea676ec6823758e94b37f44ed35
[Crafter.git] / mods / tnt / init.lua
1 --here is where tnt is defined
2 local function extreme_tnt(pos,range)
3         local pos = vector.floor(vector.add(pos,0.5))
4         
5         --kill
6         --[[
7         for _,object in ipairs(minetest.get_objects_inside_radius(pos, range)) do
8                 if  object:is_player() then 
9                         object:set_hp(-50)
10                 elseif object:get_luaentity() and object:get_luaentity().name == "__builtin:item" then
11                         object:remove()
12                 end
13         end
14         ]]--
15         
16         local delay = 0
17         for x=-1,0 do
18         for y=-1,0 do
19         for z=-1,0 do
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")
28                         
29                         for x=min.x, max.x do
30                         for y=min.y, max.y do
31                         for z=min.z, max.z do
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
35                                 --end
36                         end
37                         end
38                         end
39                         vm:set_data(data)
40                         vm:write_to_map()
41                 end,pos,range,x,y,z)
42                 delay = delay + 1
43         end
44         end
45         end
46         
47         minetest.sound_play("tnt_explode", {pos = pos, gain = 1.0, max_hear_distance = range*range*range})
48 end
49 --[[
50 minetest.register_globalstep(function(dtime)
51         --collection
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)
58                 
59                 local ray = minetest.raycast(pos, pos2, false, false)           
60                 if ray then
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})
66                                 --end
67                         end
68                 end
69         end
70 end)
71 ]]--
72 --use raycasting to create actual explosion
73 local old_node_table
74 local p_pos
75 local n_pos
76 local n
77 local node2
78 local ray
79 local stop
80 local found
81 local positional_data
82 local pos2 = vector.new(0,0,0)
83 function tnt(pos,range)
84         local pos = vector.floor(vector.add(pos,0.5))
85         local min = vector.add(pos,range)
86         local max = vector.subtract(pos,range)
87         local vm = minetest.get_voxel_manip()   
88         local emin, emax = vm:read_from_map(min,max)
89         local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
90         local data = vm:get_data()
91         
92         local air = minetest.get_content_id("air")
93         local content_id = minetest.get_name_from_content_id
94         
95         local insert = table.insert
96         
97         vm:get_light_data()
98         
99         --throw players and items
100         for _,object in ipairs(minetest.get_objects_inside_radius(pos, range)) do
101                 if object:is_player() or (object:get_luaentity() and object:get_luaentity().name == "__builtin:item") then
102                         local ppos = object:getpos()
103                         ray = minetest.raycast(pos, ppos, false, false)
104                         local clear = true
105                         for pointed_thing in ray do
106                                 n_pos = area:index(pointed_thing.under.x,pointed_thing.under.y,pointed_thing.under.z)
107                                 node2 = content_id(data[n_pos])
108                                 if node2 == "nether:obsidian" or node2 == "nether:bedrock" then
109                                         clear = false
110                                 end
111                         end
112                         
113                         if clear == true then
114                                 local power = (range - vector.distance(pos,ppos))*2
115                                 local dir = vector.subtract(ppos,pos)
116                                 local force = vector.multiply(dir,power)
117                                 if object:is_player() then
118                                         --damage the player
119                                         local hp = object:get_hp()
120                                         if hp then
121                                                 object:set_hp(hp - math.floor(power*2))
122                                         end
123                                         object:add_player_velocity(force)
124                                 elseif object:get_luaentity() and object:get_luaentity().name == "__builtin:item" then
125                                         object:setvelocity(force)
126                                 end
127                         end
128                 end
129         end
130         
131         --raycast explosion
132         for x=-range, range do
133         for y=-range, range do
134         for z=-range, range do
135                 local distance = vector.distance(pos2, vector.new(x,y,z))
136                 if distance <= range and distance >= range-1 then
137                         
138                         p_pos = area:index(pos.x+x,pos.y+y,pos.z+z)
139                         n = content_id(data[p_pos])
140                         
141                         ray = minetest.raycast(pos, vector.new(pos.x+x,pos.y+y,pos.z+z), false, false)
142                         
143                         for pointed_thing in ray do
144                                 n_pos = area:index(pointed_thing.under.x,pointed_thing.under.y,pointed_thing.under.z)
145                                 node2 = content_id(data[n_pos])
146                                 
147                                 if node2 == "nether:obsidian" or node2 == "nether:bedrock" then
148                                         break
149                                 elseif node2 == "tnt:tnt" then
150                                         data[n_pos] = air
151                                         local obj = minetest.add_entity(vector.new(pointed_thing.under.x,pointed_thing.under.y,pointed_thing.under.z), "tnt:tnt")
152                                         if obj then
153                                                 obj:get_luaentity().timer = math.random()
154                                         end
155                                 else
156                                         data[n_pos] = air
157                                         minetest.after(0, function(pointed_thing)
158                                                 minetest.check_for_falling(vector.new(pointed_thing.under.x,pointed_thing.under.y+1,pointed_thing.under.z))
159                                         end,pointed_thing)
160                                         if math.random()>0.99 then
161                                                 local item = minetest.get_node_drops(n, "main:diamondpick")[1]
162                                                 local ppos = vector.new(pointed_thing.under.x,pointed_thing.under.y,pointed_thing.under.z)
163                                                 local obj = minetest.add_item(ppos, item)
164                                                 if obj then
165                                                         local power = (range - vector.distance(pos,ppos))*2
166                                                         local dir = vector.subtract(ppos,pos)
167                                                         local force = vector.multiply(dir,power)
168                                                         obj:setvelocity(force)
169                                                 end
170                                                 
171                                         end
172                                 end
173                         end
174                 end
175         end
176         end
177         end
178         vm:set_data(data)
179         vm:calc_lighting()
180         vm:update_liquids()
181         vm:write_to_map()
182         
183         
184         
185         minetest.sound_play("tnt_explode", {pos = pos, gain = 1.0, max_hear_distance = range*range}) --hear twice as far away
186         
187         --stop client from lagging
188         local particle = range
189         if particle > 15 then
190                 particle = 15
191         end
192         
193
194         minetest.add_particlespawner({
195                 amount = particle*particle*particle,
196                 time = 0.001,
197                 minpos = pos,
198                 maxpos = pos,
199                 minvel = vector.new(-range,-range,-range),
200                 maxvel = vector.new(range,range,range),
201                 minacc = {x=0, y=0, z=0},
202                 maxacc = {x=0, y=0, z=0},
203                 minexptime = 1.1,
204                 maxexptime = 1.5,
205                 minsize = 1,
206                 maxsize = 2,
207                 collisiondetection = true,
208                 collision_removal = true,
209                 vertical = false,
210                 texture = "smoke.png",
211         })
212                 
213 end
214
215
216 minetest.register_entity("tnt:tnt", {
217         initial_properties = {
218                 hp_max = 1,
219                 physical = true,
220                 collide_with_objects = false,
221                 collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
222                 visual = "cube",
223                 visual_size = {x = 1, y = 1},
224                 textures = {"tnt_top.png", "tnt_bottom.png",
225                         "tnt_side.png", "tnt_side.png",
226                         "tnt_side.png", "tnt_side.png"},
227                 is_visible = true,
228                 pointable = true,
229         },
230
231         timer = 5,
232         range = 7,
233         
234         get_staticdata = function(self)
235                 return minetest.serialize({
236                         range = self.range,
237                         timer = self.timer,                     
238                 })
239         end,
240         
241         on_activate = function(self, staticdata, dtime_s)
242                 self.object:set_armor_groups({immortal = 1})
243                 self.object:set_velocity({x = math.random(-5,5), y = 5, z = math.random(-5,5)})
244                 self.object:set_acceleration({x = 0, y = -9.81, z = 0})
245                 if string.sub(staticdata, 1, string.len("return")) == "return" then
246                         local data = minetest.deserialize(staticdata)
247                         if data and type(data) == "table" then
248                                 self.range = data.range
249                                 self.timer = data.timer
250                         end
251                 end
252                 
253                 minetest.add_particlespawner({
254                         amount = 50,
255                         time = 0,
256                         minpos = pos,
257                         maxpos = pos,
258                         minvel = vector.new(-0.5,1,-0.5),
259                         maxvel = vector.new(0.5,5,0.5),
260                         minacc = {x=0, y=0, z=0},
261                         maxacc = {x=0, y=0, z=0},
262                         minexptime = 1.1,
263                         maxexptime = 1.5,
264                         minsize = 1,
265                         maxsize = 2,
266                         collisiondetection = false,
267                         vertical = false,
268                         texture = "smoke.png",
269                         attached = self.object,
270                 })
271                 minetest.sound_play("tnt_ignite", {object = self.object, gain = 1.0, max_hear_distance = self.range*self.range*self.range})
272         end,
273                 
274         on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
275                 local obj = minetest.add_item(self.object:getpos(), "tnt:tnt")
276                 self.object:remove()
277         end,
278
279         sound_played = false,
280         on_step = function(self, dtime)
281                 self.timer = self.timer - dtime
282                 local vel = self.object:getvelocity()
283                 vel = vector.multiply(vel,-0.05)
284                 self.object:add_velocity(vector.new(vel.x,0,vel.z))
285                 
286                 if self.timer <= 0 then
287                         local pos = self.object:getpos()
288                         if not self.range then
289                                 self.range = 7
290                         end
291                         if self.extreme == true then
292                                 extreme_tnt(pos,self.range)
293                         else
294                                 tnt(pos,self.range)
295                         end
296                         self.object:remove()
297                 end
298         end,
299 })
300
301
302 minetest.register_node("tnt:tnt", {
303     description = "Cobblestone",
304     tiles = {"tnt_top.png", "tnt_bottom.png",
305                         "tnt_side.png", "tnt_side.png",
306                         "tnt_side.png", "tnt_side.png"},
307     groups = {stone = 2, hard = 1, pickaxe = 2, hand = 4, redstone_activation = 1},
308     sounds = main.stoneSound(),
309     redstone_activation = function(pos)
310                 local obj = minetest.add_entity(pos,"tnt:tnt")
311                 local range = 7
312                 obj:get_luaentity().range = range
313                 minetest.remove_node(pos)
314     end,
315     on_punch = function(pos, node, puncher, pointed_thing)
316                 local obj = minetest.add_entity(pos,"tnt:tnt")
317                 local range = 7
318                 obj:get_luaentity().range = range
319                 minetest.remove_node(pos)
320     end,
321 })
322
323 minetest.register_node("tnt:uranium_tnt", {
324     description = "Cobblestone",
325     tiles = {"tnt_top.png^[colorize:green:100", "tnt_bottom.png^[colorize:green:100",
326                         "tnt_side.png^[colorize:green:100", "tnt_side.png^[colorize:green:100",
327                         "tnt_side.png^[colorize:green:100", "tnt_side.png^[colorize:green:100"},
328     groups = {stone = 2, hard = 1, pickaxe = 2, hand = 4},
329     sounds = main.stoneSound(),
330     on_punch = function(pos, node, puncher, pointed_thing)
331                 local obj = minetest.add_entity(pos,"tnt:tnt")
332                 local range = 50
333                 obj:get_luaentity().range = range
334                 obj:get_luaentity().timer = 7
335                 obj:get_luaentity().extreme = true
336                 
337                 minetest.remove_node(pos)
338     end,
339 })
340
341 minetest.register_node("tnt:uh_oh", {
342     description = "Cobblestone",
343     tiles = {"tnt_top.png", "tnt_bottom.png",
344                         "tnt_side.png", "tnt_side.png",
345                         "tnt_side.png", "tnt_side.png"},
346     groups = {stone = 2, hard = 1, pickaxe = 2, hand = 4},
347     sounds = main.stoneSound(),
348     on_punch = function(pos, node, puncher, pointed_thing)
349                 local range = 10
350                 for x=-range, range do
351                 for y=-range, range do
352                 for z=-range, range do 
353                         minetest.add_node(vector.new(pos.x+x,pos.y+y,pos.z+z),{name="tnt:tnt"})
354                 end
355                 end
356                 end
357     end,
358 })
359
360
361
362 minetest.register_craft({
363         output = "tnt:tnt",
364         recipe = {
365                 {"main:wood", "main:wood", "main:wood"},
366                 {"main:wood", "main:coal", "main:wood"},
367                 {"main:wood", "main:wood", "main:wood"},
368         },
369 })