|
|
@@ -1,51 +1,99 @@ |
|
|
-- Parameters |
|
|
|
|
|
local radius = 8 -- Water node search radius around player |
|
|
-- Node search radius around player |
|
|
local radius = 8 |
|
|
|
|
|
local allsounds = { |
|
|
["env_sounds_water"] = { |
|
|
trigger = {"default:water_flowing", "default:river_water_flowing"}, |
|
|
base_volume = 0.04, |
|
|
max_volume = 0.4, |
|
|
per_node = 0.004, |
|
|
}, |
|
|
["env_sounds_lava"] = { |
|
|
trigger = {"default:lava_source", "default:lava_flowing"}, |
|
|
base_volume = 0, |
|
|
max_volume = 0.6, |
|
|
per_node = { |
|
|
["default:lava_source"] = 0.008, |
|
|
["default:lava_flowing"] = 0.002, |
|
|
}, |
|
|
}, |
|
|
} |
|
|
|
|
|
if minetest.settings:get_bool("river_source_sounds") then |
|
|
table.insert(allsounds["env_sounds_water"].trigger, |
|
|
"default:river_water_source") |
|
|
end |
|
|
|
|
|
|
|
|
-- End of parameters |
|
|
-- Cache the union of all trigger nodes |
|
|
|
|
|
local cache_triggers = {} |
|
|
|
|
|
local river_source_sounds = minetest.settings:get_bool("river_source_sounds") |
|
|
for sound, def in pairs(allsounds) do |
|
|
for _, name in ipairs(def.trigger) do |
|
|
table.insert(cache_triggers, name) |
|
|
end |
|
|
end |
|
|
|
|
|
|
|
|
-- Update sound for player |
|
|
|
|
|
local function update_sound(player) |
|
|
local player_name = player:get_player_name() |
|
|
local ppos = player:get_pos() |
|
|
ppos = vector.add(ppos, player:get_properties().eye_height) |
|
|
local areamin = vector.subtract(ppos, radius) |
|
|
local areamax = vector.add(ppos, radius) |
|
|
local water_nodes = {"default:water_flowing", "default:river_water_flowing"} |
|
|
if river_source_sounds then |
|
|
table.insert(water_nodes, "default:river_water_source") |
|
|
end |
|
|
local wpos, _ = minetest.find_nodes_in_area(areamin, areamax, water_nodes) |
|
|
local waters = #wpos |
|
|
if waters == 0 then |
|
|
|
|
|
local pos = minetest.find_nodes_in_area(areamin, areamax, cache_triggers, true) |
|
|
if next(pos) == nil then -- If table empty |
|
|
return |
|
|
end |
|
|
|
|
|
-- Find average position of water positions |
|
|
local wposav = vector.new() |
|
|
for _, pos in ipairs(wpos) do |
|
|
wposav.x = wposav.x + pos.x |
|
|
wposav.y = wposav.y + pos.y |
|
|
wposav.z = wposav.z + pos.z |
|
|
for sound, def in pairs(allsounds) do |
|
|
-- Find average position |
|
|
local posav = {0, 0, 0} |
|
|
local count = 0 |
|
|
for _, name in ipairs(def.trigger) do |
|
|
if pos[name] then |
|
|
for _, p in ipairs(pos[name]) do |
|
|
posav[1] = posav[1] + p.x |
|
|
posav[2] = posav[2] + p.y |
|
|
posav[3] = posav[3] + p.z |
|
|
end |
|
|
count = count + #pos[name] |
|
|
end |
|
|
end |
|
|
|
|
|
if count > 0 then |
|
|
posav = vector.new(posav[1] / count, posav[2] / count, |
|
|
posav[3] / count) |
|
|
|
|
|
-- Calculate gain |
|
|
local gain = def.base_volume |
|
|
if type(def.per_node) == 'table' then |
|
|
for name, multiplier in pairs(def.per_node) do |
|
|
if pos[name] then |
|
|
gain = gain + #pos[name] * multiplier |
|
|
end |
|
|
end |
|
|
else |
|
|
gain = gain + count * def.per_node |
|
|
end |
|
|
gain = math.min(gain, def.max_volume) |
|
|
|
|
|
minetest.sound_play(sound, { |
|
|
pos = posav, |
|
|
to_player = player_name, |
|
|
gain = gain, |
|
|
}, true) |
|
|
end |
|
|
end |
|
|
wposav = vector.divide(wposav, waters) |
|
|
|
|
|
minetest.sound_play( |
|
|
"env_sounds_water", |
|
|
{ |
|
|
pos = wposav, |
|
|
to_player = player_name, |
|
|
gain = math.min(0.04 + waters * 0.004, 0.4), |
|
|
} |
|
|
) |
|
|
end |
|
|
|
|
|
|
|
|
-- Update sound 'on joinplayer' |
|
|
-- Update sound when player joins |
|
|
|
|
|
minetest.register_on_joinplayer(function(player) |
|
|
update_sound(player) |
|
|