]> git.lizzy.rs Git - Crafter.git/blob - mods/weather/init.lua
b31d2cf1270a1163ca11a9ed8b57135cc0457137
[Crafter.git] / mods / weather / init.lua
1 local weather_max = 2
2 local weather_type = math.random(0,weather_max)
3 local weather_timer = 0
4
5
6
7 --this updates players skys since it cannot be done clientside
8 local update_player_sky = function()
9         for _,player in ipairs(minetest.get_connected_players()) do
10                 if weather_type ~= 0 then
11                         player:set_sky({
12                                 base_color="#808080",
13                                 type="plain",
14                                 clouds=false,
15                                 
16                                 day_sky = "#808080",
17                                 dawn_horizon = "#808080",
18                                 dawn_sky = "#808080",
19                                 fog_sun_tint = "#808080",
20                                 
21                                 night_sky="#808080",
22                                 night_horizon="#808080"
23                         })
24                         player:set_sun({visible=false,sunrise_visible=false})
25                         player:set_moon({visible=false})
26                         player:set_stars({visible=false})
27                 else
28                         player:set_sky({
29                                 base_color="#8cbafa",
30                                 type="regular",
31                                 clouds=true,
32                                 
33                                 day_sky = "#8cbafa",
34                                 
35                                 dawn_horizon = "#bac1f0",
36                                 dawn_sky = "#b4bafa",
37                                 
38                                 night_sky="#006aff",
39                                 night_horizon="#4090ff"
40                         })
41                         
42                         player:set_sun({visible=true,sunrise_visible=true})
43                         player:set_moon({visible=true})
44                         player:set_stars({visible=true})
45                 end
46         end
47 end
48
49 --this tells the client mod to update the weather type
50 local function_send_weather_type = function()
51         local channel = minetest.mod_channel_join("weather_type")
52         channel:send_all(tostring(weather_type))
53         channel:leave()
54 end
55
56 --index all mods
57 local all_nodes = {}
58 minetest.register_on_mods_loaded(function()
59         for name in pairs(minetest.registered_nodes) do
60                 if name ~= "air" and name ~= "ignore" then
61                         table.insert(all_nodes,name)
62                 end
63         end     
64 end)
65
66 --this sends the client all nodes that weather can be on top of
67 --(everything)
68
69 --have the client send the server the ready signal
70 minetest.register_on_joinplayer(function(player)
71         minetest.after(5, function()
72                 
73                 local text = minetest.serialize(all_nodes)
74                 local channel = minetest.mod_channel_join("weather_nodes")
75                 channel:send_all(text)
76                 channel:leave()
77                 
78                 function_send_weather_type()
79                 update_player_sky()
80         end)
81 end)
82
83
84 --spawn snow nodes
85 local snow_timer = 0
86 local do_snow = function(dtime)
87         snow_timer = snow_timer + dtime
88         if snow_timer > 3 then
89                 snow_timer = 0
90                 for _,player in ipairs(minetest.get_connected_players()) do
91                         --print("running")
92                         local pos = player:get_pos()
93                         
94                         local meta = player:get_meta()
95                         local particle_table = {}
96                         
97                         local area = vector.new(40,40,40)
98                         
99                         local min = vector.subtract(pos, area)
100                         local max = vector.add(pos, area)
101                         
102                         
103                         local area_index = minetest.find_nodes_in_area_under_air(min, max, all_nodes)
104                         
105
106                         local spawn_table = {}
107                         for _,index in pairs(area_index) do
108                                 if not spawn_table[index.x] then spawn_table[index.x] = {} end
109                                 if not spawn_table[index.x][index.z] then
110                                         spawn_table[index.x][index.z] = index.y
111                                 elseif spawn_table[index.x][index.z] < index.y then
112                                         spawn_table[index.x][index.z] = index.y
113                                 end
114                         end
115                 
116                         
117                         --find the highest y value
118                         local bulk_list = {}
119                         for x,x_index in pairs(spawn_table) do
120                                 for z,y in pairs(x_index) do
121                                         if math.random() > 0.995 then
122                                                 local lightlevel = minetest.get_node_light(vector.new(x,y+1,z), 0.5)
123                                                 if lightlevel >= 14 then
124                                                         --make it so buildable to nodes get replaced
125                                                         local node = minetest.get_node(vector.new(x,y,z)).name
126                                                         local def = minetest.registered_nodes[node]
127                                                         local buildable = def.buildable_to
128                                                         local walkable = def.walkable
129                                                         local liquid = (def.liquidtype ~= "none")
130                                                         
131                                                         if not liquid then
132                                                                 if not buildable and minetest.get_node(vector.new(x,y+1,z)).name ~= "weather:snow" and walkable == true then
133                                                                         table.insert(bulk_list, vector.new(x,y+1,z))
134                                                                 elseif buildable == true and node ~= "weather:snow" then
135                                                                         table.insert(bulk_list, vector.new(x,y,z))
136                                                                 end
137                                                         end
138                                                 end
139                                         end
140                                 end
141                         end
142                         if bulk_list then
143                                 minetest.bulk_set_node(bulk_list, {name="weather:snow"})
144                         end
145                 end
146         end
147 end
148
149
150
151 --this sets random weather
152 local weather_timer_goal = (math.random(5,7)+math.random())*60
153 minetest.register_globalstep(function(dtime)
154         weather_timer = weather_timer + dtime
155         if weather_timer >= weather_timer_goal then
156                 weather_timer_goal = (math.random(5,7)+math.random())*60
157                 weather_timer = 0
158                 weather_type = math.random(0,weather_max)
159                 function_send_weather_type()
160                 update_player_sky()
161         end
162         --spawn snow nodes
163         if weather_type == 1 then
164                 do_snow(dtime)
165         end
166 end)
167
168 local snowball_throw = function(player)
169         local pos = player:get_pos()
170         pos.y = pos.y + 1.625
171         --let other players hear the noise too
172         minetest.sound_play("woosh",{to_player=player:get_player_name(), pitch = math.random(80,100)/100})
173         minetest.sound_play("woosh",{pos=pos, exclude_player = player:get_player_name(), pitch = math.random(80,100)/100})
174         local snowball = minetest.add_entity(pos,"weather:snowball")
175         if snowball then
176                 local vel = player:get_player_velocity()
177                 snowball:set_velocity(vector.add(vel,vector.multiply(player:get_look_dir(),20)))
178                 snowball:get_luaentity().thrower = player:get_player_name()
179                 return(true)
180         end
181         return(false)
182 end
183
184 minetest.register_node("weather:snow", {
185     description = "Snow",
186     tiles = {"snow_block.png"},
187     groups = {soft = 1, shovel = 1, hand = 1,pathable = 1,wool=1,dirt=1,falling_node=1},
188     sounds = main.woolSound(),
189     paramtype = "light",
190         drawtype = "nodebox",
191         walkable = false,
192     drop = {
193                         max_items = 5,
194                         items= {
195                                 {
196                                         items = {"weather:snowball"},
197                                 },
198                                 {
199                                         items = {"weather:snowball"},
200                                 },
201                                 {
202                                         items = {"weather:snowball"},
203                                 },
204                                 {
205                                         items = {"weather:snowball"},
206                                 },
207                                 {
208                                         rarity = 5,
209                                         items = {"weather:snowball"},
210                                 },
211                         },
212                 },
213     buildable_to = true,
214     node_box = {
215                 type = "fixed",
216                 fixed = {
217                 {-8/16, -8/16, -8/16, 8/16, -6/16, 8/16},
218                 }
219         },
220 })
221
222 minetest.register_craftitem("weather:snowball", {
223         description = "Snowball",
224         inventory_image = "snowball.png",
225         --stack_max = 1,
226         --range = 0,
227         on_place = function(itemstack, placer, pointed_thing)
228                 local worked = snowball_throw(placer)
229                 if worked then
230                         itemstack:take_item()
231                 end
232                 return(itemstack)
233         end,
234         on_secondary_use = function(itemstack, user, pointed_thing)
235                 local worked = snowball_throw(user)
236                 if worked then
237                         itemstack:take_item()
238                 end
239                 return(itemstack)
240         end,
241 })
242
243
244 snowball = {}
245 snowball.initial_properties = {
246         hp_max = 1,
247         physical = true,
248         collide_with_objects = false,
249         collisionbox = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1},
250         visual = "sprite",
251         visual_size = {x = 0.5, y = 0.5},
252         textures = {
253                 "snowball.png"
254         },
255         is_visible = true,
256         pointable = false,
257 }
258
259 snowball.snowball = true
260
261 snowball.on_activate = function(self)
262         self.object:set_acceleration(vector.new(0,-9.81,0))
263 end
264
265 --make this as efficient as possible
266 --make it so you can hit one snowball with another
267 snowball.on_step = function(self, dtime)
268         local vel = self.object:get_velocity()
269         local hit = false
270         local pos = self.object:get_pos()
271         
272         --hit object with the snowball
273         for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
274                 if (object:is_player() and object:get_hp() > 0 and object:get_player_name() ~= self.thrower) or (object:get_luaentity() and object:get_luaentity().mob == true) then
275                         object:punch(self.object, 2, 
276                                 {
277                                 full_punch_interval=1.5,
278                                 damage_groups = {fleshy=0},
279                         })
280                         hit = true
281                         break
282                 end
283         end
284         
285         if (self.oldvel and ((vel.x == 0 and self.oldvel.x ~= 0) or (vel.y == 0 and self.oldvel.y ~= 0) or (vel.z == 0 and self.oldvel.z ~= 0))) or hit == true then
286         
287                 minetest.sound_play("wool",{pos=pos, pitch = math.random(80,100)/100})
288                 minetest.add_particlespawner({
289                         amount = 20,
290                         -- Number of particles spawned over the time period `time`.
291
292                         time = 0.001,
293                         -- Lifespan of spawner in seconds.
294                         -- If time is 0 spawner has infinite lifespan and spawns the `amount` on
295                         -- a per-second basis.
296
297                         minpos = pos,
298                         maxpos = pos,
299                         minvel = {x=-2, y=3, z=-2},
300                         maxvel = {x=2, y=5, z=2},
301                         minacc = {x=0, y=-9.81, z=0},
302                         maxacc = {x=0, y=-9.81, z=0},
303                         minexptime = 1,
304                         maxexptime = 3,
305                         minsize = 1,
306                         maxsize = 1,
307                         -- The particles' properties are random values between the min and max
308                         -- values.
309                         -- pos, velocity, acceleration, expirationtime, size
310
311                         collisiondetection = true,
312
313                         collision_removal = true,
314
315                         object_collision = false,
316
317                         texture = "snowflake_"..math.random(1,2)..".png",
318
319                 })
320                 
321                 self.object:remove()
322                 
323         end
324         
325         self.oldvel = vel
326 end
327 minetest.register_entity("weather:snowball", snowball)