Increase weather duration
[MineClone/MineClone2.git] / mods / ENVIRONMENT / weather_pack / rain.lua
bloba03584c4d8e29effd6a21548a5f8a8e7d4b0dad3
1 local PARTICLES_COUNT_RAIN = 30
2 local PARTICLES_COUNT_THUNDER = 45
4 rain = {
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
12 raining = false,
14 -- keeping last timeofday value (rounded).
15 -- Defaulted to non-existing value for initial comparing.
16 sky_last_update = -1,
18 init_done = false,
21 rain.sound_handler = function(player)
22 return minetest.sound_play("weather_rain", {
23 object = player,
24 max_hear_distance = 2,
25 loop = true,
27 end
29 -- set skybox based on time (uses skycolor api)
30 rain.set_sky_box = function()
31 if weather.state == "rain" then
32 skycolor.add_layer(
33 "weather-pack-rain-sky",
34 {{r=0, g=0, b=0},
35 {r=85, g=86, b=98},
36 {r=175, g=175, b=191},
37 {r=85, g=86, b=98},
38 {r=0, g=0, b=0}})
39 skycolor.active = true
40 for _, player in pairs(minetest.get_connected_players()) do
41 player:set_clouds({color="#5D5D5FE8"})
42 end
43 end
44 end
46 -- creating manually parctiles instead of particles spawner because of easier to control
47 -- spawn position.
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},
59 expirationtime = 0.2,
60 size = math.random(0.5, 3),
61 collisiondetection = true,
62 collision_removal = true,
63 vertical = true,
64 texture = rain.get_texture(),
65 playername = player:get_player_name()
67 end
68 end
69 end
71 -- Simple random texture getter
72 rain.get_texture = function()
73 local texture_name
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"
79 else
80 texture_name = "weather_pack_rain_raindrop_3.png"
81 end
82 return texture_name;
83 end
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
92 end
93 end
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
113 return false
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()
140 rain.raining = false
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
153 return false
156 rain.make_weather()
157 end)
159 rain.make_weather = function()
160 if rain.init_done == false then
161 rain.raining = true
162 rain.set_sky_box()
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)
170 return false
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
182 else
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"},
192 interval = 4.0,
193 chance = 2,
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"},
208 interval = 56.0,
209 chance = 1,
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"})
223 -- Wetten the soil
224 minetest.register_abm({
225 label = "Rain hydrates farmland",
226 nodenames = {"mcl_farming:soil"},
227 interval = 22.0,
228 chance = 3,
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 = {
241 chance = 15,
242 clear = rain.clear,
243 -- 10min - 20min
244 min_duration = 600,
245 max_duration = 1200,