3 -- By Kaadmy, for Pixture
6 local S
= minetest
.get_translator("rp_weather")
8 local mod_storage
= minetest
.get_mod_storage()
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
}
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 }
45 if sound_handles
[name
] then
46 minetest
.sound_fade(sound_handles
[name
], -0.5, 0)
47 sound_handles
[name
] = nil
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
62 minetest
.after(3, update_sounds
, do_repeat
)
66 -- This timer prevents the weather from changing naturally too fast
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()
76 local function setweather_type(wtype
, do_repeat
)
78 for i
= 1, #weather
.types
do
79 if weather
.types
[i
] == wtype
then
84 if weather
.weather
~= wtype
then
85 -- Only reset stoptimer if weather actually changed
86 stoptimer
= stoptimer_init
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
)
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
105 local diff
= time
- weather
.last_weather_change
109 minetest
.register_globalstep(
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)
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")
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
)
139 stoptimer
= stoptimer_init
144 local light
= (minetest
.get_timeofday() * 2)
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
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()
181 speed
= {x
= -2, y
= 1},
184 player
:override_day_night_ratio(light
)
186 player
:set_sky({type = "regular", clouds
= true, sky_color
= {
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(
217 minvel
= {x
= 0, y
= -20, z
= 0},
218 maxvel
= {x
= 0, y
= -20, z
= 0},
223 collisiondetection
= true,
224 collision_removal
= true,
226 texture
= "weather_rain.png",
227 playername
= player
:get_player_name()
236 minetest
.register_privilege(
239 description
= S("Can change the weather using the /weather command"),
240 give_to_singleplayer
= false
243 minetest
.register_chatcommand(
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”.")
254 return true, S("Weather changed.")
259 minetest
.register_on_leaveplayer(function(player
)
260 sound_handles
[player
:get_player_name()] = nil