scuba.lua 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. -- This file is reloadable.
  2. -- Localize for performance.
  3. local vector_distance = vector.distance
  4. local vector_round = vector.round
  5. local done_scuba = function(name)
  6. if ambiance.players[name] ~= nil then
  7. ambiance.players[name].scuba = nil
  8. end
  9. end
  10. local done_splash = function(name)
  11. if ambiance.players[name] ~= nil then
  12. ambiance.players[name].hsplash = nil
  13. end
  14. end
  15. function ambiance.check_water_pressure(pos, player)
  16. local y = pos.y
  17. local c = 45
  18. local w = 0
  19. local n = minetest.get_node(pos)
  20. local d = minetest.registered_nodes[n.name] or {}
  21. local g = d.groups or {}
  22. -- Count water nodes above player, starting with position.
  23. while c > 0 and g.water and g.water > 0 do
  24. w = w + 1
  25. c = c - 1
  26. pos.y = pos.y + 1
  27. n = minetest.get_node(pos)
  28. d = minetest.registered_nodes[n.name] or {}
  29. g = d.groups or {}
  30. end
  31. pos.y = y
  32. local damage = 0
  33. if y < -50 then
  34. if w >= 45 then
  35. damage = 3
  36. elseif w >= 30 then
  37. damage = 2
  38. elseif w >= 15 then
  39. damage = 1
  40. end
  41. end
  42. if damage > 0 then
  43. if player:get_hp() > 0 then
  44. player:set_hp(player:get_hp() - damage)
  45. if player:get_hp() <= 0 then
  46. minetest.chat_send_all("# Server: <" .. rename.gpn(player:get_player_name()) .. "> was wrecked by water pressure.")
  47. end
  48. end
  49. end
  50. -- Return water column count.
  51. return w
  52. end
  53. local scuba_timer = 0
  54. local scuba_step = 1
  55. ambiance.globalstep_scuba = function(dtime)
  56. scuba_timer = scuba_timer + dtime
  57. if scuba_timer < scuba_step then return end
  58. scuba_timer = 0
  59. local players = minetest.get_connected_players()
  60. for k, v in ipairs(players) do
  61. local pos = v:get_pos()
  62. local name = v:get_player_name()
  63. local entry = ambiance.players[name]
  64. if entry ~= nil and not gdac.player_is_admin(name) then
  65. local under = ambiance.check_underwater(pos)
  66. if under == 2 then
  67. entry.underwater = true
  68. if entry.scuba == nil then
  69. entry.scuba = minetest.sound_play("scuba", {to_player=name, gain=1.0})
  70. minetest.after(8, done_scuba, name)
  71. end
  72. ambiance.particles_underwater(pos)
  73. ambiance.particles_underwater({x=pos.x, y=pos.y+1, z=pos.z})
  74. -- Water-shaft makers will H8TE this!
  75. ambiance.check_water_pressure(vector_round(pos), v)
  76. sprint.add_stamina(v, -3)
  77. else
  78. entry.underwater = nil
  79. if entry.scuba ~= nil then
  80. minetest.sound_stop(entry.scuba)
  81. ambiance.sound_play("drowning_gasp", pos, 1.0, 30)
  82. entry.scuba = nil
  83. end
  84. end
  85. if under == 1 then
  86. if entry.psplash == nil then entry.psplash = pos end
  87. if vector_distance(entry.psplash, pos) > 0.5 and entry.hsplash == nil then
  88. ambiance.sound_play("splashing", pos, 1.0, 30)
  89. entry.hsplash = true
  90. entry.psplash = pos
  91. minetest.after(3, done_splash, name)
  92. end
  93. ambiance.particles_underwater(pos)
  94. ambiance.particles_swimming({x=pos.x, y=pos.y+1, z=pos.z})
  95. sprint.add_stamina(v, -1)
  96. end
  97. end
  98. end
  99. end