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", {
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_sky(player_meta
.origin_sky
[1], player_meta
.origin_sky
[2], player_meta
.origin_sky
[3], true)
100 player
:set_clouds({color
="#FFF0F0E5"})
101 mcl_weather
.players
[player
:get_player_name()] = nil
105 mcl_worlds
.register_on_dimension_change(function(player
, dimension
)
106 if dimension
~= "overworld" and dimension
~= "void" then
107 mcl_weather
.rain
.remove_sound(player
)
108 mcl_weather
.rain
.remove_player(player
)
109 elseif dimension
== "overworld" then
110 mcl_weather
.rain
.update_sound(player
)
111 if mcl_weather
.rain
.raining
then
112 mcl_weather
.rain
.add_rain_particles(player
)
113 mcl_weather
.rain
.add_player(player
)
118 -- adds and removes rain sound depending how much rain particles around player currently exist.
119 -- have few seconds delay before each check to avoid on/off sound too often
120 -- when player stay on 'edge' where sound should play and stop depending from random raindrop appearance.
121 mcl_weather
.rain
.update_sound
= function(player
)
122 local player_meta
= mcl_weather
.players
[player
:get_player_name()]
123 if player_meta
~= nil then
124 if player_meta
.sound_updated
~= nil and player_meta
.sound_updated
+ 5 > minetest
.get_gametime() then
128 if player_meta
.sound_handler
~= nil then
129 if mcl_weather
.rain
.last_rp_count
== 0 then
130 minetest
.sound_stop(player_meta
.sound_handler
)
131 player_meta
.sound_handler
= nil
133 elseif mcl_weather
.rain
.last_rp_count
> 0 then
134 player_meta
.sound_handler
= mcl_weather
.rain
.sound_handler(player
)
137 player_meta
.sound_updated
= minetest
.get_gametime()
141 -- rain sound removed from player.
142 mcl_weather
.rain
.remove_sound
= function(player
)
143 local player_meta
= mcl_weather
.players
[player
:get_player_name()]
144 if player_meta
~= nil and player_meta
.sound_handler
~= nil then
145 minetest
.sound_stop(player_meta
.sound_handler
)
146 player_meta
.sound_handler
= nil
147 player_meta
.sound_updated
= nil
151 -- callback function for removing rain
152 mcl_weather
.rain
.clear
= function()
153 mcl_weather
.rain
.raining
= false
154 mcl_weather
.rain
.sky_last_update
= -1
155 mcl_weather
.rain
.init_done
= false
156 mcl_weather
.rain
.set_particles_mode("rain")
157 mcl_weather
.skycolor
.remove_layer("weather-pack-rain-sky")
158 for _
, player
in ipairs(minetest
.get_connected_players()) do
159 mcl_weather
.rain
.remove_sound(player
)
160 mcl_weather
.rain
.remove_player(player
)
164 minetest
.register_globalstep(function(dtime
)
165 if mcl_weather
.state
~= "rain" then
169 mcl_weather
.rain
.make_weather()
172 mcl_weather
.rain
.make_weather
= function()
173 if mcl_weather
.rain
.init_done
== false then
174 mcl_weather
.rain
.raining
= true
175 mcl_weather
.rain
.set_sky_box()
176 mcl_weather
.rain
.set_particles_mode(mcl_weather
.mode
)
177 mcl_weather
.rain
.init_done
= true
180 for _
, player
in ipairs(minetest
.get_connected_players()) do
181 if (mcl_weather
.is_underwater(player
) or not mcl_worlds
.has_weather(player
:get_pos())) then
182 mcl_weather
.rain
.remove_sound(player
)
185 mcl_weather
.rain
.add_player(player
)
186 mcl_weather
.rain
.add_rain_particles(player
)
187 mcl_weather
.rain
.update_sound(player
)
191 -- Switch the number of raindrops: "thunder" for many raindrops, otherwise for normal raindrops
192 mcl_weather
.rain
.set_particles_mode
= function(mode
)
193 if mode
== "thunder" then
194 mcl_weather
.rain
.particles_count
= PARTICLES_COUNT_THUNDER
196 mcl_weather
.rain
.particles_count
= PARTICLES_COUNT_RAIN
200 if mcl_weather
.allow_abm
then
201 -- ABM for extinguish fire
202 minetest
.register_abm({
203 label
= "Rain extinguishes fire",
204 nodenames
= {"mcl_fire:fire"},
207 action
= function(pos
, node
, active_object_count
, active_object_count_wider
)
208 if mcl_weather
.rain
.raining
and mcl_weather
.rain
.extinguish_fire
then
209 if mcl_weather
.is_outdoor(pos
) then
210 minetest
.remove_node(pos
)
211 minetest
.sound_play("fire_extinguish_flame", {pos
= pos
, max_hear_distance
= 8, gain
= 0.1})
217 -- Slowly fill up cauldrons
218 minetest
.register_abm({
219 label
= "Rain fills cauldrons with water",
220 nodenames
= {"mcl_cauldrons:cauldron", "mcl_cauldrons:cauldron_1", "mcl_cauldrons:cauldron_2"},
223 action
= function(pos
, node
, active_object_count
, active_object_count_wider
)
224 -- Rain is equivalent to a water bottle
225 if mcl_weather
.rain
.raining
and mcl_weather
.is_outdoor(pos
) then
226 if node
.name
== "mcl_cauldrons:cauldron" then
227 minetest
.set_node(pos
, {name
="mcl_cauldrons:cauldron_1"})
228 elseif node
.name
== "mcl_cauldrons:cauldron_1" then
229 minetest
.set_node(pos
, {name
="mcl_cauldrons:cauldron_2"})
230 elseif node
.name
== "mcl_cauldrons:cauldron_2" then
231 minetest
.set_node(pos
, {name
="mcl_cauldrons:cauldron_3"})
232 elseif node
.name
== "mcl_cauldrons:cauldron_1r" then
233 minetest
.set_node(pos
, {name
="mcl_cauldrons:cauldron_2r"})
234 elseif node
.name
== "mcl_cauldrons:cauldron_2r" then
235 minetest
.set_node(pos
, {name
="mcl_cauldrons:cauldron_3r"})
242 minetest
.register_abm({
243 label
= "Rain hydrates farmland",
244 nodenames
= {"mcl_farming:soil"},
247 action
= function(pos
, node
, active_object_count
, active_object_count_wider
)
248 if mcl_weather
.rain
.raining
and mcl_weather
.is_outdoor(pos
) then
249 if node
.name
== "mcl_farming:soil" then
250 minetest
.set_node(pos
, {name
="mcl_farming:soil_wet"})
257 if mcl_weather
.reg_weathers
.rain
== nil then
258 mcl_weather
.reg_weathers
.rain
= {
259 clear
= mcl_weather
.rain
.clear
,