diff --git a/README.txt b/README.txt index 0bf714d..e3cd2b7 100644 --- a/README.txt +++ b/README.txt @@ -1,4 +1,4 @@ -snowdrift 0.6.2 by paramat +snowdrift 0.6.3 by paramat For Minetest 0.4.16 and later. Compatible with Minetest 5.0.0. Depends: default diff --git a/init.lua b/init.lua index 97a4838..ee482bf 100644 --- a/init.lua +++ b/init.lua @@ -1,25 +1,30 @@ -- Parameters -local YLIMIT = 1 -- Set to world's water level +local YWATER = 1 -- Normally set this to world's water level -- Particles are timed to disappear at this y - -- Particles do not spawn when player's head is below this y -local PRECTIM = 5 -- Precipitation noise spread + -- Particles are not spawned for players below this y + -- Rain sound is not played for players below this y +local YMIN = -48 -- Normally set this to deepest ocean +local YMAX = 120 -- Normally set this to cloud level + -- Weather does not occur for players outside this y range +local PRECTIM = 5 -- Precipitation noise 'spread' -- Time scale for precipitation variation, in minutes local PRECTHR = 0.2 -- Precipitation noise threshold, -1 to 1: -- -1 = precipitation all the time -- 0 = precipitation half the time -- 1 = no precipitation -local FLAKLPOS = 32 -- Snowflake light-tested positions per cycle +local FLAKLPOS = 32 -- Snowflake light-tested positions per 0.5s cycle -- Maximum number of snowflakes spawned per 0.5s -local DROPLPOS = 64 -- Raindrop light-tested positions per cycle - -- Maximum number of raindrops spawned per 0.5s -local DROPPPOS = 2 -- Raindrops per light-tested pos +local DROPLPOS = 64 -- Raindrop light-tested positions per 0.5s cycle +local DROPPPOS = 2 -- Number of raindrops spawned per light-tested position local RAINGAIN = 0.2 -- Rain sound volume local NISVAL = 39 -- Overcast sky RGB value at night (brightness) local DASVAL = 159 -- Overcast sky RGB value in daytime (brightness) local FLAKRAD = 16 -- Radius in which flakes are created local DROPRAD = 16 -- Radius in which drops are created +-- Precipitation noise + local np_prec = { offset = 0, scale = 1, @@ -58,7 +63,7 @@ local np_humid = { -- End parameters --- Stuff +-- Some stuff local difsval = DASVAL - NISVAL local grad = 14 / 95 @@ -72,9 +77,14 @@ local nobj_humid = nil local nobj_prec = nil --- Globalstep function +-- Player tables local handles = {} +local skybox = {} -- true/false. To not turn off skyboxes of other mods + + +-- Globalstep function + local timer = 0 minetest.register_globalstep(function(dtime) @@ -87,25 +97,24 @@ minetest.register_globalstep(function(dtime) for _, player in ipairs(minetest.get_connected_players()) do local player_name = player:get_player_name() - -- Predict player position as slightly behind the cycle interval. - -- Assume scheduling gets behind slighly (cycle time * 1.5). - local ppos = vector.add(player:getpos(), - vector.multiply(player:get_player_velocity(), 0.75)) - -- Point just above player head, for precipitation when swimming + local ppos = player:getpos() + -- Point just above player head, to ensure precipitation when swimming local pposy = math.floor(ppos.y) + 2 - if pposy >= YLIMIT - 2 then + if pposy >= YMIN and pposy <= YMAX then + --TODO Predict player position? Only horizontally + --local ppos = vector.add(player:getpos(), + --vector.multiply(player:get_player_velocity(), ?)) local pposx = math.floor(ppos.x) local pposz = math.floor(ppos.z) local ppos = {x = pposx, y = pposy, z = pposz} + -- Heat and humidity calculations local nobj_temp = nobj_temp or minetest.get_perlin(np_temp) local nobj_humid = nobj_humid or minetest.get_perlin(np_humid) local nobj_prec = nobj_prec or minetest.get_perlin(np_prec) - local nval_temp = nobj_temp:get2d({x = pposx, y = pposz}) local nval_humid = nobj_humid:get2d({x = pposx, y = pposz}) local nval_prec = nobj_prec:get2d({x = os.clock() / 60, y = 0}) - -- Biome system: Frozen biomes below heat 35, -- deserts below line 14 * t - 95 * h = -1496 -- h = (14 * t + 1496) / 95 @@ -118,47 +127,48 @@ minetest.register_globalstep(function(dtime) local precip = nval_prec > PRECTHR and nval_humid - grad * nval_temp > yint - -- Occasionally reset player sky - if math.random() < 0.1 then - if precip then - -- Set overcast sky - local sval - local time = minetest.get_timeofday() - if time >= 0.5 then - time = 1 - time - end - -- Sky brightness transitions: - -- First transition (24000 -) 4500, (1 -) 0.1875 - -- Last transition (24000 -) 5750, (1 -) 0.2396 - if time <= 0.1875 then - sval = NISVAL - elseif time >= 0.2396 then - sval = DASVAL - else - sval = math.floor(NISVAL + - ((time - 0.1875) / 0.0521) * difsval) - end - -- Set sky to overcast bluish-grey - player:set_sky({r = sval, g = sval, b = sval + 16, a = 255}, - "plain", {}, false) - else - -- Reset sky to normal - player:set_sky({}, "regular", {}, true) + -- Set sky + if precip and not skybox[player_name] then + -- Set overcast sky only if normal + local sval + local time = minetest.get_timeofday() + if time >= 0.5 then + time = 1 - time end + -- Sky brightness transitions: + -- First transition (24000 -) 4500, (1 -) 0.1875 + -- Last transition (24000 -) 5750, (1 -) 0.2396 + if time <= 0.1875 then + sval = NISVAL + elseif time >= 0.2396 then + sval = DASVAL + else + sval = math.floor(NISVAL + + ((time - 0.1875) / 0.0521) * difsval) + end + player:set_sky({r = sval, g = sval, b = sval + 16, a = 255}, + "plain", {}, false) + skybox[player_name] = true + elseif not precip and skybox[player_name] then + -- Set normal sky only if skybox + player:set_sky({}, "regular", {}, true) + skybox[player_name] = nil end - if not precip or freeze then + -- Stop looping sound. + -- Stop sound if head below water level. + if not precip or freeze or pposy < YWATER then if handles[player_name] then - -- Stop sound if playing minetest.sound_stop(handles[player_name]) handles[player_name] = nil end end - if precip then - -- Precipitation + -- Particles and sounds. + -- Only if head above water level. + if precip and pposy >= YWATER then if freeze then - -- Snowfall + -- Snowfall particles for lpos = 1, FLAKLPOS do local lposx = pposx - FLAKRAD + math.random(0, FLAKRAD * 2) @@ -173,7 +183,7 @@ minetest.register_globalstep(function(dtime) -- in separated layers. -- Random range = speed * cycle time local spawny = pposy + 10 + math.random(0, 10) / 10 - local extime = math.min((spawny - YLIMIT) / 2, 10) + local extime = math.min((spawny - YWATER) / 2, 10) minetest.add_particle({ pos = {x = lposx, y = spawny, z = lposz}, @@ -191,7 +201,7 @@ minetest.register_globalstep(function(dtime) end end else - -- Rainfall + -- Rainfall particles for lpos = 1, DROPLPOS do local lposx = pposx - DROPRAD + math.random(0, DROPRAD * 2) @@ -202,7 +212,7 @@ minetest.register_globalstep(function(dtime) 0.5) == 15 then for drop = 1, DROPPPOS do local spawny = pposy + 10 + math.random(0, 60) / 10 - local extime = math.min((spawny - YLIMIT) / 12, 2) + local extime = math.min((spawny - YWATER) / 12, 2) local spawnx = lposx - 0.4 + math.random(0, 8) / 10 local spawnz = lposz - 0.4 + math.random(0, 8) / 10 @@ -221,9 +231,8 @@ minetest.register_globalstep(function(dtime) end end end - + -- Start looping sound if not handles[player_name] then - -- Start sound if not playing local handle = minetest.sound_play( "snowdrift_rain", { @@ -238,21 +247,34 @@ minetest.register_globalstep(function(dtime) end end end - elseif handles[player_name] then - -- Stop sound when player goes under y limit - minetest.sound_stop(handles[player_name]) - handles[player_name] = nil + else + -- Player outside y limits. + -- Stop sound if playing. + if handles[player_name] then + minetest.sound_stop(handles[player_name]) + handles[player_name] = nil + end + -- Set normal sky if skybox + if skybox[player_name] then + player:set_sky({}, "regular", {}, true) + skybox[player_name] = nil + end end end end) --- Stop sound and remove player handle on leaveplayer +-- On leaveplayer function minetest.register_on_leaveplayer(function(player) local player_name = player:get_player_name() + -- Stop sound if playing and remove handle if handles[player_name] then minetest.sound_stop(handles[player_name]) handles[player_name] = nil end + -- Remove skybox bool if necessary + if skybox[player_name] then + skybox[player_name] = nil + end end)