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 rain
.sound_handler
= function(player
)
22 return minetest
.sound_play("weather_rain", {
24 max_hear_distance
= 2,
29 -- set skybox based on time (uses skycolor api)
30 rain
.set_sky_box
= function()
31 if weather
.state
== "rain" then
33 "weather-pack-rain-sky",
36 {r
=175, g
=175, b
=191},
39 skycolor
.active
= true
40 for _
, player
in pairs(minetest
.get_connected_players()) do
41 player
:set_clouds({color
="#5D5D5FE8"})
46 -- creating manually parctiles instead of particles spawner because of easier to control
48 rain
.add_rain_particles
= function(player
)
50 rain
.last_rp_count
= 0
51 for i
=rain
.particles_count
, 1,-1 do
52 local random_pos_x
, random_pos_y
, random_pos_z
= weather
.get_random_pos_by_player_look_dir(player
)
53 if weather
.is_outdoor({x
=random_pos_x
, y
=random_pos_y
, z
=random_pos_z
}) then
54 rain
.last_rp_count
= rain
.last_rp_count
+ 1
55 minetest
.add_particle({
56 pos
= {x
=random_pos_x
, y
=random_pos_y
, z
=random_pos_z
},
57 velocity
= {x
=0, y
=-10, z
=0},
58 acceleration
= {x
=0, y
=-30, z
=0},
60 size
= math
.random(0.5, 3),
61 collisiondetection
= true,
62 collision_removal
= true,
64 texture
= rain
.get_texture(),
65 playername
= player
:get_player_name()
71 -- Simple random texture getter
72 rain
.get_texture
= function()
74 local random_number
= math
.random()
75 if random_number
> 0.33 then
76 texture_name
= "weather_pack_rain_raindrop_1.png"
77 elseif random_number
> 0.66 then
78 texture_name
= "weather_pack_rain_raindrop_2.png"
80 texture_name
= "weather_pack_rain_raindrop_3.png"
85 -- register player for rain weather.
86 -- basically needs for origin sky reference and rain sound controls.
87 rain
.add_player
= function(player
)
88 if weather
.players
[player
:get_player_name()] == nil then
89 local player_meta
= {}
90 player_meta
.origin_sky
= {player
:get_sky()}
91 weather
.players
[player
:get_player_name()] = player_meta
95 -- remove player from player list effected by rain.
96 -- be sure to remove sound before removing player otherwise soundhandler reference will be lost.
97 rain
.remove_player
= function(player
)
98 local player_meta
= weather
.players
[player
:get_player_name()]
99 if player_meta
~= nil and player_meta
.origin_sky
~= nil then
100 player
:set_sky(player_meta
.origin_sky
[1], player_meta
.origin_sky
[2], player_meta
.origin_sky
[3], true)
101 player
:set_clouds({color
="#FFF0F0E5"})
102 weather
.players
[player
:get_player_name()] = nil
106 -- adds and removes rain sound depending how much rain particles around player currently exist.
107 -- have few seconds delay before each check to avoid on/off sound too often
108 -- when player stay on 'edge' where sound should play and stop depending from random raindrop appearance.
109 rain
.update_sound
= function(player
)
110 local player_meta
= weather
.players
[player
:get_player_name()]
111 if player_meta
~= nil then
112 if player_meta
.sound_updated
~= nil and player_meta
.sound_updated
+ 5 > minetest
.get_gametime() then
116 if player_meta
.sound_handler
~= nil then
117 if rain
.last_rp_count
== 0 then
118 minetest
.sound_stop(player_meta
.sound_handler
)
119 player_meta
.sound_handler
= nil
121 elseif rain
.last_rp_count
> 0 then
122 player_meta
.sound_handler
= rain
.sound_handler(player
)
125 player_meta
.sound_updated
= minetest
.get_gametime()
129 -- rain sound removed from player.
130 rain
.remove_sound
= function(player
)
131 local player_meta
= weather
.players
[player
:get_player_name()]
132 if player_meta
~= nil and player_meta
.sound_handler
~= nil then
133 minetest
.sound_stop(player_meta
.sound_handler
)
134 player_meta
.sound_handler
= nil
138 -- callback function for removing rain
139 rain
.clear
= function()
141 rain
.sky_last_update
= -1
142 rain
.init_done
= false
143 rain
.set_particles_mode("rain")
144 skycolor
.remove_layer("weather-pack-rain-sky")
145 for _
, player
in ipairs(minetest
.get_connected_players()) do
146 rain
.remove_sound(player
)
147 rain
.remove_player(player
)
151 minetest
.register_globalstep(function(dtime
)
152 if weather
.state
~= "rain" then
159 rain
.make_weather
= function()
160 if rain
.init_done
== false then
163 rain
.init_done
= true
164 rain
.set_particles_mode(weather
.mode
)
167 for _
, player
in ipairs(minetest
.get_connected_players()) do
168 if (weather
.is_underwater(player
) or not mcl_util
.has_weather(player
:getpos())) then
169 rain
.remove_sound(player
)
172 rain
.add_player(player
)
173 rain
.add_rain_particles(player
)
174 rain
.update_sound(player
)
178 -- Switch the number of raindrops: "thunder" for many raindrops, otherwise for normal raindrops
179 rain
.set_particles_mode
= function(mode
)
180 if mode
== "thunder" then
181 rain
.particles_count
= PARTICLES_COUNT_THUNDER
183 rain
.particles_count
= PARTICLES_COUNT_RAIN
187 if weather
.allow_abm
then
188 -- ABM for extinguish fire
189 minetest
.register_abm({
190 label
= "Rain extinguishes fire",
191 nodenames
= {"mcl_fire:fire"},
194 action
= function(pos
, node
, active_object_count
, active_object_count_wider
)
195 if rain
.raining
and rain
.extinguish_fire
then
196 if weather
.is_outdoor(pos
) then
197 minetest
.remove_node(pos
)
198 minetest
.sound_play("fire_extinguish_flame", {pos
= pos
, max_hear_distance
= 16, gain
= 0.15})
204 -- Slowly fill up cauldrons
205 minetest
.register_abm({
206 label
= "Rain fills cauldrons with water",
207 nodenames
= {"mcl_cauldrons:cauldron", "mcl_cauldrons:cauldron_1", "mcl_cauldrons:cauldron_2"},
210 action
= function(pos
, node
, active_object_count
, active_object_count_wider
)
211 if rain
.raining
and weather
.is_outdoor(pos
) then
212 if node
.name
== "mcl_cauldrons:cauldron" then
213 minetest
.set_node(pos
, {name
="mcl_cauldrons:cauldron_1"})
214 elseif node
.name
== "mcl_cauldrons:cauldron_1" then
215 minetest
.set_node(pos
, {name
="mcl_cauldrons:cauldron_2"})
216 elseif node
.name
== "mcl_cauldrons:cauldron_2" then
217 minetest
.set_node(pos
, {name
="mcl_cauldrons:cauldron_3"})
224 minetest
.register_abm({
225 label
= "Rain hydrates farmland",
226 nodenames
= {"mcl_farming:soil"},
229 action
= function(pos
, node
, active_object_count
, active_object_count_wider
)
230 if rain
.raining
and weather
.is_outdoor(pos
) then
231 if node
.name
== "mcl_farming:soil" then
232 minetest
.set_node(pos
, {name
="mcl_farming:soil_wet"})
239 if weather
.reg_weathers
.rain
== nil then
240 weather
.reg_weathers
.rain
= {