diving_equipment.lua 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. if not minetest.global_exists("diving_equipment") then diving_equipment = {} end
  2. diving_equipment.modpath = minetest.get_modpath("hb4")
  3. diving_equipment.airtime = 60
  4. diving_equipment.steptime = 5
  5. diving_equipment.players = diving_equipment.players or {}
  6. -- Localize for performance.
  7. local math_floor = math.floor
  8. -- Must return true if player is wearing the diving helmet.
  9. function diving_equipment.have_equipment(pref)
  10. local inv = pref:get_inventory()
  11. if not inv then return end
  12. local have_equipment = false
  13. -- Make sure player isn't trying to cheat by wearing multiple helmets.
  14. for i=1, 6 do
  15. local stackname = inv:get_stack("armor", i):get_name()
  16. if string.find(stackname, "^3d_armor:helmet_") then
  17. if stackname == "3d_armor:helmet_scuba" then
  18. have_equipment = true
  19. else
  20. return false
  21. end
  22. end
  23. end
  24. return have_equipment
  25. end
  26. function diving_equipment.replenish_air(pname, time)
  27. local player = minetest.get_player_by_name(pname)
  28. if not player then
  29. -- We cannot give player their bottle back.
  30. diving_equipment.players[pname] = nil
  31. return
  32. end -- Player left game.
  33. if time < 0 then
  34. -- Add empty iron bottle back to player's inventory.
  35. local leftover = player:get_inventory():add_item("main", ItemStack("vessels:steel_bottle"))
  36. minetest.add_item(player:get_pos(), leftover)
  37. diving_equipment.players[pname] = nil
  38. ambiance.sound_play("default_dug_metal", player:get_pos(), 1.0, 20)
  39. minetest.chat_send_player(pname, "# Server: Air canister is empty!")
  40. return
  41. end -- Air ran out.
  42. if not diving_equipment.have_equipment(player) then
  43. -- Add empty iron bottle back to player's inventory.
  44. local leftover = player:get_inventory():add_item("main", ItemStack("vessels:steel_bottle"))
  45. minetest.add_item(player:get_pos(), leftover)
  46. diving_equipment.players[pname] = nil
  47. ambiance.sound_play("default_dug_metal", player:get_pos(), 1.0, 20)
  48. minetest.chat_send_player(pname, "# Server: Diving helmet is not worn!")
  49. return
  50. end -- Lost diving helmet.
  51. -- Play breath sound on initial breath from new canister.
  52. if time == diving_equipment.airtime then
  53. ambiance.sound_play("drowning_gasp", player:get_pos(), 1.0, 20)
  54. end
  55. player:set_breath(11)
  56. minetest.after(diving_equipment.steptime, diving_equipment.replenish_air,
  57. pname, (time - diving_equipment.steptime))
  58. end
  59. function diving_equipment.on_use(itemstack, user, pt)
  60. if not user or not user:is_player() then return end
  61. local pname = user:get_player_name()
  62. if not diving_equipment.have_equipment(user) then
  63. minetest.chat_send_player(pname, "# Server: You must be wearing a diving helmet!")
  64. return
  65. end -- No diving helmet is worn.
  66. if diving_equipment.players[pname] then
  67. minetest.chat_send_player(pname, "# Server: An air canister is already attached!")
  68. return
  69. end -- Canister already installed.
  70. diving_equipment.players[pname] = true
  71. minetest.after(diving_equipment.steptime, diving_equipment.replenish_air,
  72. pname, diving_equipment.airtime)
  73. minetest.chat_send_player(pname, "# Server: Air canister attached; you have " .. math_floor(diving_equipment.airtime) .. " seconds of air.")
  74. ambiance.sound_play("default_place_node_metal", user:get_pos(), 1.0, 20)
  75. -- An empty bottle will be added back when used up.
  76. itemstack:take_item()
  77. return itemstack
  78. end
  79. function diving_equipment.on_place(itemstack, placer, pt)
  80. -- Pass through interactions to nodes that define them (like chests).
  81. -- This also fixes a bug where player can get unlimited steel bottles (and
  82. -- thus steel ingots) by putting compressed air into item frames.
  83. if pt.type == "node" then
  84. local under = minetest.get_node(pt.under)
  85. local nn = under.name
  86. local def = minetest.reg_ns_nodes[nn] or minetest.registered_nodes[nn]
  87. if def and def.on_rightclick then
  88. return def.on_rightclick(pt.under, under, placer, itemstack, pt)
  89. end
  90. end
  91. local fakestack = ItemStack("vessels:steel_bottle")
  92. local retstack, success, position = minetest.item_place(fakestack, placer, pt)
  93. if success and position then
  94. local meta = minetest.get_meta(position)
  95. meta:set_string("infotext", "Compressed Air Canister")
  96. meta:set_string("nodetype_on_dig", "scuba:air")
  97. meta:mark_as_private("nodetype_on_dig")
  98. coresounds.play_sound_node_place(pt.above, "vessels:steel_bottle")
  99. itemstack:take_item()
  100. end
  101. return itemstack
  102. end
  103. if not diving_equipment.registered then
  104. minetest.register_craftitem(":scuba:air", {
  105. description = "Compressed Air Canister\n\nUse with a diving helmet.\nLets you stay underwater.",
  106. inventory_image = "musttest_compressed_air.png",
  107. on_use = function(...)
  108. return diving_equipment.on_use(...)
  109. end,
  110. on_place = function(...)
  111. return diving_equipment.on_place(...)
  112. end,
  113. })
  114. -- The diving mask.
  115. minetest.register_tool(":3d_armor:helmet_scuba", {
  116. description = "Ocean Diving Helmet\n\nUse with compressed air.\nLets you stay underwater.",
  117. inventory_image = "3d_armor_inv_helmet_scuba.png",
  118. groups = {armor_head=1, armor_heal=0, armor_use=2000},
  119. wear = 0,
  120. })
  121. minetest.register_craft({
  122. output = "3d_armor:helmet_scuba",
  123. recipe = {
  124. {"default:steel_ingot", "plastic:plastic_sheeting", "default:steel_ingot"},
  125. {"default:steel_ingot", "default:glass", "default:steel_ingot"},
  126. {"farming:cloth", "vessels:steel_bottle", "farming:cloth"},
  127. },
  128. })
  129. minetest.register_craft({
  130. type = "compressing",
  131. output = "scuba:air",
  132. recipe = 'vessels:steel_bottle',
  133. time = 6,
  134. })
  135. diving_equipment.registered = true
  136. end