From c1d0fe4142ce35df82c9b4178c45427a9e1e15b9 Mon Sep 17 00:00:00 2001 From: paramat Date: Thu, 31 Jan 2019 01:38:17 +0000 Subject: [PATCH] Add y limits for skybox effects, set to deep ocean and cloud level, independent of the set water level where particles and sounds stop. Add 'skybox' table to track player sky status to attempt to avoid turning off skyboxes set by other mods, therefore remove randomised and lazy setting of skybox, now happens within 0.5s. For now, remove predicted player position due to issues, to be re-added later acting horizontally only --- README.txt | 2 +- init.lua | 138 +++++++++++++++++++++++++++++++---------------------- 2 files changed, 81 insertions(+), 59 deletions(-) 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)