init.lua 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. if minetest.settings:get("bows_unmodified") then --ed
  2. nitroglycerine={}
  3. nitroglycerine.explode=function(pos,node)
  4. if not (pos and pos.x and pos.y and pos.z) then return end
  5. if not node then node={} end
  6. node.radius= node.radius or 3
  7. node.set= node.set or ""
  8. node.place= node.place or {"nitroglycerine:fire","air","air","air","air"}
  9. node.place_chance=node.place_chance or 5
  10. node.user_name=node.user_name or ""
  11. node.drops=node.drops or 1
  12. node.velocity=node.velocity or 1
  13. node.hurt=node.hurt or 1
  14. node.blow_nodes=node.blow_nodes or 1
  15. if node.blow_nodes==1 then
  16. local nodes={}
  17. if node.set~="" then node.set=minetest.get_content_id(node.set) end
  18. local nodes_n=0
  19. for i, v in pairs(node.place) do
  20. nodes_n=i
  21. nodes[i]=minetest.get_content_id(v)
  22. end
  23. if node.place_chance<=1 then node.place_chance=2 end
  24. if nodes_n<=1 then nodes_n=2 end
  25. local air=minetest.get_content_id("air")
  26. pos=vector.round(pos)
  27. local pos1 = vector.subtract(pos, node.radius)
  28. local pos2 = vector.add(pos, node.radius)
  29. local vox = minetest.get_voxel_manip()
  30. local min, max = vox:read_from_map(pos1, pos2)
  31. local area = VoxelArea:new({MinEdge = min, MaxEdge = max})
  32. local data = vox:get_data()
  33. for z = -node.radius, node.radius do
  34. for y = -node.radius, node.radius do
  35. for x = -node.radius, node.radius do
  36. local rad = vector.length(vector.new(x,y,z))
  37. local v = area:index(pos.x+x,pos.y+y,pos.z+z)
  38. local p={x=pos.x+x,y=pos.y+y,z=pos.z+z}
  39. if data[v]~=air and node.radius/rad>=1 and minetest.is_protected(p, node.user_name)==false then
  40. local no=minetest.registered_nodes[minetest.get_node(p).name]
  41. if no and no.on_blast then
  42. no.on_blast(p,node.radius)
  43. end
  44. if node.set~="" then
  45. data[v]=node.set
  46. end
  47. if math.random(1,node.place_chance)==1 then
  48. data[v]=nodes[math.random(1,nodes_n)]
  49. end
  50. if node.drops==1 and data[v]==air and math.random(1,4)==1 then
  51. local n=minetest.get_node(p)
  52. if no and no.walkable and math.random(1,2)==1 then
  53. nitroglycerine.spawn_dust(p)
  54. else
  55. for _, item in pairs(minetest.get_node_drops(n.name, "")) do
  56. if p and item then minetest.add_item(p, item) end
  57. end
  58. end
  59. end
  60. end
  61. end
  62. end
  63. end
  64. vox:set_data(data)
  65. vox:write_to_map()
  66. vox:update_map()
  67. vox:update_liquids()
  68. end
  69. if node.hurt==1 then
  70. for _, ob in ipairs(minetest.get_objects_inside_radius(pos, node.radius*2)) do
  71. if not (ob:get_luaentity() and (ob:get_luaentity().itemstring or ob:get_luaentity().nitroglycerine_dust)) then
  72. local pos2=ob:get_pos()
  73. local d=math.max(1,vector.distance(pos,pos2))
  74. local dmg=(8/d)*node.radius
  75. ob:punch(ob,1,{full_punch_interval=1,damage_groups={fleshy=dmg}})
  76. elseif ob:get_luaentity() then
  77. ob:get_luaentity().age=890
  78. end
  79. end
  80. end
  81. if node.velocity==1 then
  82. for _, ob in ipairs(minetest.get_objects_inside_radius(pos, node.radius*2)) do
  83. local pos2=ob:get_pos()
  84. local d=math.max(1,vector.distance(pos,pos2))
  85. local dmg=(8/d)*node.radius
  86. if ob:get_luaentity() and not ob:get_luaentity().attachplayer and not (ob:get_luaentity().nitroglycerine_dust and ob:get_luaentity().nitroglycerine_dust==2) then
  87. ob:set_velocity({x=(pos2.x-pos.x)*dmg, y=(pos2.y-pos.y)*dmg, z=(pos2.z-pos.z)*dmg})
  88. if ob:get_luaentity() and ob:get_luaentity().nitroglycerine_dust then ob:get_luaentity().nitroglycerine_dust=2 end
  89. elseif ob:is_player() then
  90. nitroglycerine.new_player=ob
  91. minetest.add_entity({x=pos2.x,y=pos2.y+1,z=pos2.z}, "nitroglycerine:playerp"):set_velocity({x=(pos2.x-pos.x)*dmg, y=(pos2.y-pos.y)*dmg, z=(pos2.z-pos.z)*dmg})
  92. nitroglycerine.new_player=nil
  93. end
  94. end
  95. end
  96. minetest.sound_play("nitroglycerine_explode", {pos=pos, gain = 0.5, max_hear_distance = node.radius*8})
  97. if node.radius>9 then
  98. minetest.sound_play("nitroglycerine_nuke", {pos=pos, gain = 0.5, max_hear_distance = node.radius*30})
  99. end
  100. minetest.add_particlespawner({
  101. amount = 20,
  102. time =0.2,
  103. minpos = {x=pos.x-1, y=pos.y, z=pos.z-1},
  104. maxpos = {x=pos.x+1, y=pos.y, z=pos.z+1},
  105. minvel = {x=-5, y=0, z=-5},
  106. maxvel = {x=5, y=5, z=5},
  107. minacc = {x=0, y=2, z=0},
  108. maxacc = {x=0, y=0, z=0},
  109. minexptime = 1,
  110. maxexptime = 2,
  111. minsize = 5,
  112. maxsize = 10,
  113. texture = "default_item_smoke.png",
  114. collisiondetection = true,
  115. })
  116. end
  117. nitroglycerine.punchdmg=function(ob,hp)
  118. if not ob or type(ob)~="userdata" then return end
  119. hp=hp or 1
  120. ob:punch(ob,1,{full_punch_interval=1,damage_groups={fleshy=hp}})
  121. end
  122. nitroglycerine.freeze=function(ob)
  123. local p=ob:get_properties()
  124. local pos=ob:get_pos()
  125. if ob:is_player() then
  126. pos=vector.round(pos)
  127. local node=minetest.get_node(pos)
  128. if node==nil or node.name==nil or minetest.registered_nodes[node.name].buildable_to==false then return end
  129. minetest.set_node(pos, {name = "nitroglycerine:icebox"})
  130. minetest.after(0.5, function(pos, ob)
  131. pos.y=pos.y-0.5
  132. ob:move_to(pos,false)
  133. end, pos, ob)
  134. return
  135. end
  136. if not ob:get_luaentity() then return end
  137. if p.visual=="mesh" and p.mesh~="" and p.mesh~=nil and ob:get_luaentity().name~="nitroglycerine:ice" then
  138. nitroglycerine.newice=true
  139. local m=minetest.add_entity(pos, "nitroglycerine:ice")
  140. m:set_yaw(ob:get_yaw())
  141. m:set_properties({
  142. visual_size=p.visual_size,
  143. visual="mesh",
  144. mesh=p.mesh,
  145. textures={"default_ice.png","default_ice.png","default_ice.png","default_ice.png","default_ice.png","default_ice.png"},
  146. collisionbox=p.collisionbox
  147. })
  148. elseif ob:get_luaentity().name~="nitroglycerine:ice" then
  149. minetest.add_item(pos,"default:ice")
  150. end
  151. local hp=ob:get_hp()+1
  152. ob:get_luaentity().destroy=1
  153. ob:punch(ob,1,{full_punch_interval=1,damage_groups={fleshy=hp}})
  154. if ob:get_luaentity().aliveai then
  155. for _, ob in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
  156. if ob:get_luaentity() and ob:get_luaentity().type and ob:get_luaentity().type=="" then
  157. ob:remove()
  158. end
  159. end
  160. end
  161. end
  162. nitroglycerine.spawn_dust=function(pos)
  163. if not pos then return end
  164. local drop=minetest.get_node_drops(minetest.get_node(pos).name)[1]
  165. local n=minetest.registered_nodes[minetest.get_node(pos).name]
  166. if not (n and n.walkable) or drop=="" or type(drop)~="string" then return end
  167. local t=n.tiles
  168. if not t[1] then return end
  169. local tx={}
  170. local tt={}
  171. tt.t1=t[1]
  172. tt.t2=t[1]
  173. tt.t3=t[1]
  174. if t[2] then tt.t2=t[2] tt.t3=t[2] end
  175. if t[3] and t[3].name then tt.t3=t[3].name
  176. elseif t[3] then tt.t3=t[3]
  177. end
  178. if type(tt.t3)=="table" then return end
  179. tx[1]=tt.t1
  180. tx[2]=tt.t2
  181. tx[3]=tt.t3
  182. tx[4]=tt.t3
  183. tx[5]=tt.t3
  184. tx[6]=tt.t3
  185. nitroglycerine.new_dust={t=tx,drop=drop}
  186. minetest.add_entity(pos, "nitroglycerine:dust")
  187. nitroglycerine.new_dust=nil
  188. end
  189. minetest.register_entity("nitroglycerine:ice",{
  190. hp_max = 1,
  191. physical = true,
  192. weight = 5,
  193. collisionbox = {-0.3,-0.3,-0.3, 0.3,0.3,0.3},
  194. visual = "sprite",
  195. visual_size = {x=0.7, y=0.7},
  196. textures = {},
  197. colors = {},
  198. spritediv = {x=1, y=1},
  199. initial_sprite_basepos = {x=0, y=0},
  200. is_visible = true,
  201. makes_footstep_sound = true,
  202. automatic_rotate = false,
  203. on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
  204. local pos=self.object:get_pos()
  205. minetest.sound_play("default_break_glass", {pos=pos, gain = 1.0, max_hear_distance = 10,})
  206. nitroglycerine.crush(pos)
  207. end,
  208. on_activate=function(self, staticdata)
  209. if nitroglycerine.newice then
  210. nitroglycerine.newice=nil
  211. else
  212. self.object:remove()
  213. end
  214. self.object:set_acceleration({x = 0, y = -10, z = 0})
  215. self.object:set_velocity({x = 0, y = -10, z = 0})
  216. end,
  217. on_step = function(self, dtime)
  218. self.timer=self.timer+dtime
  219. if self.timer<1 then return true end
  220. self.timer=0
  221. self.timer2=self.timer2+dtime
  222. if self.timer2>0.8 then
  223. minetest.sound_play("default_break_glass", {pos=self.object:get_pos(), gain = 1.0, max_hear_distance = 10,})
  224. self.object:remove()
  225. nitroglycerine.crush(self.object:get_pos())
  226. return true
  227. end
  228. end,
  229. timer = 0,
  230. timer2 = 0,
  231. })
  232. minetest.register_entity("nitroglycerine:dust",{
  233. hp_max = 1000,
  234. physical =true,
  235. weight = 0,
  236. collisionbox = {-0.5,-0.5,-0.5,0.5,0.5,0.5},
  237. visual = "cube",
  238. visual_size = {x=1,y=1},
  239. textures ={"nitroglycerine_air.png"},
  240. spritediv = {x=1, y=1},
  241. initial_sprite_basepos = {x=0, y=0},
  242. is_visible = true,
  243. makes_footstep_sound = true,
  244. on_punch2=function(self)
  245. minetest.add_item(self.object:get_pos(),self.drop)
  246. self.object:remove()
  247. return self
  248. end,
  249. on_activate=function(self, staticdata)
  250. if not nitroglycerine.new_dust then self.object:remove() return self end
  251. self.drop=nitroglycerine.new_dust.drop
  252. self.object:set_properties({textures = nitroglycerine.new_dust.t})
  253. self.object:set_acceleration({x=0,y=-10,z=0})
  254. return self
  255. end,
  256. on_step=function(self, dtime)
  257. self.time=self.time+dtime
  258. if self.time<self.timer then return self end
  259. self.time=0
  260. self.timer2=self.timer2-1
  261. local pos=self.object:get_pos()
  262. local u=minetest.registered_nodes[minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z}).name]
  263. if u and u.walkable then
  264. local n=minetest.registered_nodes[minetest.get_node(pos).name]
  265. if n and n.buildable_to and minetest.registered_nodes[self.drop] then
  266. minetest.set_node(pos,{name=self.drop})
  267. self.object:remove()
  268. else
  269. self.on_punch2(self)
  270. end
  271. return self
  272. elseif self.timer2<0 then
  273. self.on_punch2(self)
  274. end
  275. return self
  276. end,
  277. time=0,
  278. timer=2,
  279. timer2=10,
  280. nitroglycerine_dust=1,
  281. })
  282. minetest.register_entity("nitroglycerine:playerp",{
  283. hp_max = 1000,
  284. physical =true,
  285. collisionbox = {-0.5,-0.5,-0.5,0.5,1.5,0.5},
  286. visual = "sprite",
  287. textures ={"nitroglycerine_air.png"},
  288. is_visible = true,
  289. makes_footstep_sound = false,
  290. pointable=false,
  291. on_punch=function(self)
  292. local v=self.object:get_velocity().y
  293. if v<0.2 and v>-0.2 then
  294. self.kill(self)
  295. end
  296. end,
  297. kill=function(self,liquid)
  298. if self.ob and self.ob:get_attach() then
  299. self.ob:set_detach()
  300. if not (liquid and liquid>0) then
  301. local from=math.floor((self.y+0.5)/2)
  302. local hit=math.floor((self.object:get_pos().y+0.5)/2)
  303. local d=from-hit
  304. if d>=0 then
  305. nitroglycerine.punchdmg(self.ob,d)
  306. end
  307. end
  308. end
  309. self.object:remove()
  310. return self
  311. end,
  312. on_activate=function(self, staticdata)
  313. if not nitroglycerine.new_player or minetest.check_player_privs(nitroglycerine.new_player:get_player_name(), {fly=true}) then self.object:remove() return self end
  314. self.ob=nitroglycerine.new_player
  315. self.ob:set_attach(self.object, "",{x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
  316. self.object:set_acceleration({x=0,y=-10,z=0})
  317. self.y=self.object:get_pos().y
  318. return self
  319. end,
  320. on_step=function(self, dtime)
  321. self.time=self.time+dtime
  322. if self.time<self.timer then return self end
  323. self.time=0
  324. self.timer2=self.timer2-1
  325. local pos=self.object:get_pos()
  326. if pos.y>self.y then self.y=pos.y end
  327. local u=minetest.registered_nodes[minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z}).name]
  328. if (u and u.walkable or u.liquid_viscosity>0) or self.timer2<0 or (not self.ob or not self.ob:get_attach()) then
  329. self.kill(self,u.liquid_viscosity)
  330. end
  331. return self
  332. end,
  333. time=0,
  334. timer=0.5,
  335. timer2=100,
  336. attachplayer=1,
  337. })
  338. minetest.register_node("nitroglycerine:icebox", {
  339. description = "Ice box",
  340. wield_scale = {x=2, y=2, z=2},
  341. drawtype = "nodebox",
  342. node_box = {
  343. type = "fixed",
  344. fixed = {
  345. {-0.5, -0.5, -0.5, 0.5, -0.4375, 0.5},
  346. {-0.5, -0.5, -0.5, 0.5, 1.5, -0.4375},
  347. {-0.5, -0.5, 0.4375, 0.5, 1.5, 0.5},
  348. {0.4375, -0.5, -0.4375, 0.5, 1.5, 0.4375},
  349. {-0.5, -0.5, -0.4375, -0.4375, 1.5, 0.4375},
  350. {-0.5, 1.5, -0.5, 0.5, 1.4375, 0.5},
  351. }
  352. },
  353. drop="default:ice",
  354. tiles = {"default_ice.png"},
  355. groups = {cracky = 1, level = 2, not_in_creative_inventory=1},
  356. sounds = default.node_sound_glass_defaults(),
  357. paramtype = "light",
  358. sunlight_propagates = true,
  359. alpha = 30,
  360. is_ground_content = false,
  361. drowning = 1,
  362. damage_per_second = 2,
  363. on_construct = function(pos)
  364. minetest.get_node_timer(pos):start(20)
  365. end,
  366. on_timer = function (pos, elapsed)
  367. for i, ob in pairs(minetest.get_objects_inside_radius(pos, 1)) do
  368. return true
  369. end
  370. minetest.sound_play("default_break_glass", {pos=pos, gain = 1.0, max_hear_distance = 10,})
  371. minetest.set_node(pos, {name = "air"})
  372. nitroglycerine.crush(pos)
  373. return false
  374. end,
  375. type="",
  376. })
  377. nitroglycerine.crush=function(pos)
  378. minetest.add_particlespawner({
  379. amount = 15,
  380. time =0.1,
  381. minpos = pos,
  382. maxpos = pos,
  383. minvel = {x=-2, y=-2, z=-2},
  384. maxvel = {x=2, y=2, z=2},
  385. minacc = {x=0, y=-8, z=0},
  386. maxacc = {x=0, y=-10, z=0},
  387. minexptime = 2,
  388. maxexptime = 1,
  389. minsize = 0.1,
  390. maxsize = 3,
  391. texture = "default_ice.png",
  392. collisiondetection = true,
  393. })
  394. end
  395. minetest.register_node("nitroglycerine:fire", {
  396. description = "fire",
  397. inventory_image = "fire_basic_flame.png",
  398. drawtype = "firelike",
  399. tiles = {
  400. {
  401. name = "fire_basic_flame_animated.png",
  402. animation = {
  403. type = "vertical_frames",
  404. aspect_w = 16,
  405. aspect_h = 16,
  406. length = 1
  407. },
  408. },
  409. },
  410. paramtype = "light",
  411. light_source = 10,
  412. walkable = false,
  413. buildable_to = true,
  414. sunlight_propagates = true,
  415. damage_per_second = 4,
  416. groups = {dig_immediate = 2,not_in_creative_inventory=1},
  417. drop="",
  418. })
  419. minetest.register_node("nitroglycerine:fire2", {
  420. description = "fire",
  421. inventory_image = "fire_basic_flame.png",
  422. drawtype = "firelike",
  423. tiles = {
  424. {
  425. name = "fire_basic_flame_animated.png",
  426. animation = {
  427. type = "vertical_frames",
  428. aspect_w = 16,
  429. aspect_h = 16,
  430. length = 1
  431. },
  432. },
  433. },
  434. paramtype = "light",
  435. light_source = 5,
  436. walkable = false,
  437. buildable_to = true,
  438. sunlight_propagates = true,
  439. damage_per_second = 4,
  440. groups = {dig_immediate = 2,not_in_creative_inventory=1},
  441. drop="",
  442. })
  443. minetest.register_abm({
  444. nodenames = {"nitroglycerine:fire","nitroglycerine:fire2"},
  445. interval = 1.0,
  446. chance = 1,
  447. action = function(pos, node, active_object_count, active_object_count_wider)
  448. local n=minetest.get_node(pos).name
  449. if n=="nitroglycerine:fire" and math.random(1,20)==1 then
  450. minetest.set_node(pos, {name = "air"})
  451. elseif n=="nitroglycerine:fire2" and math.random(1,5)==1 then
  452. minetest.set_node(pos, {name = "air"})
  453. end
  454. end,
  455. })
  456. end--ed