]> git.lizzy.rs Git - crafter_client.git/blobdiff - weather_handling.lua
Update README.md
[crafter_client.git] / weather_handling.lua
index d28cf451e9d6a341c150c826b69c403439aba8dc..65ca36cf2d5a268c91c17b184ac12ea7bd0c8359 100644 (file)
@@ -1,3 +1,12 @@
+local
+minetest,name,vector,math,pairs
+=
+minetest,minetest.localplayer:get_name(),vector,math,pairs
+
+local weather_intake = minetest.mod_channel_join("weather_intake")
+local weather = minetest.mod_channel_join("weather_nodes")
+local weather_type = minetest.mod_channel_join("weather_type")
+
 local all_nodes = {}
 local do_effects = false
 local snow = false
@@ -7,75 +16,37 @@ local id_table = {}
 
 local rain_sound_handle = nil
 
-local spawn_snow = function(player)
-       local pos = player:get_pos()
-       local radius = 10
-       local particle_table = {}
-       
-       local area = vector.new(10,10,10)
-       
-       local min = vector.subtract(pos, area)
-       local max = vector.add(pos, area)
-       
-       
-       local area_index = minetest.find_nodes_in_area_under_air(min, max, all_nodes)
-       
-       local spawn_table = {}
-       --find the highest y value
-       for _,index in pairs(area_index) do
-               if not spawn_table[index.x] then spawn_table[index.x] = {} end
-               if not spawn_table[index.x][index.z] then
-                       spawn_table[index.x][index.z] = index.y
-               elseif spawn_table[index.x][index.z] < index.y then
-                       spawn_table[index.x][index.z] = index.y
-               end
-       end
-       
-       for x,x_index in pairs(spawn_table) do
-               for z,y in pairs(x_index) do
-                       if minetest.get_node_or_nil(vector.new(x,y+1,z)) ~= nil then
-                               local pos = vector.new(x,y+1,z)
-                               local lightlevel = minetest.get_node_light(pos, 0.5)
-                               if lightlevel >= 14 then
-                                       minetest.add_particlespawner({
-                                               amount = 1,
-                                               time = 0.5,
-                                               minpos = vector.new(x-0.5,y,z-0.5),
-                                               maxpos = vector.new(x+0.5,y+20,z+0.5),
-                                               minvel = {x=-0.2, y=-0.2, z=-0.2},
-                                               maxvel = {x=0.2, y=-0.5, z=0.2},
-                                               minacc = {x=0, y=0, z=0},
-                                               maxacc = {x=0, y=0, z=0},
-                                               minexptime = 1,
-                                               maxexptime = 1,
-                                               minsize = 1,
-                                               maxsize = 1,
-                                               collisiondetection = true,
-                                               collision_removal = true,
-                                               object_collision = false,
-                                               texture = "snowflake_"..math.random(1,2)..".png",
-                                               playername = player:get_name(),
-                                       })
-                               end
-                       end
-               end
-       end
-end
+local liquids = {
+       ["main:water"] = true,
+       ["main:waterflow"] = true,
+       ["main:lava"] = true,
+       ["main:lavaflow"] = true,
+       ["nether:lava"] = true,
+       ["nether:lavaflow"] = true,
+}
 
-local spawn_ichor = function(player)
-       local pos = player:get_pos()
-       local radius = 10
-       local particle_table = {}
-       
-       local area = vector.new(10,10,10)
-       
-       local min = vector.subtract(pos, area)
-       local max = vector.add(pos, area)
-       
-       
-       local area_index = minetest.find_nodes_in_area_under_air(min, max, all_nodes)
-       
-       local spawn_table = {}
+
+local y
+local pos
+local radius = 10
+local particle_table
+local area
+local min
+local max
+local area_index
+local spawn_table
+local lightlevel
+local null
+local curr_light
+local distance = vector.distance
+local current_node 
+local weather_effects = function(player,defined_type)
+       pos = vector.round(player:get_pos())
+       area = vector.new(10,10,10)
+       min = vector.subtract(pos, area)
+       max = vector.add(pos, area)
+       area_index = minetest.find_nodes_in_area_under_air(min, max, all_nodes)
+       spawn_table = {}
        --find the highest y value
        for _,index in pairs(area_index) do
                if not spawn_table[index.x] then spawn_table[index.x] = {} end
@@ -85,136 +56,162 @@ local spawn_ichor = function(player)
                        spawn_table[index.x][index.z] = index.y
                end
        end
