1 local PARTICLES_COUNT_RAIN
= 30
2 local PARTICLES_COUNT_THUNDER
= 45
5 -- max rain particles created at time
6 particles_count
= PARTICLES_COUNT_RAIN
,
8 -- flag to turn on/off extinguish fire for rain
9 extinguish_fire
= true,
11 -- flag useful when mixing weathers
14 -- keeping last timeofday value (rounded).
15 -- Defaulted to non-existing value for initial comparing.
21 mcl_weather
.rain
.sound_handler
= function(player
)
22 return minetest
.sound_play("weather_rain", {
23 to_player
= player
:get_player_name(),
28 -- set skybox based on time (uses skycolor api)
29 mcl_weather
.rain
.set_sky_box
= function()
30 if mcl_weather
.state
== "rain" then
31 mcl_weather
.skycolor
.add_layer(
32 "weather-pack-rain-sky",
35 {r
=135, g
=135, b
=151},
38 mcl_weather
.skycolor
.active
= true
39 for _
, player
in pairs(minetest
.get_connected_players()) do
40 player
:set_clouds({color
="#5D5D5FE8"})
45 -- creating manually parctiles instead of particles spawner because of easier to control
47 mcl_weather
.rain
.add_rain_particles
= function(player
)
49 mcl_weather
.rain
.last_rp_count
= 0
50 for i
=mcl_weather
.rain
.particles_count
, 1,-1 do
51 local random_pos_x
, random_pos_y
, random_pos_z
= mcl_weather
.get_random_pos_by_player_look_dir(player
)
52 if mcl_weather
.is_outdoor({x
=random_pos_x
, y
=random_pos_y
, z
=random_pos_z
}) then
53 mcl_weather
.rain
.last_rp_count
= mcl_weather
.rain
.last_rp_count
+ 1
54 minetest
.add_particle({
55 pos
= {x
=random_pos_x
, y
=random_pos_y
, z
=random_pos_z
},
56 velocity
= {x
=0, y
=-10, z
=0},
57 acceleration
= {x
=0, y
=-30, z
=0},
59 size
= math
.random(0.5, 3),
60 collisiondetection
= true,
61 collision_removal
= true,
63 texture
= mcl_weather
.rain
.get_texture(),
64 playername
= player
:get_player_name()
70 -- Simple random texture getter
71 mcl_weather
.rain
.get_texture
= function()
73 local random_number
= math
.random()
74 if random_number
> 0.33 then
75 texture_name
= "weather_pack_rain_raindrop_1.png"
76 elseif random_number
> 0.66 then
77 texture_name
= "weather_pack_rain_raindrop_2.png"
79 texture_name
= "weather_pack_rain_raindrop_3.png"
84 -- register player for rain weather.
85 -- basically needs for origin sky reference and rain sound controls.
86 mcl_weather
.rain
.add_player
= function(player
)
87 if mcl_weather
.players
[player
:get_player_name()] == nil then
88 local player_meta
= {}
89 player_meta
.origin_sky
= {player
:get_sky()}
90 mcl_weather
.players
[player
:get_player_name()] = player_meta
94 -- remove player from player list effected by rain.
95 -- be sure to remove sound before removing player otherwise soundhandler reference will be lost.
96 mcl_weather
.rain
.remove_player
= function(player
)
97 local player_meta
= mcl_weather
.players
[player
:get_player_name()]
98 if player_meta
~= nil and player_meta
.origin_sky
~= nil then
99 player
:set_clouds({color
="#FFF0F0E5"})
100 mcl_weather
.players
[player
:get_player_name()] = nil
104 mcl_worlds
.register_on_dimension_change(function(player
, dimension
)
105 if dimension
~= "overworld" and dimension
~= "void" then
106 mcl_weather
.rain
.remove_sound(player
)
107 mcl_weather
.rain
.remove_player(player
)
108 elseif dimension
== "overworld" then
109 mcl_weather
.rain
.update_sound(player
)
110 if mcl_weather
.rain
.raining
then
111 mcl_weather
.rain
.add_rain_particles(player
)
112 mcl_weather
.rain
.add_player(player
)
117 -- adds and removes rain sound depending how much rain particles around player currently exist.
118 -- have few seconds delay before each check to avoid on/off sound too often
119 -- when player stay on 'edge' where sound should play and stop depending from random raindrop appearance.
120 mcl_weather
.rain
.update_sound
= function(player
)
121 local player_meta
= mcl_weather
.players
[player
:get_player_name()]
122 if player_meta
~= nil then
123 if player_meta
.sound_updated
~= nil and player_meta
.sound_updated
+ 5 > minetest
.get_gametime() then
127 if player_meta
.sound_handler
~= nil then
128 if mcl_weather
.rain
.last_rp_count
== 0 then
129 minetest
.sound_fade(player_meta
.sound_handler
, -0.5, 0.0)
130 player_meta
.sound_handler
= nil
132 elseif mcl_weather
.rain
.last_rp_count
> 0 then
133 player_meta
.sound_handler
= mcl_weather
.rain
.sound_handler(player
)
136 player_meta
.sound_updated
= minetest
.get_gametime()
140 -- rain sound removed from player.
141 mcl_weather
.rain
.remove_sound
= function(player
)
142 local player_meta
= mcl_weather
.players
[player
:get_player_name()]
143 if player_meta
~= nil and player_meta
.sound_handler
~= nil then
144 minetest
.sound_fade(player_meta
.sound_handler
, -0.5, 0.0)
145 player_meta
.sound_handler
= nil
146 player_meta
.sound_updated
= nil
150 -- callback function for removing rain
151 mcl_weather
.rain
.clear
= function()
152 mcl_weather
.rain
.raining
= false
153 mcl_weather
.rain
.sky_last_update
= -1
154 mcl_weather
.rain
.init_done
= false
155 mcl_weather
.rain
.set_particles_mode("rain")
156 mcl_weather
.skycolor
.remove_layer("weather-pack-rain-sky")
157 for _
, player
in ipairs(minetest
.get_connected_players()) do
158 mcl_weather
.rain
.remove_sound(player
)
159 mcl_weather
.rain
.remove_player(player
)
163 minetest
.register_globalstep(function(dtime
)
164 if mcl_weather
.state
~= "rain" then
168 mcl_weather
.rain
.make_weather()
171 mcl_weather
.rain
.make_weather
= function()
172 if mcl_weather
.rain
.init_done
== false then
173 mcl_weather
.rain
.raining
= true
174 mcl_weather
.rain
.set_sky_box()
175 mcl_weather
.rain
.set_particles_mode(mcl_weather
.mode
)
176 mcl_weather
.rain
.init_done
= true
179 for _
, player
in ipairs(minetest
.get_connected_players()) do
180 if (mcl_weather
.is_underwater(player
) or not mcl_worlds
.has_weather(player
:get_pos())) then
181 mcl_weather
.rain
.remove_sound(player
)
184 mcl_weather
.rain
.add_player(player
)
185 mcl_weather
.rain
.add_rain_particles(player
)
186 mcl_weather
.rain
.update_sound(player
)
190 -- Switch the number of raindrops: "thunder" for many raindrops, otherwise for normal raindrops
191 mcl_weather
.rain
.set_particles_mode
= function(mode
)
192 if mode
== "thunder" then
193 mcl_weather
.rain
.particles_count
= PARTICLES_COUNT_THUNDER
195 mcl_weather
.rain
.particles_count
= PARTICLES_COUNT_RAIN
199 if mcl_weather
.allow_abm
then
200 -- ABM for extinguish fire
201 minetest
.register_abm({
202 label
= "Rain extinguishes fire",
203 nodenames
= {"mcl_fire:fire"},
206 action
= function(pos
, node
, active_object_count
, active_object_count_wider
)
207 -- Fire is extinguished if in rain or one of 4 neighbors is in rain
208 if mcl_weather
.rain
.raining
and mcl_weather
.rain
.extinguish_fire
then
210 { x
= 0, y
= 0, z
= 0 },
211 { x
= -1, y
= 0, z
= 0 },
212 { x
= 1, y
= 0, z
= 0 },
213 { x
= 0, y
= 0, z
= -1 },
214 { x
= 0, y
= 0, z
= 1 },
217 local apos
= vector
.add(pos
, around
[a
])
218 if mcl_weather
.is_outdoor(apos
) then
219 minetest
.remove_node(pos
)
220 minetest
.sound_play("fire_extinguish_flame", {pos
= pos
, max_hear_distance
= 8, gain
= 0.1}, true)
228 -- Slowly fill up cauldrons
229 minetest
.register_abm({
230 label
= "Rain fills cauldrons with water",
231 nodenames
= {"mcl_cauldrons:cauldron", "mcl_cauldrons:cauldron_1", "mcl_cauldrons:cauldron_2"},
234 action
= function(pos
, node
, active_object_count
, active_object_count_wider
)
235 -- Rain is equivalent to a water bottle
236 if mcl_weather
.rain
.raining
and mcl_weather
.is_outdoor(pos
) then
237 if node
.name
== "mcl_cauldrons:cauldron" then
238 minetest
.set_node(pos
, {name
="mcl_cauldrons:cauldron_1"})
239 elseif node
.name
== "mcl_cauldrons:cauldron_1" then
240 minetest
.set_node(pos
, {name
="mcl_cauldrons:cauldron_2"})
241 elseif node
.name
== "mcl_cauldrons:cauldron_2" then
242 minetest
.set_node(pos
, {name
="mcl_cauldrons:cauldron_3"})
243 elseif node
.name
== "mcl_cauldrons:cauldron_1r" then
244 minetest
.set_node(pos
, {name
="mcl_cauldrons:cauldron_2r"})
245 elseif node
.name
== "mcl_cauldrons:cauldron_2r" then
246 minetest
.set_node(pos
, {name
="mcl_cauldrons:cauldron_3r"})
253 minetest
.register_abm({
254 label
= "Rain hydrates farmland",
255 nodenames
= {"mcl_farming:soil"},
258 action
= function(pos
, node
, active_object_count
, active_object_count_wider
)
259 if mcl_weather
.rain
.raining
and mcl_weather
.is_outdoor(pos
) then
260 if node
.name
== "mcl_farming:soil" then
261 minetest
.set_node(pos
, {name
="mcl_farming:soil_wet"})
268 if mcl_weather
.reg_weathers
.rain
== nil then
269 mcl_weather
.reg_weathers
.rain
= {
270 clear
= mcl_weather
.rain
.clear
,