Update game screenshot
[Pixture/pixture_revival.git] / mods / rp_weather / init.lua
blob491a9cf3560e57c932ae7ec0cc9a0010df624407
1 --
2 -- Weather mod
3 -- By Kaadmy, for Pixture
4 --
6 local S = minetest.get_translator("rp_weather")
8 local mod_storage = minetest.get_mod_storage()
10 weather = {}
11 weather.weather = "clear"
12 weather.previous_weather = "clear"
13 weather.last_weather_change = nil
14 weather.types = {"storm", "clear"}
16 local sound_handles = {}
18 local function addvec(v1, v2)
19 return {x = v1.x + v2.x, y = v1.y + v2.y, z = v1.z + v2.z}
20 end
22 local mapseed = minetest.get_mapgen_setting("seed")
23 local weather_pr=PseudoRandom(mapseed + 2387)
25 local sound_min_height = -20 -- Below -20m you can't hear weather
27 local default_cloud_state = nil
29 local loaded_weather = mod_storage:get_string("rp_weather:weather")
30 local weather_inited = false
32 local function update_sounds(do_repeat)
33 if weather.weather == "storm" then
34 for _, player in ipairs(minetest.get_connected_players()) do
35 local name = player:get_player_name()
36 local pos = player:get_pos()
37 local node = minetest.get_node({x=pos.x, y=pos.y+1.5, z=pos.z})
38 if pos.y > sound_min_height and minetest.get_item_group(node.name, "water") == 0 then
39 if not sound_handles[name] then
40 sound_handles[name] = minetest.sound_play(
41 { name = "weather_storm" }, { to_player = name, loop = true, fade = 0.5 }
43 end
44 else
45 if sound_handles[name] then
46 minetest.sound_fade(sound_handles[name], -0.5, 0)
47 sound_handles[name] = nil
48 end
49 end
50 end
51 else
52 for _, player in ipairs(minetest.get_connected_players()) do
53 local name = player:get_player_name()
54 if sound_handles[name] then
55 minetest.sound_fade(sound_handles[name], -1.0, 0)
56 sound_handles[name] = nil
57 end
58 end
59 end
61 if do_repeat then
62 minetest.after(3, update_sounds, do_repeat)
63 end
64 end
66 -- This timer prevents the weather from changing naturally too fast
67 local stoptimer = 0
68 local stoptimer_init = 15 -- minumum time between natural weather changes in seconds
70 local function setweather_raw(new_weather)
71 weather.previous_weather = weather.weather
72 weather.weather = new_weather
73 weather.last_weather_change = minetest.get_us_time()
74 end
76 local function setweather_type(wtype, do_repeat)
77 local valid = false
78 for i = 1, #weather.types do
79 if weather.types[i] == wtype then
80 valid = true
81 end
82 end
83 if valid then
84 if weather.weather ~= wtype then
85 -- Only reset stoptimer if weather actually changed
86 stoptimer = stoptimer_init
87 end
88 setweather_raw(wtype)
89 mod_storage:set_string("rp_weather:weather", weather.weather)
90 minetest.log("action", "[rp_weather] Weather set to: "..weather.weather)
91 update_sounds(do_repeat)
92 return true
93 else
94 return false
95 end
96 end
98 -- Returns a number telling how many µs the weather was changed before.
99 -- Returns nil if weather was not changed before
100 function weather.weather_last_changed_before()
101 local time = minetest.get_us_time()
102 if not weather.last_weather_change then
103 return nil
105 local diff = time - weather.last_weather_change
106 return diff
109 minetest.register_globalstep(
110 function(dtime)
111 if stoptimer > 0 then
112 stoptimer = stoptimer - dtime
114 if minetest.settings:get_bool("weather_enable") and stoptimer <= 0 then
115 if not weather_inited then
116 if loaded_weather == "" then
117 setweather_type("clear", true)
118 else
119 setweather_type(loaded_weather, true)
121 weather_inited = true
122 elseif weather_pr:next(0, 5000) < 1 then
123 local weathertype = weather_pr:next(0, 19)
125 -- on avg., every 1800 globalsteps, the weather.weather will change to one of:
126 -- 13/20 chance of clear weather
127 -- 7/20 chance or stormy weather
129 local oldweather = weather.weather
130 if weathertype < 13 then
131 setweather_raw("clear")
132 else
133 setweather_raw("storm")
135 if oldweather ~= weather.weather then
136 mod_storage:set_string("rp_weather:weather", weather.weather)
137 minetest.log("action", "[rp_weather] Weather changed to: "..weather.weather)
138 update_sounds()
139 stoptimer = stoptimer_init
144 local light = (minetest.get_timeofday() * 2)
146 if light > 1 then
147 light = 1 - (light - 1)
150 light = (light * 0.5) + 0.15
152 local skycol = math.floor(light * 190)
154 for _, player in ipairs(minetest.get_connected_players()) do
155 if weather.weather == "storm" then
156 player:set_sky({
157 type = "regular",
158 clouds = true,
159 sky_color = {
160 day_sky = {r = skycol, g = skycol, b = skycol * 1.2},
161 day_horizon = {r = skycol, g = skycol, b = skycol * 1.2},
162 dawn_sky = {r = skycol*0.75, g = skycol*0.75, b = skycol * 0.9},
163 dawn_horizon = {r = skycol*0.75, g = skycol*0.75, b = skycol * 0.9},
164 night_sky = {r = skycol*0.5, g = skycol*0.5, b = skycol * 0.6},
165 night_horizon = {r = skycol*0.5, g = skycol*0.5, b = skycol * 0.6},
168 player:set_sun({visible=false, sunrise_visible=false})
169 player:set_stars({visible=false})
170 player:set_moon({visible=false})
171 if default_cloud_state == nil then
172 default_cloud_state = player:get_clouds()
175 player:set_clouds({
176 density = 0.5,
177 color = "#a0a0a0f0",
178 ambient = "#000000",
179 height = 100,
180 thickness = 40,
181 speed = {x = -2, y = 1},
184 player:override_day_night_ratio(light)
185 else
186 player:set_sky({type = "regular", clouds = true, sky_color = {
187 day_sky = "#8cbafa",
188 day_horizon = "#9bc1f0",
189 dawn_sky = "#b4bafa",
190 dawn_horizon = "#bac1f0",
191 night_sky = "#006aff",
192 night_horizon = "#4090ff",
194 player:set_sun({visible=true, sunrise_visible=true})
195 player:set_stars({visible=true})
196 player:set_moon({visible=true})
198 if default_cloud_state ~= nil then
199 player:set_clouds(default_cloud_state)
202 player:override_day_night_ratio(nil)
205 local p=player:get_pos()
207 if weather.weather == "storm" then
208 if minetest.get_node_light({x=p.x, y=p.y+15, z=p.z}, 0.5) == 15 then
209 local minpos = addvec(player:get_pos(), {x = -15, y = 15, z = -15})
210 local maxpos = addvec(player:get_pos(), {x = 15, y = 10, z = 15})
211 minetest.add_particlespawner(
213 amount = 30,
214 time = 0.5,
215 minpos = minpos,
216 maxpos = maxpos,
217 minvel = {x = 0, y = -20, z = 0},
218 maxvel = {x = 0, y = -20, z = 0},
219 minexptime = 0.9,
220 maxexptime = 1.1,
221 minsize = 2,
222 maxsize = 3,
223 collisiondetection = true,
224 collision_removal = true,
225 vertical = true,
226 texture = "weather_rain.png",
227 playername = player:get_player_name()
236 minetest.register_privilege(
237 "weather",
239 description = S("Can change the weather using the /weather command"),
240 give_to_singleplayer = false
243 minetest.register_chatcommand(
244 "weather",
246 params = "storm | clear",
247 description = S("Change the weather"),
248 privs = {weather = true},
249 func = function(name, param)
250 local weather_set = setweather_type(param)
251 if not weather_set then
252 return false, S("Incorrect weather. Valid weathers are “storm” and “clear”.")
253 else
254 return true, S("Weather changed.")
259 minetest.register_on_leaveplayer(function(player)
260 sound_handles[player:get_player_name()] = nil
261 end)