Repository for the rocket mod.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1101 lines
29KB

  1. --Helper Functions
  2. local function get_sign(i)
  3. if i == 0 then
  4. return 0
  5. else
  6. return i / math.abs(i)
  7. end
  8. end
  9. local function get_velocity(v, yaw, y)
  10. local x = -math.sin(yaw) * v
  11. local z = math.cos(yaw) * v
  12. return {x = x, y = y, z = z}
  13. end
  14. local function get_v(v)
  15. return math.sqrt(v.x ^ 2 + v.z ^ 2)
  16. end
  17. --Entities
  18. --Vertical rocket: lift off, landing
  19. local rocket = {
  20. initial_properties = {
  21. hp_max = 50,
  22. physical = true,
  23. collide_with_objects = false, -- Workaround fix for a MT engine bug
  24. collisionbox = {-0.85, 0.0, -0.85, 0.85, 5.0, 0.85}, --{-0.85, -1.5, -0.85, 0.85, 1.5, 0.85},
  25. visual = "mesh",
  26. mesh = "rocket.obj",
  27. visual_size = {x = 1.0, y = 1.0, z = 1.0},
  28. textures = {"rocket.png"},
  29. },
  30. -- Custom fields
  31. driver = nil,
  32. removed = false,
  33. v = 0,
  34. vy = 0,
  35. rot = 0,
  36. auto = false,
  37. soundThrust = nil,
  38. }
  39. function rocket.on_punch(self, puncher)
  40. if not puncher or not puncher:is_player() or self.removed then
  41. return
  42. end
  43. local name = puncher:get_player_name()
  44. if self.driver and name == self.driver then
  45. -- Detach
  46. self.driver = nil
  47. puncher:set_detach()
  48. default.player_attached[name] = false
  49. minetest.sound_stop(self.soundThrust)
  50. end
  51. if not self.driver then
  52. -- Move to inventory
  53. self.removed = true
  54. local inv = puncher:get_inventory()
  55. if not (creative and creative.is_enabled_for
  56. and creative.is_enabled_for(name))
  57. or not inv:contains_item("main", "rocket:rocket_item") then
  58. local leftover = inv:add_item("main", "rocket:rocket_item")
  59. if not leftover:is_empty() then
  60. minetest.add_item(self.object:getpos(), leftover)
  61. end
  62. end
  63. minetest.after(0.1, function()
  64. self.object:remove()
  65. end)
  66. end
  67. end
  68. function rocket.on_rightclick(self, clicker)
  69. if not clicker or not clicker:is_player() then
  70. return
  71. end
  72. local name = clicker:get_player_name()
  73. if self.driver and name == self.driver then
  74. -- Detach
  75. self.driver = nil
  76. self.auto = false
  77. clicker:set_detach()
  78. default.player_attached[name] = false
  79. default.player_set_animation(clicker, "stand" , 30)
  80. local pos = clicker:getpos()
  81. minetest.after(0.1, function()
  82. clicker:setpos(pos)
  83. end)
  84. minetest.sound_stop(self.soundThrust)
  85. elseif not self.driver then
  86. -- Attach
  87. local attach = clicker:get_attach()
  88. if attach and attach:get_luaentity() then
  89. local luaentity = attach:get_luaentity()
  90. if luaentity.driver then
  91. luaentity.driver = nil
  92. end
  93. clicker:set_detach()
  94. end
  95. self.driver = name
  96. clicker:set_attach(self.object, "",
  97. {x = 0, y = 2, z = 0}, {x = 0, y = 4, z = 0})
  98. default.player_attached[name] = true
  99. minetest.after(0.2, function()
  100. -- default.player_set_animation(clicker, "sit" , 30)
  101. default.player_set_animation(clicker, "stand" , 30)
  102. end)
  103. clicker:set_look_horizontal(self.object:getyaw())
  104. self.soundThrust=minetest.sound_play({name="thrust"},{object = self.object, gain = 2.0, max_hear_distance = 4, loop = true,}) --old: max_hear_distance = 32
  105. --minetest.sound_play({name="fire_fire.3.ogg"},{object = self.object, gain = 2.0, max_hear_distance = 32, loop = true,})
  106. --[[
  107. Fuel Display Hud (abandoned)
  108. local fuel_display = clicker:hud_add({ --HUD
  109. hud_elem_type = "text",
  110. position = {x = 0.5, y = 0.5},
  111. offset = {x = 0, y = 0},
  112. text = "Hello world!",
  113. alignment = {x = 0, y = 0},
  114. scale = {x = 100, y = 100},
  115. })
  116. clicker:hud_remove(fuel_display) --HUD
  117. ]]
  118. end
  119. end
  120. on_activate = function(self, staticdata, dtime_s)
  121. self.object:set_armor_groups({immortal = 1})
  122. end
  123. function rocket.on_step(self, dtime)
  124. self.v = get_v(self.object:getvelocity()) * get_sign(self.v)
  125. self.vy = self.object:getvelocity().y
  126. -- Controls
  127. if self.driver then
  128. local driver_objref = minetest.get_player_by_name(self.driver)
  129. if driver_objref then
  130. if driver_objref:get_breath() < 11 then
  131. --Oxygen system, for when in space or an unbreathable atmosphere
  132. driver_objref:set_breath(11)
  133. end
  134. local ctrl = driver_objref:get_player_control()
  135. if ctrl.jump and ctrl.sneak then --if ctrl.up and ctrl.down then
  136. if not self.auto then
  137. self.auto = true
  138. minetest.chat_send_player(self.driver,
  139. "[rocket] Cruise on")
  140. end
  141. elseif ctrl.sneak then --ctrl.down then
  142. --self.v = self.v - 0.1
  143. if self.auto then
  144. self.auto = false
  145. minetest.chat_send_player(self.driver,
  146. "[rocket] Cruise off")
  147. end
  148. --[[
  149. elseif ctrl.up or self.auto then
  150. self.v = self.v + 0.1
  151. --self.v = self.v + 10]]
  152. end
  153. if ctrl.up then
  154. self.v = self.v + 0.1
  155. --self.v = self.v + 10
  156. elseif ctrl.down then
  157. self.v = self.v - 0.1
  158. end
  159. if ctrl.left and ctrl.right and self.vy < 10 then
  160. local sideways_rocket = minetest.add_entity(self.object:getpos(), "rocket:sideways_rocket")
  161. sideways_rocket:setyaw(self.object:getyaw())
  162. default.player_set_animation(driver_objref, "sit" , 30)
  163. driver_objref:set_detach()
  164. driver_objref:set_attach(sideways_rocket, "", {x = 0, y = 1, z = 0}, {x = 0, y = 2, z = 0})
  165. minetest.sound_stop(self.soundThrust)
  166. self.object:remove()
  167. --right click after pressing A+D to go into the sideways rocket
  168. elseif ctrl.left then
  169. self.rot = self.rot + 0.001
  170. elseif ctrl.right then
  171. self.rot = self.rot - 0.001
  172. end
  173. if ctrl.jump and (not self.auto) then
  174. if self.vy < 50 then
  175. self.vy = self.vy + 0.075
  176. --self.vy = self.vy + 7.5
  177. end
  178. minetest.add_particlespawner({
  179. amount = 3, --1,
  180. time = 0.2, --0.1,
  181. minpos = {x = 0, y = 0, z = 0},
  182. maxpos = {x = 0, y = 0, z = 0},
  183. minvel = {x = -0.2, y = 0, z = -0.2},
  184. maxvel = {x = 0.3, y = 0.3, z = 0.3},
  185. minacc = {x = 0, y = 0.1, z = 0},
  186. maxacc = {x = 0, y = 0.3, z = 0},
  187. minexptime = 1,
  188. maxexptime = 2.5,
  189. minsize = 4, --1,
  190. maxsize = 10, --4,
  191. attached = self.object,
  192. texture = "rocket_smoke.png",
  193. })
  194. minetest.add_particlespawner({
  195. amount = 1, --1,
  196. time = 1.0, --0.1,
  197. minpos = {x = 0, y = 0, z = 0},
  198. maxpos = {x = 0, y = 0, z = 0},
  199. minvel = {x = -0.2, y = 0, z = -0.2},
  200. maxvel = {x = 0.3, y = 0.3, z = 0.3},
  201. minacc = {x = 0, y = 0.1, z = 0},
  202. maxacc = {x = 0, y = 0.3, z = 0},
  203. minexptime = 0.25, --1
  204. maxexptime = 0.75, --2.5,
  205. minsize = 14, --1,
  206. maxsize = 16, --4,
  207. attached = self.object,
  208. texture = "rocket_boom.png",
  209. })
  210. elseif (not (ctrl.jump or self.auto)) and self.vy > -50 then --elseif ctrl.sneak then
  211. self.vy = self.vy - 0.075
  212. --self.vy = self.vy - 7.5
  213. end
  214. if self.auto and self.vy > 0 and (not ctrl.jump) then
  215. minetest.add_particlespawner({
  216. amount = 3, --1,
  217. time = 0.2, --0.1,
  218. minpos = {x = 0, y = 0, z = 0},
  219. maxpos = {x = 0, y = 0, z = 0},
  220. minvel = {x = -0.2, y = 0, z = -0.2},
  221. maxvel = {x = 0.3, y = 0.3, z = 0.3},
  222. minacc = {x = 0, y = 0.1, z = 0},
  223. maxacc = {x = 0, y = 0.3, z = 0},
  224. minexptime = 1,
  225. maxexptime = 2.5,
  226. minsize = 4, --1,
  227. maxsize = 10, --4,
  228. attached = self.object,
  229. texture = "rocket_smoke.png",
  230. })
  231. minetest.add_particlespawner({
  232. amount = 1, --1,
  233. time = 1.0, --0.1,
  234. minpos = {x = 0, y = 0, z = 0},
  235. maxpos = {x = 0, y = 0, z = 0},
  236. minvel = {x = -0.2, y = 0, z = -0.2},
  237. maxvel = {x = 0.3, y = 0.3, z = 0.3},
  238. minacc = {x = 0, y = 0.1, z = 0},
  239. maxacc = {x = 0, y = 0.3, z = 0},
  240. minexptime = 0.25, --1
  241. maxexptime = 0.75, --2.5,
  242. minsize = 14, --1,
  243. maxsize = 16, --4,
  244. attached = self.object,
  245. texture = "rocket_boom.png",
  246. })
  247. end
  248. else
  249. -- Player left server while driving
  250. -- In MT 5.0.0 use 'rocket:on_detach_child()' to do this
  251. self.driver = nil
  252. self.auto = false
  253. minetest.log("warning", "[rocket] Driver left server while" ..
  254. " driving. This may cause some 'Pushing ObjectRef to" ..
  255. " removed/deactivated object' warnings.")
  256. end
  257. end
  258. if self.vy > 0 and (not self.driver) then
  259. minetest.add_particlespawner({
  260. amount = 3, --1,
  261. time = 0.2, --0.1,
  262. minpos = {x = 0, y = 0, z = 0},
  263. maxpos = {x = 0, y = 0, z = 0},
  264. minvel = {x = -0.2, y = 0, z = -0.2},
  265. maxvel = {x = 0.3, y = 0.3, z = 0.3},
  266. minacc = {x = 0, y = 0.1, z = 0},
  267. maxacc = {x = 0, y = 0.3, z = 0},
  268. minexptime = 1,
  269. maxexptime = 2.5,
  270. minsize = 4, --1,
  271. maxsize = 10, --4,
  272. attached = self.object,
  273. texture = "rocket_smoke.png",
  274. })
  275. minetest.add_particlespawner({
  276. amount = 1, --1,
  277. time = 1.0, --0.1,
  278. minpos = {x = 0, y = 0, z = 0},
  279. maxpos = {x = 0, y = 0, z = 0},
  280. minvel = {x = -0.2, y = 0, z = -0.2},
  281. maxvel = {x = 0.3, y = 0.3, z = 0.3},
  282. minacc = {x = 0, y = 0.1, z = 0},
  283. maxacc = {x = 0, y = 0.3, z = 0},
  284. minexptime = 0.25, --1
  285. maxexptime = 0.75, --2.5,
  286. minsize = 14, --1,
  287. maxsize = 16, --4,
  288. attached = self.object,
  289. texture = "rocket_boom.png",
  290. })
  291. end
  292. -- Early return for stationary vehicle
  293. if self.v == 0 and self.rot == 0 and self.vy == 0 then
  294. self.object:setpos(self.object:getpos())
  295. return
  296. end
  297. -- Reduction and limiting of linear speed
  298. local s = get_sign(self.v)
  299. self.v = self.v - 0.02 * s
  300. if s ~= get_sign(self.v) then
  301. self.v = 0
  302. end
  303. if math.abs(self.v) > 6 then
  304. self.v = 6 * get_sign(self.v)
  305. end
  306. -- Reduction and limiting of rotation
  307. local sr = get_sign(self.rot)
  308. self.rot = self.rot - 0.0003 * sr
  309. if sr ~= get_sign(self.rot) then
  310. self.rot = 0
  311. end
  312. if math.abs(self.rot) > 0.015 then
  313. self.rot = 0.015 * get_sign(self.rot)
  314. end
  315. -- Reduction and limiting of vertical speed
  316. --[[
  317. local sy = get_sign(self.vy)
  318. self.vy = self.vy - 0.03 * sy
  319. if sy ~= get_sign(self.vy) then
  320. self.vy = 0
  321. end
  322. if math.abs(self.vy) > 4 then
  323. self.vy = 4 * get_sign(self.vy)
  324. end
  325. ]]
  326. local new_acce = {x = 0, y = 0, z = 0}
  327. -- Bouyancy in liquids
  328. --[[
  329. local p = self.object:getpos()
  330. p.y = p.y - 1.5
  331. local def = minetest.registered_nodes[minetest.get_node(p).name]
  332. if def and (def.liquidtype == "source" or def.liquidtype == "flowing") then
  333. new_acce = {x = 0, y = 10, z = 0}
  334. end
  335. ]]
  336. --Crash landing
  337. local p = self.object:getpos()
  338. local vacuum = "air"
  339. if(minetest.get_modpath("vacuum")) ~= nil then
  340. vacuum = "vacuum:vacuum"
  341. end
  342. local p1 = self.object:getpos()
  343. p1.y = p1.y - 1
  344. if minetest.get_node(p1).name ~= "air" and minetest.get_node(p1).name ~= vacuum and self.vy < -10 then
  345. tnt.boom(p, {
  346. radius = 3,
  347. damage_radius = 6,
  348. sound = "tnt_explode",
  349. explode_center = false,
  350. })
  351. minetest.sound_stop(self.soundThrust)
  352. self.object:remove()
  353. end
  354. local p2 = self.object:getpos()
  355. p2.y = p2.y + 6
  356. local p3 = self.object:getpos()
  357. p3.y = p3.y + 4
  358. if minetest.get_node(p2).name ~= "air" and minetest.get_node(p2).name ~= vacuum and self.vy > 10 then
  359. tnt.boom(p3, {
  360. radius = 3,
  361. damage_radius = 6,
  362. sound = "tnt_explode",
  363. explode_center = false,
  364. })
  365. minetest.sound_stop(self.soundThrust)
  366. self.object:remove()
  367. end
  368. self.object:setpos(self.object:getpos())
  369. self.object:setvelocity(get_velocity(self.v, self.object:getyaw(), self.vy))
  370. self.object:setacceleration(new_acce)
  371. self.object:setyaw(self.object:getyaw() + (1 + dtime) * self.rot)
  372. end
  373. minetest.register_entity("rocket:rocket", rocket)
  374. --Horizontal rocket: moving in space, docking
  375. local sideways_rocket = {
  376. initial_properties = {
  377. hp_max = 50,
  378. physical = true,
  379. collide_with_objects = false, -- Workaround fix for a MT engine bug
  380. collisionbox = {-1, 0, -1, 1, 1.85, 1}, --old collison box (was ok sometimes, but did not turn): {-0.9, 0.0, -2.5, 0.9, 1.85, 2.5},
  381. visual = "mesh",
  382. mesh = "sideways_rocket.obj",
  383. visual_size = {x = 1.0, y = 1.0, z = 1.0},
  384. textures = {"rocket.png"},
  385. },
  386. -- Custom fields
  387. driver = nil,
  388. removed = false,
  389. v = 0,
  390. vy = 0,
  391. rot = 0,
  392. auto = false,
  393. soundThrust = nil,
  394. }
  395. function sideways_rocket.on_punch(self, puncher)
  396. if not puncher or not puncher:is_player() or self.removed then
  397. return
  398. end
  399. local name = puncher:get_player_name()
  400. if self.driver and name == self.driver then
  401. -- Detach
  402. self.driver = nil
  403. puncher:set_detach()
  404. default.player_attached[name] = false
  405. minetest.sound_stop(self.soundThrust)
  406. end
  407. if not self.driver then
  408. -- Move to inventory
  409. self.removed = true
  410. local inv = puncher:get_inventory()
  411. if not (creative and creative.is_enabled_for
  412. and creative.is_enabled_for(name))
  413. or not inv:contains_item("main", "rocket:rocket_item") then
  414. local leftover = inv:add_item("main", "rocket:rocket_item")
  415. if not leftover:is_empty() then
  416. minetest.add_item(self.object:getpos(), leftover)
  417. end
  418. end
  419. minetest.after(0.1, function()
  420. self.object:remove()
  421. end)
  422. end
  423. end
  424. function sideways_rocket.on_rightclick(self, clicker)
  425. if not clicker or not clicker:is_player() then
  426. return
  427. end
  428. local name = clicker:get_player_name()
  429. if self.driver and name == self.driver then
  430. -- Detach
  431. self.driver = nil
  432. self.auto = false
  433. clicker:set_detach()
  434. default.player_attached[name] = false
  435. default.player_set_animation(clicker, "stand" , 30)
  436. local pos = clicker:getpos()
  437. minetest.after(0.1, function()
  438. clicker:setpos(pos)
  439. end)
  440. minetest.sound_stop(self.soundThrust)
  441. elseif not self.driver then
  442. -- Attach
  443. local attach = clicker:get_attach()
  444. if attach and attach:get_luaentity() then
  445. local luaentity = attach:get_luaentity()
  446. if luaentity.driver then
  447. luaentity.driver = nil
  448. end
  449. clicker:set_detach()
  450. end
  451. self.driver = name
  452. clicker:set_attach(self.object, "",
  453. {x = 0, y = 1, z = 0}, {x = 0, y = 2, z = 0})
  454. default.player_attached[name] = true
  455. minetest.after(0.2, function()
  456. default.player_set_animation(clicker, "sit" , 30)
  457. end)
  458. clicker:set_look_horizontal(self.object:getyaw())
  459. self.soundThrust=minetest.sound_play({name="thrust"},{object = self.object, gain = 2.0, max_hear_distance = 4, loop = true,})--old: max_hear_distance = 32
  460. end
  461. end
  462. on_activate = function(self, staticdata, dtime_s)
  463. self.object:set_armor_groups({immortal = 1})
  464. end
  465. function sideways_rocket.on_step(self, dtime)
  466. self.v = get_v(self.object:getvelocity()) * get_sign(self.v)
  467. self.vy = self.object:getvelocity().y
  468. -- Controls
  469. if self.driver then
  470. local driver_objref = minetest.get_player_by_name(self.driver)
  471. if driver_objref then
  472. if driver_objref:get_breath() < 11 then
  473. --Oxygen system, for when in space or an unbreathable atmosphere
  474. driver_objref:set_breath(11)
  475. end
  476. local ctrl = driver_objref:get_player_control()
  477. if ctrl.up and ctrl.down then
  478. if not self.auto then
  479. self.auto = true
  480. minetest.chat_send_player(self.driver,
  481. "[rocket] Cruise on")
  482. end
  483. elseif ctrl.down then --braking
  484. --self.v = self.v - 0.1
  485. if self.v > 0 and self.v < 0.01 then
  486. self.v = 0
  487. elseif self.v > 0 then
  488. self.v = self.v - 0.1
  489. end
  490. if self.auto then
  491. self.auto = false
  492. minetest.chat_send_player(self.driver,
  493. "[rocket] Cruise off")
  494. end
  495. elseif ctrl.up or self.auto then
  496. --self.v = self.v + 0.1
  497. if self.v < 30.0 then
  498. self.v = self.v + 0.1
  499. end
  500. minetest.add_particlespawner({
  501. amount = 1, --1,
  502. time = 1.0, --0.1,
  503. minpos = {x = 0, y = 0.5, z = 0},
  504. maxpos = {x = 0, y = 0.5, z = 0},
  505. minvel = {x = -0.2, y = 0, z = -0.2},
  506. maxvel = {x = 0.3, y = 0.3, z = 0.3},
  507. minacc = {x = 0, y = 0.1, z = 0},
  508. maxacc = {x = 0, y = 0.3, z = 0},
  509. minexptime = 0.25, --1
  510. maxexptime = 1.0, --2.5,
  511. minsize = 14, --1,
  512. maxsize = 16, --4,
  513. attached = self.object,
  514. texture = "rocket_boom.png",
  515. })
  516. end
  517. if ctrl.left and ctrl.right and self.v < 10 then
  518. local rocket = minetest.add_entity(self.object:getpos(), "rocket:rocket")
  519. rocket:setyaw(self.object:getyaw())
  520. default.player_set_animation(driver_objref, "stand" , 30)
  521. driver_objref:set_detach()
  522. driver_objref:set_attach(rocket, "", {x = 0, y = 1, z = 0}, {x = 0, y = 2, z = 0})
  523. minetest.sound_stop(self.soundThrust)
  524. self.object:remove()
  525. --right click after pressing A+D to go into the rocket
  526. elseif ctrl.left then
  527. self.rot = self.rot + 0.001
  528. elseif ctrl.right then
  529. self.rot = self.rot - 0.001
  530. end
  531. if ctrl.jump then
  532. self.vy = self.vy + 0.075
  533. elseif ctrl.sneak then
  534. self.vy = self.vy - 0.075
  535. end
  536. else
  537. -- Player left server while driving
  538. -- In MT 5.0.0 use 'sideways_rocket:on_detach_child()' to do this
  539. self.driver = nil
  540. self.auto = false
  541. minetest.log("warning", "[rocket] Driver left server while" ..
  542. " driving. This may cause some 'Pushing ObjectRef to" ..
  543. " removed/deactivated object' warnings.")
  544. end
  545. end
  546. if self.v > 0 and (not self.driver) then
  547. minetest.add_particlespawner({
  548. amount = 1, --1,
  549. time = 1.0, --0.1,
  550. minpos = {x = 0, y = 0.5, z = 0},
  551. maxpos = {x = 0, y = 0.5, z = 0},
  552. minvel = {x = -0.2, y = 0, z = -0.2},
  553. maxvel = {x = 0.3, y = 0.3, z = 0.3},
  554. minacc = {x = 0, y = 0.1, z = 0},
  555. maxacc = {x = 0, y = 0.3, z = 0},
  556. minexptime = 0.25, --1
  557. maxexptime = 1.0, --2.5,
  558. minsize = 14, --1,
  559. maxsize = 16, --4,
  560. attached = self.object,
  561. texture = "rocket_boom.png",
  562. })
  563. end
  564. -- Early return for stationary vehicle
  565. if self.v == 0 and self.rot == 0 and self.vy == 0 then
  566. self.object:setpos(self.object:getpos())
  567. return
  568. end
  569. -- Reduction and limiting of linear speed
  570. --[[
  571. local s = get_sign(self.v)
  572. self.v = self.v - 0.02 * s
  573. if s ~= get_sign(self.v) then
  574. self.v = 0
  575. end
  576. if math.abs(self.v) > 6 then
  577. self.v = 6 * get_sign(self.v)
  578. end
  579. ]]
  580. -- Reduction and limiting of rotation
  581. local sr = get_sign(self.rot)
  582. self.rot = self.rot - 0.0003 * sr
  583. if sr ~= get_sign(self.rot) then
  584. self.rot = 0
  585. end
  586. if math.abs(self.rot) > 0.015 then
  587. self.rot = 0.015 * get_sign(self.rot)
  588. end
  589. -- Reduction and limiting of vertical speed
  590. local sy = get_sign(self.vy)
  591. self.vy = self.vy - 0.03 * sy
  592. if sy ~= get_sign(self.vy) then
  593. self.vy = 0
  594. end
  595. if math.abs(self.vy) > 4 then
  596. self.vy = 4 * get_sign(self.vy)
  597. end
  598. local new_acce = {x = 0, y = 0, z = 0}
  599. -- Bouyancy in liquids
  600. --[[
  601. local p = self.object:getpos()
  602. p.y = p.y - 1.5
  603. local def = minetest.registered_nodes[minetest.get_node(p).name]
  604. if def and (def.liquidtype == "source" or def.liquidtype == "flowing") then
  605. new_acce = {x = 0, y = 10, z = 0}
  606. end
  607. ]]
  608. --Crashing
  609. local p = self.object:getpos()
  610. local vacuum = "air"
  611. if(minetest.get_modpath("vacuum")) ~= nil then
  612. vacuum = "vacuum:vacuum"
  613. end
  614. local p1 = self.object:getpos()
  615. p1.x = p1.x + 2
  616. local p2 = self.object:getpos()
  617. p2.x = p2.x - 2
  618. local p3 = self.object:getpos()
  619. p3.z = p3.z + 2
  620. local p4 = self.object:getpos()
  621. p4.x = p4.x - 2
  622. if minetest.get_node(p1).name ~= "air" and minetest.get_node(p1).name ~= vacuum and self.v > 10 then
  623. minetest.sound_stop(self.soundThrust)
  624. self.object:remove()
  625. if driver_objref then
  626. default.player_set_animation(driver_objref, "stand" , 30)
  627. driver_objref:set_detach()
  628. end
  629. tnt.boom(p, {
  630. radius = 3,
  631. damage_radius = 6,
  632. sound = "tnt_explode",
  633. explode_center = false,
  634. })
  635. elseif minetest.get_node(p2).name ~= "air" and minetest.get_node(p2).name ~= vacuum and self.v > 10 then
  636. minetest.sound_stop(self.soundThrust)
  637. self.object:remove()
  638. if driver_objref then
  639. default.player_set_animation(driver_objref, "stand" , 30)
  640. driver_objref:set_detach()
  641. end
  642. tnt.boom(p, {
  643. radius = 3,
  644. damage_radius = 6,
  645. sound = "tnt_explode",
  646. explode_center = false,
  647. })
  648. elseif minetest.get_node(p3).name ~= "air" and minetest.get_node(p3).name ~= vacuum and self.v > 10 then
  649. minetest.sound_stop(self.soundThrust)
  650. self.object:remove()
  651. if driver_objref then
  652. default.player_set_animation(driver_objref, "stand" , 30)
  653. driver_objref:set_detach()
  654. end
  655. tnt.boom(p, {
  656. radius = 3,
  657. damage_radius = 6,
  658. sound = "tnt_explode",
  659. explode_center = false,
  660. })
  661. elseif minetest.get_node(p4).name ~= "air" and minetest.get_node(p4).name ~= vacuum and self.v > 10 then
  662. minetest.sound_stop(self.soundThrust)
  663. self.object:remove()
  664. if driver_objref then
  665. default.player_set_animation(driver_objref, "stand" , 30)
  666. driver_objref:set_detach()
  667. end
  668. tnt.boom(p, {
  669. radius = 3,
  670. damage_radius = 6,
  671. sound = "tnt_explode",
  672. explode_center = false,
  673. })
  674. end
  675. self.object:setpos(self.object:getpos())
  676. self.object:setvelocity(get_velocity(self.v, self.object:getyaw(), self.vy))
  677. self.object:setacceleration(new_acce)
  678. self.object:setyaw(self.object:getyaw() + (1 + dtime) * self.rot)
  679. end
  680. minetest.register_entity("rocket:sideways_rocket", sideways_rocket)
  681. --Main Craftitem
  682. minetest.register_craftitem("rocket:rocket_item", {
  683. description = "Space Shuttle",
  684. inventory_image = "rocket_rocket_inv.png",
  685. wield_scale = {x = 1, y = 1, z = 1},
  686. liquids_pointable = true,
  687. on_place = function(itemstack, placer, pointed_thing)
  688. local under = pointed_thing.under
  689. local node = minetest.get_node(under)
  690. local udef = minetest.registered_nodes[node.name]
  691. -- Run any on_rightclick function of pointed node instead
  692. if udef and udef.on_rightclick and
  693. not (placer and placer:is_player() and
  694. placer:get_player_control().sneak) then
  695. return udef.on_rightclick(under, node, placer, itemstack,
  696. pointed_thing) or itemstack
  697. end
  698. if pointed_thing.type ~= "node" then
  699. return itemstack
  700. end
  701. pointed_thing.under.y = pointed_thing.under.y + 0.5 -- + 2
  702. local rocket = minetest.add_entity(pointed_thing.under,
  703. "rocket:rocket")
  704. if rocket then
  705. if placer then
  706. rocket:setyaw(placer:get_look_horizontal())
  707. end
  708. local player_name = placer and placer:get_player_name() or ""
  709. if not (creative and creative.is_enabled_for and
  710. creative.is_enabled_for(player_name)) then
  711. itemstack:take_item()
  712. end
  713. end
  714. return itemstack
  715. end,
  716. })
  717. --Other craftitems
  718. minetest.register_craftitem("rocket:rocket_cone", {
  719. description = "Rocket Cone",
  720. inventory_image = "rocket_cone.png"
  721. })
  722. minetest.register_craftitem("rocket:rocket_thruster", {
  723. description = "Rocket Thruster",
  724. inventory_image = "rocket_thruster.png"
  725. })
  726. minetest.register_craftitem("rocket:rocket_hull", {
  727. description = "Rocket Hull",
  728. inventory_image = "rocket_hull.png"
  729. })
  730. minetest.register_craftitem("rocket:rocket_left_fin", {
  731. description = "Rocket Left Fin",
  732. inventory_image = "rocket_left_fin.png"
  733. })
  734. minetest.register_craftitem("rocket:rocket_right_fin", {
  735. description = "Rocket Right Fin",
  736. inventory_image = "rocket_right_fin.png"
  737. })
  738. --Crafting recipes
  739. minetest.register_craft({
  740. type = "shaped",
  741. output = "rocket:rocket_left_fin",
  742. recipe = {
  743. {"", "", "default:steel_ingot"},
  744. {"", "default:steel_ingot", "default:steel_ingot"},
  745. {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}
  746. }
  747. })
  748. minetest.register_craft({
  749. type = "shaped",
  750. output = "rocket:rocket_right_fin",
  751. recipe = {
  752. {"default:steel_ingot", "", ""},
  753. {"default:steel_ingot", "default:steel_ingot", ""},
  754. {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}
  755. }
  756. })
  757. minetest.register_craft({
  758. type = "shaped",
  759. output = "rocket:rocket_thruster",
  760. recipe = {
  761. {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
  762. {"", "default:steelblock", ""},
  763. {"default:steelblock", "fire:flint_and_steel", "default:steelblock"}
  764. }
  765. })
  766. minetest.register_craft({
  767. type = "shaped",
  768. output = "rocket:rocket_hull",
  769. recipe = {
  770. {"default:steelblock", "rocket:bucket_rocket_fuel", "default:steelblock"},
  771. {"default:steelblock", "rocket:bucket_rocket_fuel", "default:steelblock"},
  772. {"default:steelblock", "rocket:bucket_rocket_fuel", "default:steelblock"}
  773. }
  774. })
  775. minetest.register_craft({
  776. type = "shaped",
  777. output = "rocket:rocket_cone",
  778. recipe = {
  779. {"", "default:steel_ingot", ""},
  780. {"", "stairs:slab_steelblock", ""},
  781. {"stairs:slab_steelblock", "default:steelblock", "stairs:slab_steelblock"}
  782. }
  783. })
  784. minetest.register_craft({
  785. type = "shaped",
  786. output = "rocket:rocket_item",
  787. recipe = {
  788. {"", "rocket:rocket_cone", ""},
  789. {"", "rocket:rocket_hull", ""},
  790. {"rocket:rocket_left_fin", "rocket:rocket_thruster", "rocket:rocket_right_fin"}
  791. }
  792. })
  793. --Liquids
  794. --Oil
  795. minetest.register_node("rocket:oil_source", {
  796. description = "Oil Source",
  797. drawtype = "liquid",
  798. tiles = {
  799. {
  800. name = "rocket_oil_source_animated.png",
  801. animation = {
  802. type = "vertical_frames",
  803. aspect_w = 16,
  804. aspect_h = 16,
  805. length = 2.0,
  806. },
  807. },
  808. },
  809. special_tiles = {
  810. -- New-style water source material (mostly unused)
  811. {
  812. name = "rocket_oil_source_animated.png",
  813. animation = {
  814. type = "vertical_frames",
  815. aspect_w = 16,
  816. aspect_h = 16,
  817. length = 2.0,
  818. },
  819. backface_culling = false,
  820. },
  821. },
  822. alpha = 160,
  823. paramtype = "light",
  824. walkable = false,
  825. pointable = false,
  826. diggable = false,
  827. buildable_to = true,
  828. is_ground_content = false,
  829. drop = "",
  830. drowning = 1,
  831. liquidtype = "source",
  832. liquid_alternative_flowing = "rocket:oil_flowing",
  833. liquid_alternative_source = "rocket:oil_source",
  834. liquid_viscosity = 1,
  835. liquid_renewable = false,
  836. post_effect_color = {a = 103, r = 45, g = 23, b = 7},
  837. groups = {oil = 3, liquid = 1, flammable = 1},
  838. sounds = default.node_sound_water_defaults(),
  839. })
  840. minetest.register_node("rocket:oil_flowing", {
  841. description = "Flowing Oil",
  842. drawtype = "flowingliquid",
  843. tiles = {"rocket_oil_source.png"},
  844. special_tiles = {
  845. {
  846. name = "rocket_oil_flowing_animated.png",
  847. backface_culling = false,
  848. animation = {
  849. type = "vertical_frames",
  850. aspect_w = 16,
  851. aspect_h = 16,
  852. length = 0.8,
  853. },
  854. },
  855. {
  856. name = "rocket_oil_flowing_animated.png",
  857. backface_culling = true,
  858. animation = {
  859. type = "vertical_frames",
  860. aspect_w = 16,
  861. aspect_h = 16,
  862. length = 0.8,
  863. },
  864. },
  865. },
  866. alpha = 160,
  867. paramtype = "light",
  868. paramtype2 = "flowingliquid",
  869. walkable = false,
  870. pointable = false,
  871. diggable = false,
  872. buildable_to = true,
  873. is_ground_content = false,
  874. drop = "",
  875. drowning = 1,
  876. liquidtype = "flowing",
  877. liquid_alternative_flowing = "rocket:oil_flowing",
  878. liquid_alternative_source = "rocket:oil_source",
  879. liquid_viscosity = 1,
  880. liquid_renewable = false,
  881. post_effect_color = {a = 150, r = 45, g = 23, b = 7},
  882. groups = {oil = 3, liquid = 1, flammable = 1, not_in_creative_inventory = 1},
  883. sounds = default.node_sound_water_defaults(),
  884. })
  885. bucket.register_liquid(
  886. "rocket:oil_source",
  887. "rocket:oil_flowing",
  888. "rocket:bucket_oil",
  889. "rocket_bucket_oil.png",
  890. "Oil Bucket"
  891. )
  892. --Oil ore
  893. minetest.register_ore({
  894. ore_type = "scatter",
  895. ore = "rocket:oil_source",
  896. wherein = "default:stone",
  897. clust_scarcity = 17 * 17 * 17,
  898. clust_num_ores = 4,
  899. clust_size = 3,
  900. y_min = -255,
  901. y_max = -128,
  902. })
  903. minetest.register_ore({
  904. ore_type = "scatter",
  905. ore = "rocket:oil_source",
  906. wherein = "default:stone",
  907. clust_scarcity = 15 * 15 * 15,
  908. clust_num_ores = 4,
  909. clust_size = 3,
  910. y_min = -31000,
  911. y_max = -256,
  912. })
  913. --Rocket fuel
  914. minetest.register_node("rocket:rocket_fuel_source", {
  915. description = "Rocket Fuel Source",
  916. drawtype = "liquid",
  917. tiles = {
  918. {
  919. name = "rocket_rocket_fuel_source_animated.png",
  920. animation = {
  921. type = "vertical_frames",
  922. aspect_w = 16,
  923. aspect_h = 16,
  924. length = 2.0,
  925. },
  926. },
  927. },
  928. special_tiles = {
  929. -- New-style water source material (mostly unused)
  930. {
  931. name = "rocket_rocket_fuel_source_animated.png",
  932. animation = {
  933. type = "vertical_frames",
  934. aspect_w = 16,
  935. aspect_h = 16,
  936. length = 2.0,
  937. },
  938. backface_culling = false,
  939. },
  940. },
  941. alpha = 160,
  942. paramtype = "light",
  943. walkable = false,
  944. pointable = false,
  945. diggable = false,
  946. buildable_to = true,
  947. is_ground_content = false,
  948. drop = "",
  949. drowning = 1,
  950. liquidtype = "source",
  951. liquid_alternative_flowing = "rocket:rocket_fuel_flowing",
  952. liquid_alternative_source = "rocket:rocket_fuel_source",
  953. liquid_viscosity = 1,
  954. liquid_renewable = false,
  955. post_effect_color = {a = 103, r = 254, g = 0, b = 30},
  956. groups = {oil = 3, liquid = 1, flammable = 1},
  957. sounds = default.node_sound_water_defaults(),
  958. })
  959. minetest.register_node("rocket:rocket_fuel_flowing", {
  960. description = "Flowing Rocket Fuel",
  961. drawtype = "flowingliquid",
  962. tiles = {"rocket_rocket_fuel_source.png"},
  963. special_tiles = {
  964. {
  965. name = "rocket_rocket_fuel_flowing_animated.png",
  966. backface_culling = false,
  967. animation = {
  968. type = "vertical_frames",
  969. aspect_w = 16,
  970. aspect_h = 16,
  971. length = 0.8,
  972. },
  973. },
  974. {
  975. name = "rocket_rocket_fuel_flowing_animated.png",
  976. backface_culling = true,
  977. animation = {
  978. type = "vertical_frames",
  979. aspect_w = 16,
  980. aspect_h = 16,
  981. length = 0.8,
  982. },
  983. },
  984. },
  985. alpha = 160,
  986. paramtype = "light",
  987. paramtype2 = "flowingliquid",
  988. walkable = false,
  989. pointable = false,
  990. diggable = false,
  991. buildable_to = true,
  992. is_ground_content = false,
  993. drop = "",
  994. drowning = 1,
  995. liquidtype = "flowing",
  996. liquid_alternative_flowing = "rocket:rocket_fuel_flowing",
  997. liquid_alternative_source = "rocket:rocket_fuel_source",
  998. liquid_viscosity = 1,
  999. liquid_renewable = false,
  1000. post_effect_color = {a = 103, r = 254, g = 0, b = 30},
  1001. groups = {oil = 3, liquid = 1, flammable = 1, not_in_creative_inventory = 1},
  1002. sounds = default.node_sound_water_defaults(),
  1003. })
  1004. bucket.register_liquid(
  1005. "rocket:rocket_fuel_source",
  1006. "rocket:rocket_fuel_flowing",
  1007. "rocket:bucket_rocket_fuel",
  1008. "rocket_bucket_rocket_fuel.png",
  1009. "Rocket Fuel Bucket"
  1010. )
  1011. --Oil refinement recipe
  1012. minetest.register_craft({
  1013. type = "cooking",
  1014. output = "rocket:bucket_rocket_fuel",
  1015. recipe = "rocket:bucket_oil",
  1016. --cooktime = 5,
  1017. })
  1018. --Rocket fuel as a fuel
  1019. minetest.register_craft({
  1020. type = "fuel",
  1021. recipe = "rocket:bucket_rocket_fuel",
  1022. burntime = 80,
  1023. replacements = {{"rocket:bucket_rocket_fuel", "bucket:bucket_empty"}},
  1024. })