2024-08-06 14:14:46 +02:00

168 lines
4.2 KiB
Lua

-- Weather mod for Lazarr!
-- It features rain and lightning.
-- Lightning is handled by lzr_sky.
lzr_weather = {}
local RAIN_RESPAWN = 5
local LIGHTNING_TIMER_MIN = 1
local LIGHTNING_TIMER_MAX = 35
local LIGHTNING_DURATION = 0.1
-- local weather variables
local current_weather = "clear"
local weather_types = {
"clear",
"drizzle",
"rain",
"storm"
}
local lightning_pr = PseudoRandom(4291990 + minetest.get_us_time())
local last_particlespawner
local rain_timer = RAIN_RESPAWN
local lightning_timer = 0
local next_lightning_at = nil
-- Returns the current weather
function lzr_weather.get_weather()
return current_weather
end
function lzr_weather.get_weathers()
return weather_types
end
function lzr_weather.weather_exists(weather)
for w=1, #weather_types do
if weather_types[w] == weather then
return true
end
end
return false
end
-- Set the current weather
function lzr_weather.set_weather(weather)
current_weather = weather
rain_timer = RAIN_RESPAWN
lightning_timer = 0
if last_particlespawner then
minetest.delete_particlespawner(last_particlespawner)
end
end
minetest.register_globalstep(
function(dtime)
-- Clear weather: Nothing to do
local state = lzr_gamestate.get_state()
if current_weather == "clear" then
return
end
-- Storm weather: Occasional lightning
if current_weather == "storm" then
lightning_timer = lightning_timer + dtime
-- Lightning active: turn off lightning sky after LIGHTNING_DURATION
if lzr_sky.get_lightning() == true then
if lightning_timer >= LIGHTNING_DURATION then
lzr_sky.set_lightning(false)
lightning_timer = 0
end
-- Lightning inactive: turn on lightning sky after a random time
else
if not next_lightning_at then
next_lightning_at = lightning_pr:next(LIGHTNING_TIMER_MIN, LIGHTNING_TIMER_MAX)
end
if lightning_timer >= next_lightning_at then
-- Note: The lightning sky remains active until we manually disable it
lzr_sky.set_lightning(true)
lightning_timer = 0
next_lightning_at = lightning_pr:next(LIGHTNING_TIMER_MIN, LIGHTNING_TIMER_MAX)
end
end
end
rain_timer = rain_timer + dtime
if rain_timer < RAIN_RESPAWN then
return
end
rain_timer = 0
-- Rainy weather: Spawn rain particles
local amount, fall_speed, min_size, max_size
if current_weather == "drizzle" then
amount = 200
fall_speed = 15
min_size = 1.8
max_size = 1.9
elseif current_weather == "rain" then
amount = 600
fall_speed = 16
min_size = 2.3
max_size = 2.6
elseif current_weather == "storm" then
amount = 1500
fall_speed = 20
min_size = 2.6
max_size = 3.0
else
return
end
local XZ_BUFFER = 4
local Y_BUFFER = 3
local spawn_min, spawn_max
if lzr_gamestate.get_state() == lzr_gamestate.MENU then
-- Weather at the "main menu ship" proably needs more work
spawn_min = {
x = lzr_globals.MENU_SHIP_POS.x - XZ_BUFFER,
y = lzr_globals.MENU_SHIP_POS.y + 20,
z = lzr_globals.MENU_SHIP_POS.z - XZ_BUFFER,
}
spawn_max = {
x = lzr_globals.MENU_SHIP_POS.x + XZ_BUFFER + 20,
y = lzr_globals.MENU_SHIP_POS.y + 20,
z = lzr_globals.MENU_SHIP_POS.z + XZ_BUFFER + 35,
}
else
spawn_min = {
x = lzr_globals.PLAYFIELD_START.x - XZ_BUFFER,
y = lzr_globals.PLAYFIELD_START.y + lzr_globals.PLAYFIELD_SIZE.y + Y_BUFFER,
z = lzr_globals.PLAYFIELD_START.z - XZ_BUFFER,
}
spawn_max = {
x = lzr_globals.PLAYFIELD_START.x + lzr_globals.PLAYFIELD_SIZE.x + XZ_BUFFER,
y = lzr_globals.PLAYFIELD_START.y + lzr_globals.PLAYFIELD_SIZE.y + Y_BUFFER,
z = lzr_globals.PLAYFIELD_START.z + lzr_globals.PLAYFIELD_SIZE.z + XZ_BUFFER,
}
end
-- Don't spawn particles if area is not loaded yet
if minetest.get_node_or_nil(spawn_min) == nil or minetest.get_node_or_nil(spawn_max) == nil then
return
end
last_particlespawner = minetest.add_particlespawner({
amount = amount,
time = RAIN_RESPAWN,
minpos = spawn_min,
maxpos = spawn_max,
minvel = {x = 0, y = -fall_speed, z = 0},
maxvel = {x = 0, y = -fall_speed, z = 0},
minexptime = 3,
maxexptime = 3,
minsize = min_size,
maxsize = max_size,
collisiondetection = true,
collision_removal = true,
vertical = true,
texture = "lzr_weather_rain.png",
})
end
)