-       
-       for x,x_index in pairs(spawn_table) do
-               for z,y in pairs(x_index) do
-                       if minetest.get_node_or_nil(vector.new(x,y+1,z)) ~= nil then
-                               local pos = vector.new(x,y+1,z)
-                               minetest.add_particlespawner({
-                                       amount = 1,
-                                       time = 0.5,
-                                       minpos = vector.new(x-0.5,y,z-0.5),
-                                       maxpos = vector.new(x+0.5,y+20,z+0.5),
-                                       minvel = {x=-0.2, y=0.2, z=-0.2},
-                                       maxvel = {x=0.2, y=0.5, z=0.2},
-                                       minacc = {x=0, y=0, z=0},
-                                       maxacc = {x=0, y=0, z=0},
-                                       minexptime = 1,
-                                       maxexptime = 1,
-                                       minsize = 1,
-                                       maxsize = 1,
-                                       collisiondetection = true,
-                                       collision_removal = true,
-                                       object_collision = false,
-                                       texture = "ichor_"..math.random(1,2)..".png",
-                                       playername = player:get_name(),
-                               })
+
+       if defined_type == "rain" then
+       curr_light = minetest.get_node_light(minetest.camera:get_pos(),0.5)
+       --rain sound effect
+       if curr_light then
+               current_node = minetest.get_node_or_nil(minetest.camera:get_pos())
+
+               if curr_light >= 15 and current_node and not liquids[current_node.name] then
+                       if not rain_sound_handle then
+                               rain_sound_handle = minetest.sound_play("rain", {loop=true,gain=0})
                        end
+                       minetest.sound_fade(rain_sound_handle, 0.5, 1)
+               elseif rain_sound_handle then
+                       minetest.sound_fade(rain_sound_handle, -0.5, 0)
+                       rain_sound_handle = nil
                end
        end
-end
 
-local spawn_rain = function(player)
-       local pos = player:get_pos()
-       local radius = 10
-       local particle_table = {}
-       
-       local area = vector.new(10,10,10)
-       
-       local min = vector.subtract(pos, area)
-       local max = vector.add(pos, area)
-       
-       
-       local area_index = minetest.find_nodes_in_area_under_air(min, max, all_nodes)
-       
-       local spawn_table = {}
-       --find the highest y value
-       for _,index in pairs(area_index) do
-               if not spawn_table[index.x] then spawn_table[index.x] = {} end
-               if not spawn_table[index.x][index.z] then
-                       spawn_table[index.x][index.z] = index.y
-               elseif spawn_table[index.x][index.z] < index.y then
-                       spawn_table[index.x][index.z] = index.y
-               end
+       particle_table = {
+               amount = 3,
+               time = 0.5,
+               minvel = {x=0, y=-30, z=0},
+               maxvel = {x=0, y=-30, z=0},
+               minacc = {x=0, y=0, z=0},
+               maxacc = {x=0, y=0, z=0},
+               minexptime = 0.5,
+               maxexptime = 0.5,
+               minsize = 4,
+               maxsize = 4,
+               collisiondetection = true,
+               collision_removal = true,
+               object_collision = false,
+               vertical = true,
+               texture = "raindrop.png^[opacity:80",
+       }
+       elseif defined_type == "snow" then
+       particle_table = {
+               amount = 1,
+               time = 0.5,
+               minvel = {x=-0.2, y=-0.2, z=-0.2},
+               maxvel = {x=0.2, y=-0.5, z=0.2},
+               minacc = {x=0, y=0, z=0},
+               maxacc = {x=0, y=0, z=0},
+               minexptime = 1,
+               maxexptime = 1,
+               minsize = 1,
+               maxsize = 1,
+               collisiondetection = true,
+               collision_removal = true,
+               object_collision = false,
+               texture = "snowflake_"..math.random(1,2)..".png",
+       }
+       elseif defined_type == "ichor" then
+       particle_table = {
+               amount = 1,
+               time = 0.5,
+               minvel = {x=-0.2, y=0.2, z=-0.2},
+               maxvel = {x=0.2, y=0.5, z=0.2},
+               minacc = {x=0, y=0, z=0},
+               maxacc = {x=0, y=0, z=0},
+               minexptime = 1,
+               maxexptime = 1,
+               minsize = 1,
+               maxsize = 1,
+               collisiondetection = true,
+               collision_removal = true,
+               object_collision = false,
+               texture = "ichor_"..math.random(1,2)..".png",
+       }
        end
