treesounds.lua 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. ambiance.tree_sounds = {
  2. {name="craw", gain=1.0, miny=-20, maxy=500, time="day" , indoors=false, mintime=120, maxtime=360, },
  3. {name="hornedowl", gain=1.0, miny=-20, maxy=500, time="night", indoors=false, mintime=120, maxtime=360, },
  4. -- More animal sounds. These should play with less frequency.
  5. {name="cricket", gain=1.0, miny=-20, maxy=500, time="night", indoors=false, },
  6. {name="jungle_night_1", gain=1.0, miny=-20, maxy=500, time="night", indoors=false, },
  7. {name="cardinal", gain=1.0, miny=-20, maxy=500, time="liminal", indoors=false, mintime=20, maxtime=60, },
  8. {name="crestedlark", gain=1.0, miny=-20, maxy=500, time="liminal", indoors=false, mintime=20, maxtime=60, },
  9. {name="deer", gain=1.0, miny=-20, maxy=500, time="night", indoors=false, mintime=20, maxtime=120, },
  10. {name="frog", gain=0.7, miny=-20, maxy=500, time="liminal", indoors=false, },
  11. {name="robin", gain=1.0, miny=-20, maxy=500, time="liminal", indoors=false, },
  12. {name="bluejay", gain=1.0, miny=-20, maxy=500, time="liminal", indoors=false, },
  13. {name="gull", gain=1.0, miny=-20, maxy=500, time="liminal", indoors=false, },
  14. {name="peacock", gain=1.0, miny=-20, maxy=500, time="liminal", indoors=false, },
  15. {name="canadianloon1", gain=1.0, miny=-20, maxy=500, time="night", indoors=false, mintime=120, maxtime=360, },
  16. }
  17. -- Initialize extra table parameters.
  18. for k, v in ipairs(ambiance.tree_sounds) do
  19. -- Mintime & maxtime are the min and max seconds a sound can play again after it has played.
  20. -- The timer is reset to a new random value between min and max every time the sound plays.
  21. v.mintime = v.mintime or 30
  22. v.maxtime = v.maxtime or 120
  23. if v.mintime < 0 then v.mintime = 0 end
  24. if v.maxtime < v.mintime then v.maxtime = v.mintime end
  25. -- If minimum or maximum gain are not specified, calculate min and max gain.
  26. v.mingain = v.mingain or (v.gain - 0.5)
  27. v.maxgain = v.maxgain or (v.gain + 0.1)
  28. if v.mingain < 0 then v.mingain = 0 end
  29. if v.maxgain < v.mingain then v.maxgain = v.mingain end
  30. -- Initialize timer to a random value between min and max time.
  31. -- This ensures all sounds start with random times on first run.
  32. v.timer = math.random(v.mintime, v.maxtime)
  33. v.range = v.range or 30
  34. end
  35. if not ambiance.tree_sounds_registered then
  36. ambiance.register_sound_beacon(":soundbeacon:trees", {
  37. -- Minimum and maximum times between environment checks.
  38. check_time_min = 60,
  39. check_time_max = 60*60,
  40. -- Minimum and maximum times between sounds playing.
  41. play_time_min = 5,
  42. play_time_max = 30,
  43. -- Shall check the beacon's nearby environment, and return 'true' if beacon
  44. -- can remain, 'false' or 'nil' if it should be removed. Data can be stored in
  45. -- `data`. `pos` is always a rounded position.
  46. on_check_environment = function(data, pos)
  47. local p1 = vector.add(pos, {x=-3, y=-3, z=-3})
  48. local p2 = vector.add(pos, {x=3, y=3, z=3})
  49. local nodes = {"group:leaves", "group:tree"}
  50. local positions = minetest.find_nodes_in_area(p1, p2, nodes)
  51. if #positions > 10 then
  52. return true
  53. end
  54. --minetest.chat_send_all("removed!")
  55. end,
  56. -- Shall play sound to nearby players (or check whether sound can be played at
  57. -- this time). Data can be stored in `data`. `pos` is
  58. -- always a rounded position. `dtime` is seconds since last call to func.
  59. on_play_sound = function(data, pos, dtime)
  60. if not data.sounds then
  61. data.sounds = table.copy(ambiance.tree_sounds)
  62. end
  63. -- For all sounds, check if anyone can hear them. If yes, play sound to players that can hear.
  64. local allsounds = data.sounds or {}
  65. --minetest.chat_send_all("num: " .. #allsounds)
  66. -- Get current time of day.
  67. local curtime = minetest.get_timeofday()
  68. local rand = math.random
  69. for k, v in ipairs(allsounds) do
  70. v.timer = v.timer - dtime
  71. if v.timer <= 0 then
  72. -- Timer has expired, fire sound (if possible).
  73. -- Also reset the timer so the sound can fire again.
  74. v.timer = rand(v.mintime, v.maxtime)
  75. -- Can this sound play at the current time of day?
  76. if ambiance.check_time(v.time, curtime) then
  77. -- Scan through all players. The following checks must be done per-player.
  78. local players = minetest.get_connected_players()
  79. for _, pref in ipairs(players) do
  80. local pname = pref:get_player_name()
  81. local ppos = utility.get_foot_pos(pref:get_pos())
  82. --minetest.chat_send_all("found player")
  83. -- Is player in this sounds's Y layer?
  84. if ppos.y >= v.miny and ppos.y <= v.maxy then
  85. local pdist = vector.distance(pos, ppos)
  86. if pdist < v.range then
  87. -- Don't play sound if player is underwater (muted sounds).
  88. -- Note: player's underwater status is modified by the scuba code.
  89. local underwater = ambiance.players[pname].underwater
  90. if underwater == nil then
  91. -- Only play sound if sound can be played indoors or out-of-doors.
  92. -- If sound doesn't care whether indoors or out-of-doors, then play it.
  93. local indoors
  94. if v.indoors ~= nil then
  95. -- Randomize position a bit in case player is just standing under an overhang.
  96. ppos.x = rand(ppos.x - 1, ppos.x + 1)
  97. ppos.y = rand(ppos.y - 1, ppos.y + 1)
  98. ppos.z = rand(ppos.z - 1, ppos.z + 1)
  99. indoors = ambiance.check_indoors(pname, ppos)
  100. end
  101. if v.indoors == indoors then
  102. -- Play sound to current player!
  103. -- If multiple players can hear, the sound will be played at the same time to all of them.
  104. local gain = rand(v.mingain*100.0, v.maxgain*100.0)/100.0
  105. -- Clamp gain!
  106. if gain < 0.0 then gain = 0.0 end
  107. if gain > 2.0 then gain = 2.0 end
  108. local md = ambiance.compute_gain(pdist, v.range)
  109. minetest.sound_play(v.name, {to_player=pname, gain=gain*md})
  110. end
  111. end
  112. end
  113. end
  114. end
  115. end
  116. end
  117. end
  118. end,
  119. })
  120. ambiance.tree_sounds_registered = true
  121. end