|
| 1 | + |
| 2 | +--= Ambience lite by TenPlus1 (16th April 2015) |
| 3 | + |
| 4 | +local max_frequency_all = 1000 -- larger number means more frequent sounds (100-2000) |
| 5 | +local SOUNDVOLUME = 1 |
| 6 | +local ambiences |
| 7 | +local played_on_start = false |
| 8 | +local tempy = {} |
| 9 | + |
| 10 | +-- compatibility with soundset mod |
| 11 | +local get_volume |
| 12 | +if (minetest.get_modpath("soundset")) ~= nil then |
| 13 | + get_volume = soundset.get_gain |
| 14 | +else |
| 15 | + get_volume = function (player_name, sound_type) return SOUNDVOLUME end |
| 16 | + -- set volume command |
| 17 | + minetest.register_chatcommand("svol", { |
| 18 | + params = "<svol>", |
| 19 | + description = "set sound volume (0.1 to 1.0)", |
| 20 | + privs = {server=true}, |
| 21 | + func = function(name, param) |
| 22 | + if tonumber(param) then |
| 23 | + SOUNDVOLUME = tonumber(param) |
| 24 | + minetest.chat_send_player(name, "Sound volume set.") |
| 25 | + else |
| 26 | + minetest.chat_send_player(name, "Sound volume no set, bad param.") |
| 27 | + end |
| 28 | + end, |
| 29 | + }) |
| 30 | +end |
| 31 | + |
| 32 | + |
| 33 | +-- sound sets |
| 34 | +local night = { |
| 35 | + handler = {}, frequency = 40, |
| 36 | + {name="hornedowl", length=2}, |
| 37 | + {name="wolves", length=4}, |
| 38 | + {name="cricket", length=6}, |
| 39 | + {name="deer", length=7}, |
| 40 | + {name="frog", length=1}, |
| 41 | +} |
| 42 | + |
| 43 | +local day = { |
| 44 | + handler = {}, frequency = 40, |
| 45 | + {name="cardinal", length=3}, |
| 46 | + {name="bluejay", length=6}, |
| 47 | + {name="craw", length=3}, |
| 48 | + {name="canadianloon2", length=14}, |
| 49 | + {name="robin", length=4}, |
| 50 | + {name="bird1", length=11}, |
| 51 | + {name="bird2", length=6}, |
| 52 | + {name="crestedlark", length=6}, |
| 53 | + {name="peacock", length=2} |
| 54 | +} |
| 55 | + |
| 56 | +local high_up = { |
| 57 | + handler = {}, frequency = 40, |
| 58 | + {name="craw", length=3}, |
| 59 | + {name="wind", length=9.5}, |
| 60 | +} |
| 61 | + |
| 62 | +local cave = { |
| 63 | + handler = {}, frequency = 60, |
| 64 | + {name="drippingwater1", length=1.5}, |
| 65 | + {name="drippingwater2", length=1.5} |
| 66 | +} |
| 67 | + |
| 68 | +local beach = { |
| 69 | + handler = {}, frequency = 40, |
| 70 | + {name="seagull", length=4.5}, |
| 71 | + {name="beach", length=13}, |
| 72 | + {name="gull", length=1} |
| 73 | +} |
| 74 | + |
| 75 | +local desert = { |
| 76 | + handler = {}, frequency = 20, |
| 77 | + {name="coyote", length=2.5}, |
| 78 | + {name="desertwind", length=8} |
| 79 | +} |
| 80 | + |
| 81 | +local flowing_water = { |
| 82 | + handler = {}, frequency = 1000, |
| 83 | + {name="waterfall", length=6} |
| 84 | +} |
| 85 | + |
| 86 | +local underwater = { |
| 87 | + handler = {}, frequency = 1000, |
| 88 | + {name="scuba", length=8} |
| 89 | +} |
| 90 | + |
| 91 | +local splash = { |
| 92 | + handler = {}, frequency = 1000, |
| 93 | + {name="swim_splashing", length=3}, |
| 94 | +} |
| 95 | + |
| 96 | +local lava = { |
| 97 | + handler = {}, frequency = 1000, |
| 98 | + {name="lava", length=7} |
| 99 | +} |
| 100 | + |
| 101 | +local smallfire = { |
| 102 | + handler = {}, frequency = 1000, |
| 103 | + {name="fire_small", length=6} |
| 104 | +} |
| 105 | + |
| 106 | +local largefire = { |
| 107 | + handler = {}, frequency = 1000, |
| 108 | + {name="fire_large", length=8} |
| 109 | +} |
| 110 | + |
| 111 | +-- check where player is and which sounds are played |
| 112 | +local get_ambience = function(player) |
| 113 | + |
| 114 | + -- where am I? |
| 115 | + local pos = player:getpos() |
| 116 | + |
| 117 | + -- what is around me? |
| 118 | + pos.y = pos.y + 1.4 -- head level |
| 119 | + local nod_head = minetest.get_node(pos).name |
| 120 | + |
| 121 | + pos.y = pos.y - 1.2 -- feet level |
| 122 | + local nod_feet = minetest.get_node(pos).name |
| 123 | + |
| 124 | + pos.y = pos.y - 0.2 -- reset pos |
| 125 | + |
| 126 | + --= START Ambiance |
| 127 | + |
| 128 | + if nod_head == "default:water_source" |
| 129 | + or nod_head == "default:water_flowing" then |
| 130 | + return {underwater=underwater} |
| 131 | + end |
| 132 | + |
| 133 | + if nod_feet == "default:water_source" |
| 134 | + or nod_feet == "default:water_flowing" then |
| 135 | + return {splash=splash} |
| 136 | + end |
| 137 | + |
| 138 | + local num_fire, num_lava, num_water_source, num_water_flowing, num_desert = 0,0,0,0,0 |
| 139 | + |
| 140 | + -- get block of nodes we need to check |
| 141 | + tempy = minetest.find_nodes_in_area({x=pos.x-6,y=pos.y-2, z=pos.z-6}, |
| 142 | + {x=pos.x+6,y=pos.y+2, z=pos.z+6}, |
| 143 | + {"fire:basic_flame", "bakedclay:safe_fire", "default:lava_flowing", "default:lava_source", |
| 144 | + "default:water_flowing", "default:water_source", "default:desert_sand", "default:desert_stone",}) |
| 145 | + |
| 146 | + -- count separate instances in block |
| 147 | + for _, npos in ipairs(tempy) do |
| 148 | + local node = minetest.get_node(npos).name |
| 149 | + if node == "fire:basic_flame" or node == "bakedclay:safe_fire" then num_fire = num_fire + 1 end |
| 150 | + if node == "default:lava_flowing" or node == "default:lava_source" then num_lava = num_lava + 1 end |
| 151 | + if node == "default:water_flowing" then num_water_flowing = num_water_flowing + 1 end |
| 152 | + if node == "default:water_source" then num_water_source = num_water_source + 1 end |
| 153 | + if node == "default:desert_sand" or node == "default:desert_stone" then num_desert = num_desert + 1 end |
| 154 | + end ; --print (num_fire, num_lava, num_water_flowing, num_water_source, num_desert) |
| 155 | + |
| 156 | + -- is fire redo mod active? |
| 157 | + if fire and fire.mod and fire.mod == "redo" then |
| 158 | + if num_fire > 8 then |
| 159 | + return {largefire=largefire} |
| 160 | + elseif num_fire > 0 then |
| 161 | + return {smallfire=smallfire} |
| 162 | + end |
| 163 | + end |
| 164 | + |
| 165 | + if num_lava > 5 then |
| 166 | + return {lava=lava} |
| 167 | + end |
| 168 | + |
| 169 | + if num_water_flowing > 30 then |
| 170 | + return {flowing_water=flowing_water} |
| 171 | + end |
| 172 | + |
| 173 | + if pos.y < 7 and pos.y > 0 and num_water_source > 100 then |
| 174 | + return {beach=beach} |
| 175 | + end |
| 176 | + |
| 177 | + if num_desert > 150 then |
| 178 | + return {desert=desert} |
| 179 | + end |
| 180 | + |
| 181 | + if pos.y > 60 then |
| 182 | + return {high_up=high_up} |
| 183 | + end |
| 184 | + |
| 185 | + if pos.y < -10 then |
| 186 | + return {cave=cave} |
| 187 | + end |
| 188 | + |
| 189 | + if minetest.get_timeofday() > 0.2 and minetest.get_timeofday() < 0.8 then |
| 190 | + return {day=day} |
| 191 | + else |
| 192 | + return {night=night} |
| 193 | + end |
| 194 | + |
| 195 | + -- END Ambiance |
| 196 | + |
| 197 | +end |
| 198 | + |
| 199 | +-- play sound, set handler then delete handler when sound finished |
| 200 | +local play_sound = function(player, list, number) |
| 201 | + |
| 202 | + local player_name = player:get_player_name() |
| 203 | + |
| 204 | + if list.handler[player_name] == nil then |
| 205 | + |
| 206 | + local gain = get_volume(player:get_player_name(), "ambience") |
| 207 | + local handler = minetest.sound_play(list[number].name, {to_player=player_name, gain=gain}) |
| 208 | + |
| 209 | + if handler then |
| 210 | + list.handler[player_name] = handler |
| 211 | + |
| 212 | + minetest.after(list[number].length, function(args) |
| 213 | + local list = args[1] |
| 214 | + local player_name = args[2] |
| 215 | + |
| 216 | + if list.handler[player_name] then |
| 217 | + minetest.sound_stop(list.handler[player_name]) |
| 218 | + list.handler[player_name] = nil |
| 219 | + end |
| 220 | + end, {list, player_name}) |
| 221 | + end |
| 222 | + end |
| 223 | +end |
| 224 | + |
| 225 | +-- stop sound in still_playing |
| 226 | +local stop_sound = function (list, player) |
| 227 | + |
| 228 | + local player_name = player:get_player_name() |
| 229 | + |
| 230 | + if list.handler[player_name] then |
| 231 | + if list.on_stop then |
| 232 | + minetest.sound_play(list.on_stop, {to_player=player:get_player_name(),gain=get_volume(player:get_player_name(), "ambience")}) |
| 233 | + end |
| 234 | + minetest.sound_stop(list.handler[player_name]) |
| 235 | + list.handler[player_name] = nil |
| 236 | + end |
| 237 | + |
| 238 | +end |
| 239 | + |
| 240 | +-- check sounds that are not in still_playing |
| 241 | +local still_playing = function(still_playing, player) |
| 242 | + if not still_playing.cave then stop_sound(cave, player) end |
| 243 | + if not still_playing.high_up then stop_sound(high_up, player) end |
| 244 | + if not still_playing.beach then stop_sound(beach, player) end |
| 245 | + if not still_playing.desert then stop_sound(desert, player) end |
| 246 | + if not still_playing.night then stop_sound(night, player) end |
| 247 | + if not still_playing.day then stop_sound(day, player) end |
| 248 | + if not still_playing.flowing_water then stop_sound(flowing_water, player) end |
| 249 | + if not still_playing.splash then stop_sound(splash, player) end |
| 250 | + if not still_playing.underwater then stop_sound(underwater, player) end |
| 251 | + if not still_playing.lava then stop_sound(lava, player) end |
| 252 | + if not still_playing.smallfire then stop_sound(smallfire, player) end |
| 253 | + if not still_playing.largefire then stop_sound(largefire, player) end |
| 254 | +end |
| 255 | + |
| 256 | +local function tick() |
| 257 | + for _,player in ipairs(minetest.get_connected_players()) do |
| 258 | +--local t1 = os.clock() |
| 259 | + ambiences = get_ambience(player) |
| 260 | +--print ("[AMBIENCE] "..math.ceil((os.clock() - t1) * 1000).." ms") |
| 261 | + |
| 262 | + still_playing(ambiences, player) |
| 263 | + if get_volume(player:get_player_name(), "ambience") > 0 then |
| 264 | + for _,ambience in pairs(ambiences) do |
| 265 | + if math.random(1, 1000) <= ambience.frequency then |
| 266 | + if ambience.on_start and played_on_start == false then |
| 267 | + played_on_start = true |
| 268 | + minetest.sound_play(ambience.on_start, |
| 269 | + {to_player=player:get_player_name(),gain=get_volume(player:get_player_name(), "ambience")}) |
| 270 | + end |
| 271 | + play_sound(player, ambience, math.random(1, #ambience)) |
| 272 | + end |
| 273 | + end |
| 274 | + end |
| 275 | + end |
| 276 | + minetest.after(1, tick) |
| 277 | +end |
| 278 | + |
| 279 | +minetest.after(10, tick) |
0 commit comments