scuba.lua 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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. local hp_max = pova.get_active_modifier(player, "properties").hp_max
  35. if w >= 45 then
  36. damage = hp_max * 0.15
  37. elseif w >= 30 then
  38. damage = hp_max * 0.10
  39. elseif w >= 15 then
  40. damage = hp_max * 0.05
  41. end
  42. end
  43. if damage > 0 then
  44. if player:get_hp() > 0 then
  45. utility.damage_player(player, "pressure", damage)
  46. if player:get_hp() <= 0 then
  47. minetest.chat_send_all("# Server: <" .. rename.gpn(player:get_player_name()) .. "> was wrecked by water pressure.")
  48. end
  49. end
  50. end
  51. -- Return water column count.
  52. return w
  53. end
  54. local scuba_timer = 0
  55. local scuba_step = 1
  56. ambiance.globalstep_scuba = function(dtime)
  57. scuba_timer = scuba_timer + dtime
  58. if scuba_timer < scuba_step then return end
  59. scuba_timer = 0
  60. local players = minetest.get_connected_players()
  61. for k, v in ipairs(players) do
  62. local pos = v:get_pos()
  63. local name = v:get_player_name()
  64. local entry = ambiance.players[name]
  65. if entry ~= nil and not gdac.player_is_admin(name) then
  66. local under = ambiance.check_underwater(pos)
  67. if under == 2 then
  68. entry.underwater = true
  69. if entry.scuba == nil then
  70. entry.scuba = minetest.sound_play("scuba", {to_player=name, gain=1.0})
  71. minetest.after(8, done_scuba, name)
  72. end
  73. ambiance.particles_underwater(pos)
  74. ambiance.particles_underwater({x=pos.x, y=pos.y+1, z=pos.z})
  75. -- Water-shaft makers will H8TE this!
  76. ambiance.check_water_pressure(vector_round(pos), v)
  77. sprint.add_stamina(v, -3)
  78. else
  79. entry.underwater = nil
  80. if entry.scuba ~= nil then
  81. minetest.sound_stop(entry.scuba)
  82. ambiance.sound_play("drowning_gasp", pos, 1.0, 30)
  83. entry.scuba = nil
  84. end
  85. end
  86. if under == 1 then
  87. if entry.psplash == nil then entry.psplash = pos end
  88. if vector_distance(entry.psplash, pos) > 0.5 and entry.hsplash == nil then
  89. ambiance.sound_play("splashing", pos, 1.0, 30)
  90. entry.hsplash = true
  91. entry.psplash = pos
  92. minetest.after(3, done_splash, name)
  93. end
  94. ambiance.particles_underwater(pos)
  95. ambiance.particles_swimming({x=pos.x, y=pos.y+1, z=pos.z})
  96. sprint.add_stamina(v, -1)
  97. end
  98. end
  99. end
  100. end