Weather mod: Tune cloud density variation
[oweals/minetest_game.git] / mods / weather / init.lua
1 -- Disable by mapgen or setting
2
3 local mg_name = minetest.get_mapgen_setting("mg_name")
4 if mg_name == "v6" or mg_name == "singlenode" or
5                 minetest.settings:get_bool("enable_weather") == false then
6         return
7 end
8
9
10 -- Parameters
11
12 local TSCALE = 600 -- Time scale of noise variation in seconds
13 local CYCLE = 8 -- Time period of cyclic clouds update in seconds
14
15 local np_density = {
16         offset = 0.5,
17         scale = 0.5,
18         spread = {x = TSCALE, y = TSCALE, z = TSCALE},
19         seed = 813,
20         octaves = 1,
21         persist = 0,
22         lacunarity = 2,
23 }
24
25 local np_thickness = {
26         offset = 0.5,
27         scale = 0.5,
28         spread = {x = TSCALE, y = TSCALE, z = TSCALE},
29         seed = 96,
30         octaves = 1,
31         persist = 0,
32         lacunarity = 2,
33 }
34
35 local np_speedx = {
36         offset = 0,
37         scale = 1,
38         spread = {x = TSCALE, y = TSCALE, z = TSCALE},
39         seed = 911923,
40         octaves = 1,
41         persist = 0,
42         lacunarity = 2,
43 }
44
45 local np_speedz = {
46         offset = 0,
47         scale = 1,
48         spread = {x = TSCALE, y = TSCALE, z = TSCALE},
49         seed = 5728,
50         octaves = 1,
51         persist = 0,
52         lacunarity = 2,
53 }
54
55 -- End parameters
56
57
58 -- Initialise noise objects to nil
59
60 local nobj_density = nil
61 local nobj_thickness = nil
62 local nobj_speedx = nil
63 local nobj_speedz = nil
64
65
66 -- Update clouds function
67
68 local function rangelim(value, lower, upper)
69         return math.min(math.max(value, lower), upper)
70 end
71
72 local os_time_0 = os.time()
73 local t_offset = math.random(0, 300000)
74
75 local function update_clouds()
76         -- Time in seconds.
77         -- Add random time offset to avoid identical behaviour each server session.
78         local time = os.difftime(os.time(), os_time_0) - t_offset
79
80         nobj_density = nobj_density or minetest.get_perlin(np_density)
81         nobj_thickness = nobj_thickness or minetest.get_perlin(np_thickness)
82         nobj_speedx = nobj_speedx or minetest.get_perlin(np_speedx)
83         nobj_speedz = nobj_speedz or minetest.get_perlin(np_speedz)
84
85         local n_density = nobj_density:get_2d({x = time, y = 0}) -- 0 to 1
86         local n_thickness = nobj_thickness:get_2d({x = time, y = 0}) -- 0 to 1
87         local n_speedx = nobj_speedx:get_2d({x = time, y = 0}) -- -1 to 1
88         local n_speedz = nobj_speedz:get_2d({x = time, y = 0}) -- -1 to 1
89
90         for _, player in ipairs(minetest.get_connected_players()) do
91                 local humid = minetest.get_humidity(player:get_pos())
92                 -- Default and classic density value is 0.4, make this happen
93                 -- at humidity midvalue 50 when n_density is at midvalue 0.5.
94                 -- density_max = 0.25 at humid = 0.
95                 -- density_max = 0.8 at humid = 50.
96                 -- density_max = 1.35 at humid = 100.
97                 local density_max = 0.8 + ((humid - 50) / 50) * 0.55
98                 player:set_clouds({
99                         -- Range limit density_max to always have occasional
100                         -- small scattered clouds at extreme low humidity.
101                         density = rangelim(density_max, 0.2, 1.0) * n_density,
102                         thickness = math.max(math.floor(
103                                 rangelim(32 * humid / 100, 8, 32) * n_thickness
104                                 ), 2),
105                         speed = {x = n_speedx * 4, z = n_speedz * 4},
106                 })
107         end
108 end
109
110
111 local function cyclic_update()
112         update_clouds()
113         minetest.after(CYCLE, cyclic_update)
114 end
115
116
117 minetest.after(0, cyclic_update)
118
119
120 -- Update on player join to instantly alter clouds from the default
121
122 minetest.register_on_joinplayer(function(player)
123         update_clouds()
124 end)