Add rainy weather support and storm_clouds sky

This commit is contained in:
Wuzzy 2024-08-06 13:29:41 +02:00
parent 90d008effe
commit 9f933f4cbb
6 changed files with 262 additions and 1 deletions

View File

@ -24,6 +24,7 @@ All levels by Wuzzy.
- Water, wood, tree, stone, tools, hand, gold block, wooden chest, locked wooden chest, ship lightbox, player textures, crates, seaweed, purple coral, crab grass, fire, candle (standing, wall, wield) come from “PixelBOX” texture pack by jp (CC0)
- Hanging candle by Wuzzy (CC0)
- Raindrop by Wuzzy (CC0)
- Textures in `lzr_decor` mod made by jp (CC0)
- Barricade, dark chest made by jp (CC0)
- Skulls by Mikita "rudzik8" Wiśniewski (CC BY-SA 3.0)

View File

@ -29,6 +29,9 @@ local TIMEOFDAY_NIGHT_END = 0.15
-- Check the timeofday to reset every this many seconds
local TIMEOFDAY_RESET_TIME = 5.0
-- True if the special lightning sky is currently acitve
local lightning_active = false
-- Currently active sky
local current_sky
@ -87,12 +90,27 @@ function lzr_sky.set_sky(skyname)
reset_timeofday(skyname)
local skyskydef = table.copy(skydef.sky)
if lightning_active and skyskydef.sky_color then
-- Lightning takes precedence on the sky color.
-- When the lightning is over, the real sky
-- color is applied.
skyskydef.sky_color.type = nil
skyskydef.sky_color.day_sky = nil
skyskydef.sky_color.day_horizon = nil
skyskydef.sky_color.dawn_sky = nil
skyskydef.sky_color.dawn_horizon = nil
skyskydef.sky_color.night_sky = nil
skyskydef.sky_color.night_horizon = nil
end
player:set_sky(skyskydef)
player:set_clouds(skydef.clouds)
player:set_sun(skydef.sun)
player:set_moon(skydef.moon)
player:set_stars(skydef.stars)
player:override_day_night_ratio(skydef.day_night_ratio)
-- Lightning takes precendence for day night ratio
if not lightning_active then
player:override_day_night_ratio(skydef.day_night_ratio)
end
-- Remember skyname for later
current_sky = skyname
@ -104,6 +122,34 @@ function lzr_sky.get_sky()
return current_sky
end
function lzr_sky.get_lightning()
return lightning_active
end
function lzr_sky.set_lightning(active)
local player = minetest.get_player_by_name("singleplayer")
if active then
-- Activate flash
lightning_active = true
player:override_day_night_ratio(1)
player:set_sky({
type = "plain",
base_color = "#ffffff",
})
minetest.log("info", "[lzr_sky] Lightning activated!")
else
-- Deactivate flash
lightning_active = false
local skydef = registered_skies[current_sky]
-- (Re-)Apply the sky and day/night ratio of the current sky
if skydef then
player:set_sky(skydef.sky)
end
player:override_day_night_ratio(skydef.day_night_ratio)
minetest.log("verbose", "[lzr_sky] Lightning deactivated!")
end
end
-- Regularily check if the timeofday falls into the permissble range
-- of timeofday values for the current sky and if not, reset
-- it. This code is a workaround for the fact we cannot yet
@ -135,6 +181,7 @@ end)
register_sky("bright_blue", {
sky = {
type = "regular",
sky_color = {
day_sky="#3d4caa",
day_horizon="#55aaff",
@ -155,6 +202,7 @@ register_sky("bright_blue", {
})
register_sky("tropical_dawn", {
sky = {
type = "regular",
sky_color = {
day_sky="#d20000",
day_horizon="#ff6c09",
@ -176,6 +224,7 @@ register_sky("tropical_dawn", {
})
register_sky("ocean_evening", {
sky = {
type = "regular",
sky_color = {
day_sky="#3d374d",
day_horizon="#5a2a34",
@ -201,6 +250,7 @@ register_sky("ocean_evening", {
})
register_sky("ocean_morning", {
sky = {
type = "regular",
sky_color = {
day_sky="#5184a2",
day_horizon="#ffb754",
@ -222,6 +272,7 @@ register_sky("ocean_morning", {
})
register_sky("ominous_fog", {
sky = {
type = "regular",
sky_color = {
day_sky="#e7deff",
day_horizon="#e1deff",
@ -243,8 +294,34 @@ register_sky("ominous_fog", {
timeofday_start = TIMEOFDAY_DAY_START,
timeofday_end = TIMEOFDAY_DAY_END,
})
register_sky("storm_clouds", {
sky = {
type = "regular",
sky_color = {
day_sky="#808080",
day_horizon="#808080",
},
fog = {
fog_distance = 60,
fog_start = 0.2,
},
},
clouds = {
height = 100,
thickness = 40,
density = 0.7,
color = "#808080aa",
},
stars = { visible = false },
sun = { visible = false, sunrise_visible = false },
moon = { visible = false },
timeofday_start = TIMEOFDAY_DAY_START,
timeofday_end = TIMEOFDAY_DAY_END,
day_night_ratio = 0.7,
})
register_sky("starry_night", {
sky = {
type = "regular",
sky_color = {
day_sky="#000020",
day_horizon="#000020",

27
mods/lzr_weather/API.md Normal file
View File

@ -0,0 +1,27 @@
# `lzr_weather` API
This mod adds rain and lightning. The weather can *only* be changed by API calls.
Weather is independent from the sky, and no sound effects are included;
those are supposed to be done by other mods.
## Weather types
The following weather types are available:
* `"clear"`: Clear weather (does nothing)
* `"drizzle"`: Light rain
* `"rain"`: Medium rain
* `"storm"`: Heavy rain and occassional lightning
## Functions
The following functions are available:
### `lzr_weather.get_weather()`
Returns the current weather as a string.
### `lzr_weather.set_weather(weather_type)`
Set the weather to the specified weather type.

154
mods/lzr_weather/init.lua Normal file
View File

@ -0,0 +1,154 @@
-- 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
-- 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
)

View File

@ -0,0 +1,2 @@
name = lzr_weather
depends = lzr_globals, lzr_sky

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 B