disable weather in caves
This commit is contained in:
parent
b9aa145de3
commit
4287714cc6
|
@ -1,5 +1,6 @@
|
|||
# Weather mod for [Minetest](http://minetest.net/)
|
||||
[![luacheck][luacheck badge]][luacheck workflow]
|
||||
[![luacheck][luacheck badge]][luacheck workflow]
|
||||
[![ContentDB][ContenDB badge]][ContentDB page]
|
||||
|
||||
License:
|
||||
- Code: LGPL
|
||||
|
@ -9,3 +10,5 @@ License:
|
|||
|
||||
[luacheck badge]: https://github.com/theFox6/minetest_mod_weather/workflows/luacheck/badge.svg
|
||||
[luacheck workflow]: https://github.com/theFox6/minetest_mod_weather/actions?query=workflow%3Aluacheck
|
||||
[ContentDB badge]: https://content.minetest.net/packages/theFox/weather/shields/title/
|
||||
[ContentDB page]: https://content.minetest.net/packages/theFox/weather/
|
||||
|
|
125
weather/api.lua
125
weather/api.lua
|
@ -40,16 +40,16 @@ end
|
|||
|
||||
local default_downfall = {
|
||||
--minimum starting position
|
||||
min_pos = {x=-15, y=10, z=-15},
|
||||
min_pos = {x=-15, y=15, z=-15},
|
||||
--maximum starting position
|
||||
max_pos = {x=15, y=10, z=15},
|
||||
max_pos = {x=15, y=15, z=15},
|
||||
--y falling speed
|
||||
falling_speed = 10,
|
||||
--number of textures spawned
|
||||
amount = 15,
|
||||
--the texture size
|
||||
size = 25,
|
||||
--whether lightning schould be enabled
|
||||
--whether lightning should be enabled
|
||||
enable_lightning=false,
|
||||
--whether to damage the player
|
||||
damage_player=false,
|
||||
|
@ -71,12 +71,10 @@ local default_damage = {
|
|||
function weather_mod.register_downfall(id,def)
|
||||
local name = check_modname_prefix(id)
|
||||
if name == "none" then error("\"none\" means none, thanks") end
|
||||
if weather_mod.registered_downfalls[name]~=nil then error(name.." is already registered") end
|
||||
assert(not weather_mod.registered_downfalls[name], name.." is already registered")
|
||||
local ndef = table.copy(def)
|
||||
--what the downfall looks like
|
||||
if not ndef.texture then
|
||||
error("no texture given")
|
||||
end
|
||||
assert(ndef.texture,"no texture given")
|
||||
set_defaults(ndef,default_downfall)
|
||||
--when to delete the particles
|
||||
if not ndef.exptime then
|
||||
|
@ -110,115 +108,4 @@ function weather_mod.disable_downfall(id,disable)
|
|||
weather_mod.registered_downfalls[id].disabled = state
|
||||
end
|
||||
|
||||
if minetest.get_modpath("lightning") then
|
||||
lightning.auto = false
|
||||
--rawset(lightning,"auto",false)
|
||||
end
|
||||
|
||||
function weather_mod.handle_lightning(current_weather)
|
||||
if not minetest.get_modpath("lightning") then return end
|
||||
if not current_weather then return end
|
||||
lightning.auto = current_weather.enable_lightning
|
||||
--rawset(lightning,"auto",current_weather.enable_lightning)
|
||||
if current_weather.enable_lightning and math.random(1,2) == 1 then
|
||||
local time = math.floor(math.random(lightning.interval_low/2,lightning.interval_low))
|
||||
minetest.after(time, lightning.strike)
|
||||
end
|
||||
end
|
||||
|
||||
local do_raycasts = minetest.is_yes(minetest.settings:get_bool('raycast_hitcheck'))
|
||||
local damage_steps = 0
|
||||
|
||||
local function handle_damage(damage,player, downfall_origin)
|
||||
if not damage then return end
|
||||
damage_steps = damage_steps +1
|
||||
if damage_steps < damage.time then return end
|
||||
damage_steps = 0
|
||||
if do_raycasts then
|
||||
-- this check should be more accurate
|
||||
local hitpos = vector.add(player:get_pos(),vector.new(0,1,0))
|
||||
local ray = minetest.raycast(downfall_origin,hitpos)
|
||||
local o = ray:next()
|
||||
if o.type~="object" then return end -- hit node or something
|
||||
if not o.ref:is_player() then return end -- hit different object
|
||||
if o.ref:get_player_name() ~= player:get_player_name() then
|
||||
return --hit other player
|
||||
end
|
||||
o = ray:next()
|
||||
if o then
|
||||
minetest.log("warning","[weather] raycast hit more after hitting the player\n"..
|
||||
dump2(o,"o"))
|
||||
end
|
||||
else
|
||||
--check if player is affected by downfall, if it's dark there are nodes nearby
|
||||
if minetest.get_node_light(player:get_pos(), 0.5) ~= 15 then return end
|
||||
end
|
||||
if math.random() < damage.chance then
|
||||
player:set_hp(player:get_hp()-damage.amount)
|
||||
end
|
||||
end
|
||||
|
||||
local function weather_step()
|
||||
local current_downfall = weather_mod.registered_downfalls[weather.type]
|
||||
if current_downfall==nil then return end
|
||||
for _, player in ipairs(minetest.get_connected_players()) do
|
||||
local ppos = player:get_pos()
|
||||
|
||||
if ppos.y > 120 then return end
|
||||
|
||||
local wind_pos = vector.multiply(weather.wind,-1)
|
||||
|
||||
local minp = vector.add(vector.add(ppos, current_downfall.min_pos),wind_pos)
|
||||
local maxp = vector.add(vector.add(ppos, current_downfall.max_pos),wind_pos)
|
||||
|
||||
local vel = {x=weather.wind.x,y=-current_downfall.falling_speed,z=weather.wind.z}
|
||||
local acc = {x=0, y=0, z=0}
|
||||
|
||||
local exp = current_downfall.exptime
|
||||
|
||||
minetest.add_particlespawner({
|
||||
amount=current_downfall.amount, time=0.5,
|
||||
minpos=minp, maxpos=maxp,
|
||||
minvel=vel, maxvel=vel,
|
||||
minacc=acc, maxacc=acc,
|
||||
minexptime=exp, maxexptime=exp,
|
||||
minsize=current_downfall.size, maxsize=current_downfall.size,
|
||||
collisiondetection=true, collision_removal=true,
|
||||
vertical=true,
|
||||
texture=current_downfall.texture, playername=player:get_player_name()
|
||||
})
|
||||
|
||||
local downfall_origin = vector.divide(vector.add(minp,maxp),2)
|
||||
handle_damage(current_downfall.damage_player,player,downfall_origin)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_globalstep(function()
|
||||
if math.random(1, 10000) == 1 then
|
||||
weather.type = "none"
|
||||
if minetest.get_modpath("lightning") then
|
||||
lightning.auto = false
|
||||
--rawset(lightning,"auto",false)
|
||||
end
|
||||
weather_mod.handle_weather_change({type = "none", reason = "globalstep"})
|
||||
else
|
||||
local cnum = 10000 * weather_mod.registered_downfall_count
|
||||
for id,w in pairs(weather_mod.registered_downfalls) do
|
||||
if math.random(1, cnum) == 1 then
|
||||
weather.wind = {
|
||||
x = math.random(0,10),
|
||||
y = 0,
|
||||
z = math.random(0,10)
|
||||
}
|
||||
if (not w.disabled) and vector.length(weather.wind) >= w.min_wind then
|
||||
weather.type = id
|
||||
weather_mod.handle_lightning(w)
|
||||
weather_mod.handle_weather_change({type = id, wind = true, reason = "globalstep"})
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
weather_step()
|
||||
end)
|
||||
return weather_mod
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
if minetest.get_modpath("lightning") then
|
||||
lightning.auto = false
|
||||
--rawset(lightning,"auto",false)
|
||||
end
|
||||
|
||||
function weather_mod.handle_lightning(current_weather)
|
||||
if not minetest.get_modpath("lightning") then return end
|
||||
if not current_weather then return end
|
||||
lightning.auto = current_weather.enable_lightning
|
||||
--rawset(lightning,"auto",current_weather.enable_lightning)
|
||||
if current_weather.enable_lightning and math.random(1,2) == 1 then
|
||||
local time = math.floor(math.random(lightning.interval_low/2,lightning.interval_low))
|
||||
minetest.after(time, lightning.strike)
|
||||
end
|
||||
end
|
||||
|
||||
local do_raycasts = minetest.is_yes(minetest.settings:get_bool('raycast_hitcheck'))
|
||||
local check_light = minetest.is_yes(minetest.settings:get_bool('light_roofcheck',true))
|
||||
local damage_steps = 0
|
||||
|
||||
local function handle_damage(damage,player, downfall_origin)
|
||||
if not damage then return end
|
||||
damage_steps = damage_steps +1
|
||||
if damage_steps < damage.time then return end
|
||||
damage_steps = 0
|
||||
if do_raycasts then
|
||||
-- this check should be more accurate
|
||||
local hitpos = vector.add(player:get_pos(),vector.new(0,1,0))
|
||||
local ray = minetest.raycast(downfall_origin,hitpos)
|
||||
local o = ray:next()
|
||||
if o.type~="object" then return end -- hit node or something
|
||||
if not o.ref:is_player() then return end -- hit different object
|
||||
if o.ref:get_player_name() ~= player:get_player_name() then
|
||||
return --hit other player
|
||||
end
|
||||
o = ray:next()
|
||||
if o then
|
||||
minetest.log("warning","[weather] raycast hit more after hitting the player\n"..
|
||||
dump2(o,"o"))
|
||||
end
|
||||
else
|
||||
--check if player is affected by downfall, if it's dark there are nodes nearby
|
||||
if minetest.get_node_light(player:get_pos(), 0.5) ~= 15 then return end
|
||||
end
|
||||
if math.random() < damage.chance then
|
||||
player:set_hp(player:get_hp()-damage.amount)
|
||||
end
|
||||
end
|
||||
|
||||
local function has_light(minp,maxp)
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local e1, e2 = manip:read_from_map(minp, maxp)
|
||||
local area = VoxelArea:new{MinEdge=e1, MaxEdge=e2}
|
||||
local data = manip:get_light_data()
|
||||
|
||||
local node_num = 0
|
||||
local light = false
|
||||
|
||||
for i in area:iterp(minp, maxp) do
|
||||
node_num = node_num + 1
|
||||
if node_num < 5 then
|
||||
if data[i] and data[i] == 15 then
|
||||
light = true
|
||||
break
|
||||
end
|
||||
else
|
||||
node_num = 0
|
||||
end
|
||||
end
|
||||
|
||||
return light
|
||||
end
|
||||
|
||||
local function weather_step()
|
||||
local current_downfall = weather_mod.registered_downfalls[weather.type]
|
||||
if current_downfall==nil then return end
|
||||
for _, player in ipairs(minetest.get_connected_players()) do
|
||||
local ppos = player:get_pos()
|
||||
|
||||
if ppos.y > 120 then return end
|
||||
|
||||
local wind_pos = vector.multiply(weather.wind,-1)
|
||||
|
||||
local minp = vector.add(vector.add(ppos, current_downfall.min_pos),wind_pos)
|
||||
local maxp = vector.add(vector.add(ppos, current_downfall.max_pos),wind_pos)
|
||||
|
||||
if check_light and not has_light(minp,maxp) then return end
|
||||
|
||||
local vel = {x=weather.wind.x,y=-current_downfall.falling_speed,z=weather.wind.z}
|
||||
local acc = {x=0, y=0, z=0}
|
||||
|
||||
local exp = current_downfall.exptime
|
||||
|
||||
minetest.add_particlespawner({
|
||||
amount=current_downfall.amount, time=0.5,
|
||||
minpos=minp, maxpos=maxp,
|
||||
minvel=vel, maxvel=vel,
|
||||
minacc=acc, maxacc=acc,
|
||||
minexptime=exp, maxexptime=exp,
|
||||
minsize=current_downfall.size, maxsize=current_downfall.size,
|
||||
collisiondetection=true, collision_removal=true,
|
||||
vertical=true,
|
||||
texture=current_downfall.texture, playername=player:get_player_name()
|
||||
})
|
||||
|
||||
local downfall_origin = vector.divide(vector.add(minp,maxp),2)
|
||||
handle_damage(current_downfall.damage_player,player,downfall_origin)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_globalstep(function()
|
||||
if math.random(1, 10000) == 1 then
|
||||
weather.type = "none"
|
||||
if minetest.get_modpath("lightning") then
|
||||
lightning.auto = false
|
||||
--rawset(lightning,"auto",false)
|
||||
end
|
||||
weather_mod.handle_weather_change({type = "none", reason = "globalstep"})
|
||||
else
|
||||
local cnum = 10000 * weather_mod.registered_downfall_count
|
||||
for id,w in pairs(weather_mod.registered_downfalls) do
|
||||
if math.random(1, cnum) == 1 then
|
||||
weather.wind = {
|
||||
x = math.random(0,10),
|
||||
y = 0,
|
||||
z = math.random(0,10)
|
||||
}
|
||||
if (not w.disabled) and vector.length(weather.wind) >= w.min_wind then
|
||||
weather.type = id
|
||||
weather_mod.handle_lightning(w)
|
||||
weather_mod.handle_weather_change({type = id, wind = true, reason = "globalstep"})
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
weather_step()
|
||||
end)
|
|
@ -31,6 +31,7 @@ weather = (function()
|
|||
end) ()
|
||||
|
||||
dofile(weather_mod.modpath.."/api.lua")
|
||||
dofile(weather_mod.modpath.."/engine.lua")
|
||||
dofile(weather_mod.modpath.."/rain.lua")
|
||||
dofile(weather_mod.modpath.."/sand.lua")
|
||||
dofile(weather_mod.modpath.."/snow.lua")
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
-- Rain
|
||||
weather_mod.register_downfall("weather:rain",{
|
||||
min_pos = {x=-15, y=7, z=-15},
|
||||
max_pos = {x= 15, y=7, z= 15},
|
||||
min_pos = {x=-15, y=10, z=-15},
|
||||
max_pos = {x= 15, y=10, z= 15},
|
||||
falling_speed=10,
|
||||
amount=25,
|
||||
exptime=0.8,
|
||||
exptime=1,
|
||||
size=25,
|
||||
texture="weather_rain.png",
|
||||
enable_lightning=true,
|
||||
})
|
||||
|
||||
weather_mod.register_downfall("weather:storm",{
|
||||
min_pos = {x = -15, y = 7, z = -15},
|
||||
max_pos = {x = 15, y = 7, z = 15},
|
||||
min_pos = {x = -15, y = 10, z = -15},
|
||||
max_pos = {x = 15, y = 10, z = 15},
|
||||
falling_speed = 10,
|
||||
amount = 30,
|
||||
exptime = 0.8,
|
||||
exptime = 1,
|
||||
size = 30,
|
||||
texture = "weather_rain_dark.png",
|
||||
enable_lightning = true,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
weather_mod.register_downfall("weather:sandstorm",{
|
||||
min_pos = {x=-20, y=0, z=-20},
|
||||
max_pos = {x= 20, y=2, z= 20},
|
||||
min_pos = {x=-20, y=-4, z=-20},
|
||||
max_pos = {x= 20, y=4, z= 20},
|
||||
falling_speed=-1,
|
||||
amount=20,
|
||||
amount=40,
|
||||
exptime=1,
|
||||
size=25,
|
||||
texture="weather_sand.png",
|
||||
|
|
|
@ -16,3 +16,13 @@ snow_covers_abm (Snow covers for fast PCs) bool false
|
|||
# The raycasts only effect is that they also check the wind
|
||||
# direction. This might cause the performance to drop though.
|
||||
raycast_hitcheck (Raycast hitchecks for fast PCs) bool false
|
||||
|
||||
# Light Roof Check
|
||||
#
|
||||
# This setting controls if light data from the VoxelManipulator is
|
||||
# used to check if the player is under a roof and cannot see the downfall.
|
||||
# If disabled the weather may appear in caves and under other high roofs.
|
||||
# If enabled it may have an impact on the performance of a server.
|
||||
# The light checks are made in the areas around each player.
|
||||
# Hence it will cost more performance the more players are on a server.
|
||||
light_roofcheck (Light Roof Check for fast PCs) bool true
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
-- Snow
|
||||
weather_mod.register_downfall("weather:snow",{
|
||||
min_pos = {x=-15, y=7, z=-15},
|
||||
max_pos = {x= 15, y=7, z= 15},
|
||||
min_pos = {x=-15, y=10, z=-15},
|
||||
max_pos = {x= 15, y=10, z= 15},
|
||||
falling_speed=5,
|
||||
amount=15,
|
||||
exptime=5,
|
||||
exptime=7,
|
||||
size=25,
|
||||
texture="weather_snow.png",
|
||||
})
|
||||
|
||||
weather_mod.register_downfall("weather:hail",{
|
||||
min_pos = {x=-15, y=7, z=-15},
|
||||
max_pos = {x= 15, y=7, z= 15},
|
||||
min_pos = {x=-15, y=10, z=-15},
|
||||
max_pos = {x= 15, y=10, z= 15},
|
||||
falling_speed=25,
|
||||
amount=15,
|
||||
exptime=0.8,
|
||||
exptime=1,
|
||||
size=25,
|
||||
texture="weather_hail.png",
|
||||
enable_lightning = true,
|
||||
|
|
Loading…
Reference in New Issue