From fdc457bd096405aa803289c7a0d993a152f7a601 Mon Sep 17 00:00:00 2001 From: Till Affeldt Date: Mon, 13 Apr 2020 16:53:32 +0200 Subject: [PATCH] Implement dynamic cloud sizes, adjust cycle lengths --- TODO.md | 12 +++++----- ca_effects/clouds.lua | 54 +++++++++++++++++++++++++++++++++++++++++++ ca_effects/sound.lua | 2 +- init.lua | 1 + lib/api.lua | 5 ++-- lib/api_utility.lua | 2 +- lib/datastorage.lua | 20 ++++++++-------- lib/environment.lua | 2 +- mod.conf | 12 ++++++++-- 9 files changed, 86 insertions(+), 24 deletions(-) create mode 100644 ca_effects/clouds.lua diff --git a/TODO.md b/TODO.md index dd2a2db..383fa10 100644 --- a/TODO.md +++ b/TODO.md @@ -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 diff --git a/ca_effects/clouds.lua b/ca_effects/clouds.lua new file mode 100644 index 0000000..2f8487d --- /dev/null +++ b/ca_effects/clouds.lua @@ -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) \ No newline at end of file diff --git a/ca_effects/sound.lua b/ca_effects/sound.lua index c11b948..890cbd4 100644 --- a/ca_effects/sound.lua +++ b/ca_effects/sound.lua @@ -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) \ No newline at end of file +climate_api.set_effect_cycle("climate_api:skybox", climate_api.MEDIUM_CYCLE) \ No newline at end of file diff --git a/init.lua b/init.lua index 402a5b7..9190b0f 100644 --- a/init.lua +++ b/init.lua @@ -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") diff --git a/lib/api.lua b/lib/api.lua index 01fd6e2..5e9dcaa 100644 --- a/lib/api.lua +++ b/lib/api.lua @@ -1,8 +1,9 @@ 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.DEFAULT_CYCLE = 0.1 -- for most effect types +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 = {} diff --git a/lib/api_utility.lua b/lib/api_utility.lua index fb63664..b121298 100644 --- a/lib/api_utility.lua +++ b/lib/api_utility.lua @@ -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 diff --git a/lib/datastorage.lua b/lib/datastorage.lua index 5a26088..9571b48 100644 --- a/lib/datastorage.lua +++ b/lib/datastorage.lua @@ -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 \ No newline at end of file diff --git a/lib/environment.lua b/lib/environment.lua index f10660a..123527f 100644 --- a/lib/environment.lua +++ b/lib/environment.lua @@ -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 diff --git a/mod.conf b/mod.conf index 594b9b6..2f158d2 100644 --- a/mod.conf +++ b/mod.conf @@ -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. """ \ No newline at end of file