Implement dynamic cloud sizes, adjust cycle lengths

This commit is contained in:
Till Affeldt 2020-04-13 16:53:32 +02:00
parent 47530bb07e
commit fdc457bd09
9 changed files with 86 additions and 24 deletions

12
TODO.md
View File

@ -1,12 +1,8 @@
# TODO
## Required for MVP
- Fix obvious bugs that prevent weathers from being selected
- Test if day progression works
- Test non-random heat and humidity values
- Fix noise function
- Implement sounds
- Test if sky changes are working
- Re-implement sounds into new engine
- Implement start/end events
- Make sure all weather presets are working
- Implement chat commands
@ -20,13 +16,17 @@
- Add license information to source files
- Write helpful README
- Find good values for weather conditions
- Make switches between effects more smooth
- Set effects on player join
## Nice to have
- Write documentation on how to add weathers and effects
- Register *Moon Phases* as a weather preset using the *skybox* effect
- Assign meta data (like "downfall", "wind", etc.) to weather presets
- Fog effects
- Optimize performance by replacing some particles with animated texture planes
- Make switches between effects more smooth
- Adjust size of particle boxes based on player speed
- Ability to register environment conditions dynamically (like the heat)
## Future Plans & Ideas
- Complete season system

54
ca_effects/clouds.lua Normal file
View File

@ -0,0 +1,54 @@
if not climate_mod.settings.skybox then return end
if not minetest.get_modpath("skylayer") then return end
local SKYBOX_NAME = "climate_api:clouds"
local function set_clouds(player, clouds)
sky = { name = SKYBOX_NAME, cloud_data = clouds }
skylayer.add_layer(player:get_player_name(), sky)
end
local function remove_cloud_layer(player)
skylayer.remove_layer(player:get_player_name(), SKYBOX_NAME)
end
local function accumulate(current, incoming, fn)
if type(incoming) ~= "nil" and type(current) == "nil" then
return incoming
elseif type(incoming) ~= "nil" then
return fn(current, incoming)
end
return current
end
local function handle_effect(player_data)
for playername, data in pairs(player_data) do
local player = minetest.get_player_by_name(playername)
local data = player.get_meta()
local current_size = data.get_float("climate_api:cloud_size")
local current_speed_x = data.get_float("climate_api:cloud_speed_x")
local current_speed_z = data.get_float("climate_api:cloud_speed_z")
local clouds = {}
for weather, value in pairs(data) do
clouds.size = accumulate(clouds.size, data.size, function(a, b) return a * b end)
clouds.speed = accumulate(clouds.speed, data.speed, vector.multiply)
if type(data.color) ~= "nil" then
clouds.color = data.color
end
end
set_clouds(player, clouds)
end
end
local function remove_effect(player_data)
for playername, data in ipairs(player_data) do
local player = minetest.get_player_by_name(playername)
remove_cloud_layer(player)
end
end
climate_api.register_effect("climate_api:clouds", handle_effect, "tick")
climate_api.register_effect("climate_api:clouds", remove_effect, "end")
climate_api.set_effect_cycle("climate_api:clouds", climate_api.LONG_CYCLE)

View File

@ -11,4 +11,4 @@ local function update_effect(player_data)
end
climate_api.register_effect("climate_api:sound", update_effect, "change")
climate_api.set_effect_cycle("climate_api:skybox", climate_api.LONG_CYCLE)
climate_api.set_effect_cycle("climate_api:skybox", climate_api.MEDIUM_CYCLE)

View File

@ -42,3 +42,4 @@ dofile(modpath.."/lib/main.lua")
-- import predefined environment effects
dofile(modpath .. "/ca_effects/particles.lua")
dofile(modpath .. "/ca_effects/skybox.lua")
dofile(modpath .. "/ca_effects/clouds.lua")

View File

@ -2,7 +2,8 @@ local api = {}
api.SHORT_CYCLE = 0.03 -- for particles and fast animations
api.DEFAULT_CYCLE = 0.1 -- for most effect types
api.LONG_CYCLE = 0.5 -- for write operations and skybox changes
api.MEDIUM_CYCKE = 2.0 -- for ressource intensive tasks
api.LONG_CYCLE = 5.0 -- for write operations and skybox changes
climate_mod.weathers = {}
climate_mod.effects = {}

View File

@ -22,7 +22,7 @@ function utility.merge_tables(a, b)
end
-- see https://en.wikipedia.org/wiki/Logistic_function
function utility.logistic_growth(value, max, growth, midpoint)
function utility.sigmoid(value, max, growth, midpoint)
return max / (1 + math.exp(-growth * (value - midpoint)))
end

View File

@ -1,16 +1,14 @@
local default_state = {
heat = 1,
humidity = 1,
wind_x = 0.5,
wind_z = 0.5,
time_last_check = 0,
time_current_day = 1
}
local state = minetest.get_mod_storage()
if not state:contains("time_last_check") then
state:from_table({ fields = default_state })
if not state:contains("noise_timer") then
state:from_table({
heat_random = 1,
humidity_random = 1,
humidity_base = 50,
wind_x = 0.5,
wind_z = 0.5,
noise_timer = math.random(0, 300000)
})
end
return state

View File

@ -8,7 +8,7 @@ end
local function get_heat_calendar()
-- European heat center in August instead of June
local day = minetest.get_day_count()
local progression = (day + 61) / 365
local progression = ((day + 61) % 365) / 365
return climate_api.utility.normalized_cycle(progression) * 0.6 + 0.7
end

View File

@ -4,6 +4,14 @@ author = TestificateMods
release = 1
optional_depends = skylayer, player_monoids, playerphysics
description = """
The ultimate weather mod with support not only for rain, snow, and hail,
but also seasons, dynamic puddles and snow layers, wind, regrowing fruit and much more.
A powerful engine for weather presets and visual effects.
Use the regional climate to set up different effects for different regions.
Control where your effects are activated based on temperature, humidity, wind,
position, light level or a completely custom activator.
Climate API provides temperature and humidity values on a block-per-block basis
that follow the seasons, day / night cycle and random changes.
Make it rain, change the sky or poison the player - it's up to you.
Climate API requires additional weather packs in order to function.
Try regional_weather for the best experience.
"""