-       
-       for x,x_index in pairs(spawn_table) do
-               for z,y in pairs(x_index) do
-                       if minetest.get_node_or_nil(vector.new(x,y+1,z)) ~= nil then
-                               local pos = vector.new(x,y+1,z)
-                               local lightlevel = minetest.get_node_light(pos, 0.5)
-                               if lightlevel >= 14 then
-                                       minetest.add_particlespawner({
-                                               amount = 3,
-                                               time = 0.5,
-                                               minpos = vector.new(x-0.5,y,z-0.5),
-                                               maxpos = vector.new(x+0.5,y+20,z+0.5),
-                                               minvel = {x=0, y=-20, z=0},
-                                               maxvel = {x=0, y=-20, z=0},
-                                               minacc = {x=0, y=0, z=0},
-                                               maxacc = {x=0, y=0, z=0},
-                                               minexptime = 1,
-                                               maxexptime = 2,
-                                               minsize = 4,
-                                               maxsize = 4,
-                                               collisiondetection = true,
-                                               collision_removal = true,
-                                               object_collision = false,
-                                               vertical = true,
-                                               texture = "raindrop.png^[opacity:80",
-                                               playername = player:get_name(),
-                                       })
+
+
+       for x = min.x,max.x do
+               for z = min.z,max.z do
+                       if distance({x=x,y=0,z=z},{x=pos.x,y=0,z=pos.z}) <= 10 then
+                               y = pos.y - 5
+                               if spawn_table[x] and spawn_table[x][z] then
+                                       y = spawn_table[x][z]
+                               end
+                               if minetest.get_node_or_nil(vector.new(x,y+1,z)) ~= nil then
+                                       lightlevel = minetest.get_node_light(vector.new(x,y+1,z), 0.5)
+                                       if lightlevel >= 14 or defined_type == "ichor" then
+
+                                               particle_table.minpos = vector.new(x-0.5,y,z-0.5)
+                                               particle_table.maxpos = vector.new(x+0.5,y+20,z+0.5)
+
+                                               null = minetest.add_particlespawner(particle_table)
+                                       end
                                end
                        end
                end
        end
 end
 
+
+
+
 --client runs through spawning weather particles
 local player_pos
+local current_node
 local function update_weather()
        player_pos = minetest.localplayer:get_pos()
        if do_effects then
                if snow or rain then
-                       --do normal weather
-                       if player_pos.y > -10033 then
-                               if snow == true then
-                                       spawn_snow(minetest.localplayer)
-                               elseif rain == true then
-                                       spawn_rain(minetest.localplayer)
-                               end
-                       --rain blood upwards in the nether
-                       else
-                               if snow == true or rain == true then
-                                       spawn_ichor(minetest.localplayer)
-                               end
-                       
-                               --stop the rain sound effect
-                               if rain_sound_handle then
-                                       minetest.sound_fade(rain_sound_handle, -0.5, 0)
-                                       rain_sound_handle = nil
+                       current_node = minetest.get_node_or_nil(minetest.camera:get_pos())
+                       if current_node and not liquids[current_node.name] then
+                               --do normal weather
+                               if player_pos.y > -10033 then
+                                       if snow == true then
+                                               weather_effects(minetest.localplayer, "snow")
+                                       elseif rain == true then
+                                               weather_effects(minetest.localplayer, "rain")
+                                       end
+                               --rain blood upwards in the nether
+                               else
+                                       if snow == true or rain == true then
+                                               weather_effects(minetest.localplayer, "ichor")
+                                       end
+                               
+                                       --stop the rain sound effect
+                                       if rain_sound_handle then
+                                               minetest.sound_fade(rain_sound_handle, -0.5, 0)
+                                               rain_sound_handle = nil
+                                       end
                                end
+                       elseif rain_sound_handle then
+                               minetest.sound_fade(rain_sound_handle, -0.5, 0)
+                               rain_sound_handle = nil
                        end
                end
        end
+
+       if not rain and rain_sound_handle then
+               minetest.sound_fade(rain_sound_handle, -0.5, 0)
+               rain_sound_handle = nil
+       end
        --do again every half second
        minetest.after(0.5, function()
                update_weather()
        end)
 end
 
-
-
 minetest.register_on_modchannel_message(function(channel_name, sender, message)
        --receive the initial packet which tells the client which nodes
        --to spawn weather columns on
-       if channel_name == "weather_nodes" then
+       if sender == "" and channel_name == "weather_nodes" then
                all_nodes = minetest.deserialize(message)
+               nodes = {}
+               for _,key in pairs(all_nodes) do
+                       nodes[key] = true
+               end
                do_effects = true
                weather:leave() --leave the channel
        end
        --receive the weather type
-       if channel_name == "weather_type" then
+       if sender == "" and channel_name == "weather_type" then
                if message == "1" then
                        rain = false
                        snow = true
@@ -226,14 +223,6 @@ minetest.register_on_modchannel_message(function(channel_name, sender, message)
                        snow = false
                end
        end
-       --rain sound effect
-       if not rain_sound_handle and rain == true then
-               rain_sound_handle = minetest.sound_play("rain", {loop=true,gain=0})
-               minetest.sound_fade(rain_sound_handle, 0.5, 0.5)
-       elseif rain_sound_handle and rain == false then
-               minetest.sound_fade(rain_sound_handle, -0.5, 0)
-               rain_sound_handle = nil
-       end
 end)