351 lines
9.8 KiB
Lua
351 lines
9.8 KiB
Lua
--[[
|
|
when updating check if the modified node is below the current entity position
|
|
|
|
or when dug check if below
|
|
|
|
when placed check if above
|
|
|
|
if finding node fails and player is under direct sunlight then
|
|
do weather effects with the y pos half way down the column of the weather particle spawner
|
|
|
|
|
|
|
|
--add all nodes to node list
|
|
local all_nodes = {}
|
|
minetest.register_on_mods_loaded(function()
|
|
for name in pairs(minetest.registered_nodes) do
|
|
if name ~= "air" and name ~= "ignore" then
|
|
table.insert(all_nodes,name)
|
|
end
|
|
end
|
|
end)
|
|
|
|
local spawn_weather = function(player)
|
|
local pos = player:get_pos()
|
|
local radius = 10
|
|
local meta = player:get_meta()
|
|
local particle_table = {}
|
|
|
|
local min = vector.subtract(pos, 10)
|
|
local max = vector.add(pos, 10)
|
|
|
|
|
|
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
|
|
local lightlevel = minetest.get_node_light(vector.new(x,y+1,z), 0.5)
|
|
--print(lightlevel)
|
|
if lightlevel >= 14 then
|
|
--minetest.add_item(vector.new(x,y+1,z),ItemStack("main:glass"))
|
|
--local node_list = minetest.find_nodes_in_area_under_air(vector.new(pos.x+x,pos.y-10,pos.z+z), vector.new(pos.x+x,pos.y+10,pos.z+z), all_nodes)
|
|
--print(dump(minetest.registered_nodes))
|
|
|
|
if math.random() > 0.995 then
|
|
--make it so buildable to nodes get replaced
|
|
local node = minetest.get_node(vector.new(x,y,z)).name
|
|
local buildable = minetest.registered_nodes[node].buildable_to
|
|
local walkable = minetest.registered_nodes[node].walkable
|
|
local liquid = (minetest.registered_nodes[node].liquidtype ~= "none")
|
|
|
|
if not liquid then
|
|
if not buildable and minetest.get_node(vector.new(x,y+1,z)).name ~= "weather:snow" and walkable == true then
|
|
minetest.set_node(vector.new(x,y+1,z),{name="weather:snow"})
|
|
elseif buildable == true and minetest.get_node(vector.new(x,y,z)).name ~= "weather:snow" then
|
|
minetest.set_node(vector.new(x,y,z),{name="weather:snow"})
|
|
end
|
|
end
|
|
end
|
|
|
|
local id = minetest.add_particlespawner({
|
|
amount = 2,
|
|
-- Number of particles spawned over the time period `time`.
|
|
|
|
time = 0,
|
|
-- Lifespan of spawner in seconds.
|
|
-- If time is 0 spawner has infinite lifespan and spawns the `amount` on
|
|
-- a per-second basis.
|
|
|
|
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,
|
|
-- The particles' properties are random values between the min and max
|
|
-- values.
|
|
-- pos, velocity, acceleration, expirationtime, size
|
|
|
|
collisiondetection = true,
|
|
-- If true collide with `walkable` nodes and, depending on the
|
|
-- `object_collision` field, objects too.
|
|
|
|
collision_removal = true,
|
|
-- If true particles are removed when they collide.
|
|
-- Requires collisiondetection = true to have any effect.
|
|
|
|
object_collision = false,
|
|
-- If true particles collide with objects that are defined as
|
|
-- `physical = true,` and `collide_with_objects = true,`.
|
|
-- Requires collisiondetection = true to have any effect.
|
|
|
|
--attached = ObjectRef,
|
|
-- If defined, particle positions, velocities and accelerations are
|
|
-- relative to this object's position and yaw
|
|
|
|
--vertical = false,
|
|
-- If true face player using y axis only
|
|
|
|
texture = "snowflake_"..math.random(1,2)..".png",
|
|
|
|
playername = player:get_player_name(),
|
|
-- Optional, if specified spawns particles only on the player's client
|
|
|
|
--animation = {Tile Animation definition},
|
|
-- Optional, specifies how to animate the particles' texture
|
|
|
|
--glow = 0
|
|
-- Optional, specify particle self-luminescence in darkness.
|
|
-- Values 0-14.
|
|
})
|
|
table.insert(particle_table,id)
|
|
end
|
|
end
|
|
end
|
|
meta:set_string("id table",minetest.serialize(particle_table))
|
|
end
|
|
|
|
--handle weather effects on players when joining
|
|
minetest.register_on_joinplayer(function(player)
|
|
minetest.after(2, function(player)
|
|
spawn_weather(player)
|
|
end,player)
|
|
player:set_sky({
|
|
base_color="#808080",
|
|
type="plain",
|
|
clouds=false,
|
|
|
|
day_sky = "#808080",
|
|
dawn_horizon = "#808080",
|
|
dawn_sky = "#808080",
|
|
fog_sun_tint = "#808080",
|
|
|
|
night_sky="#000000",
|
|
night_horizon="#000000"
|
|
})
|
|
player:set_sun({visible=false})
|
|
player:set_moon({visible=false})
|
|
player:set_stars({visible=false})
|
|
end)
|
|
|
|
--handle weather effects during game loop
|
|
local weather_update_timer = 0
|
|
minetest.register_globalstep(function(dtime)
|
|
weather_update_timer = weather_update_timer + dtime
|
|
if weather_update_timer > 1 then
|
|
weather_update_timer = 0
|
|
for _,player in ipairs(minetest.get_connected_players()) do
|
|
local meta = player:get_meta()
|
|
local pos = vector.round(player:get_pos())
|
|
|
|
if meta:contains("weather old pos") then
|
|
local old_pos = minetest.string_to_pos(meta:get_string("weather old pos"))
|
|
if not vector.equals(pos,old_pos) then
|
|
if meta:contains("id table") then
|
|
local particle_table = minetest.deserialize(meta:get_string("id table"))
|
|
|
|
for id in pairs(particle_table) do
|
|
minetest.delete_particlespawner(id, player:get_player_name())
|
|
end
|
|
meta:set_string("id table", nil)
|
|
end
|
|
--print("spawning weather")
|
|
spawn_weather(player)
|
|
end
|
|
end
|
|
|
|
meta:set_string("weather old pos", minetest.pos_to_string(pos))
|
|
end
|
|
end
|
|
end)
|
|
|
|
]]--
|
|
|
|
minetest.register_node("weather:snow", {
|
|
description = "Snow",
|
|
tiles = {"snow_block.png"},
|
|
groups = {soft = 1, shovel = 1, hand = 1,pathable = 1,wool=1,dirt=1,falling_node=1},
|
|
sounds = main.woolSound(),
|
|
paramtype = "light",
|
|
drawtype = "nodebox",
|
|
drop = {
|
|
max_items = 5,
|
|
items= {
|
|
{
|
|
items = {"weather:snowball"},
|
|
},
|
|
{
|
|
items = {"weather:snowball"},
|
|
},
|
|
{
|
|
items = {"weather:snowball"},
|
|
},
|
|
{
|
|
items = {"weather:snowball"},
|
|
},
|
|
{
|
|
rarity = 5,
|
|
items = {"weather:snowball"},
|
|
},
|
|
},
|
|
},
|
|
buildable_to = true,
|
|
node_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{-8/16, -8/16, -8/16, 8/16, -6/16, 8/16},
|
|
}
|
|
},
|
|
})
|
|
|
|
local snowball_throw = function(player)
|
|
local pos = player:get_pos()
|
|
pos.y = pos.y + 1.625
|
|
--let other players hear the noise too
|
|
minetest.sound_play("woosh",{to_player=player:get_player_name(), pitch = math.random(80,100)/100})
|
|
minetest.sound_play("woosh",{pos=pos, exclude_player = player:get_player_name(), pitch = math.random(80,100)/100})
|
|
local snowball = minetest.add_entity(pos,"weather:snowball")
|
|
if snowball then
|
|
local vel = player:get_player_velocity()
|
|
snowball:set_velocity(vector.add(vel,vector.multiply(player:get_look_dir(),20)))
|
|
snowball:get_luaentity().thrower = player:get_player_name()
|
|
return(true)
|
|
end
|
|
return(false)
|
|
end
|
|
|
|
minetest.register_craftitem("weather:snowball", {
|
|
description = "Snowball",
|
|
inventory_image = "snowball.png",
|
|
--stack_max = 1,
|
|
--range = 0,
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
local worked = snowball_throw(placer)
|
|
if worked then
|
|
itemstack:take_item()
|
|
end
|
|
return(itemstack)
|
|
end,
|
|
on_secondary_use = function(itemstack, user, pointed_thing)
|
|
local worked = snowball_throw(user)
|
|
if worked then
|
|
itemstack:take_item()
|
|
end
|
|
return(itemstack)
|
|
end,
|
|
})
|
|
|
|
|
|
snowball = {}
|
|
snowball.initial_properties = {
|
|
hp_max = 1,
|
|
physical = true,
|
|
collide_with_objects = false,
|
|
collisionbox = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1},
|
|
visual = "sprite",
|
|
visual_size = {x = 0.5, y = 0.5},
|
|
textures = {
|
|
"snowball.png"
|
|
},
|
|
is_visible = true,
|
|
pointable = false,
|
|
}
|
|
|
|
snowball.snowball = true
|
|
|
|
snowball.on_activate = function(self)
|
|
self.object:set_acceleration(vector.new(0,-9.81,0))
|
|
end
|
|
|
|
--make this as efficient as possible
|
|
--make it so you can hit one snowball with another
|
|
snowball.on_step = function(self, dtime)
|
|
local vel = self.object:get_velocity()
|
|
local hit = false
|
|
local pos = self.object:get_pos()
|
|
|
|
--hit object with the snowball
|
|
for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
|
|
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
|
|
object:punch(self.object, 2,
|
|
{
|
|
full_punch_interval=1.5,
|
|
damage_groups = {fleshy=0},
|
|
})
|
|
hit = true
|
|
break
|
|
end
|
|
end
|
|
|
|
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
|
|
|
|
minetest.sound_play("wool",{pos=pos, pitch = math.random(80,100)/100})
|
|
minetest.add_particlespawner({
|
|
amount = 20,
|
|
-- Number of particles spawned over the time period `time`.
|
|
|
|
time = 0.001,
|
|
-- Lifespan of spawner in seconds.
|
|
-- If time is 0 spawner has infinite lifespan and spawns the `amount` on
|
|
-- a per-second basis.
|
|
|
|
minpos = pos,
|
|
maxpos = pos,
|
|
minvel = {x=-2, y=3, z=-2},
|
|
maxvel = {x=2, y=5, z=2},
|
|
minacc = {x=0, y=-9.81, z=0},
|
|
maxacc = {x=0, y=-9.81, z=0},
|
|
minexptime = 1,
|
|
maxexptime = 3,
|
|
minsize = 1,
|
|
maxsize = 1,
|
|
-- The particles' properties are random values between the min and max
|
|
-- values.
|
|
-- pos, velocity, acceleration, expirationtime, size
|
|
|
|
collisiondetection = true,
|
|
|
|
collision_removal = true,
|
|
|
|
object_collision = false,
|
|
|
|
texture = "snowflake_"..math.random(1,2)..".png",
|
|
|
|
})
|
|
|
|
self.object:remove()
|
|
|
|
end
|
|
|
|
self.oldvel = vel
|
|
end
|
|
minetest.register_entity("weather:snowball", snowball)
|