diff --git a/README.md b/README.md deleted file mode 100644 index 0c63654..0000000 --- a/README.md +++ /dev/null @@ -1,9 +0,0 @@ -## Assets -- Rain sounds CC0 by Q.K., taken from mymonths -- Thunder sound and puddle texture DWYWPL by Don, Nathan from mymonths at https://github.com/minetest-mods/mymonths -- Snow cover texture WTFPL, taken from mymonths -- Rain texture CC-BY-SA 3.0 from TeddyDesTodes, taken from his weather branch at https://github.com/TeddyDesTodes/minetest/tree/weather -- Snow flake and rain drop textures CC BY-SA (3.0) by paramat, found in snowdrift mod at https://github.com/paramat/snowdrift -- Snow texture composited from individual snow flakes by paramat. CC-BY-SA (3.0) -- Wind sound CC-BY (3.0) by InspectorJ from https://freesound.org/people/InspectorJ/sounds/376415/ -- Hail sound CC0 by ikayuka from https://freesound.org/people/ikayuka/sounds/240742/ \ No newline at end of file diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..dd2a2db --- /dev/null +++ b/TODO.md @@ -0,0 +1,55 @@ +# 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 +- Implement start/end events +- Make sure all weather presets are working +- Implement chat commands + +## Planned for first release +- Improve test_condition function +- Implement ABM system for additional effects +- Add light level to possible conditions +- Implement fallback for sky changes without skylayer +- Configurable number of days in a year +- Add license information to source files +- Write helpful README +- Find good values for weather conditions +- Make switches between effects more smooth + +## 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 + +## Future Plans & Ideas +- Complete season system + - crops grow better in their respective season or worse in winter + - regrowing apples, lemons, etc. in their respective months + - holidays and reminders via chat commands + - day/night nycle adjusted to season + - special events like a bloodmoon -> increased mob spawns +- Fantasy weather effects + - pretty skyboxes + - swirling flower petals, mushroom spores, etc. in fitting biomes + - underground environment effects + - space effects at high y-level (meteors, magnetic storms, different skybox) +- Eco Pack (with climate change) + - Integration with Technic mods, etc. + - Track planted trees vs chopped wood, killed mobs, etc. + - Ecological footprint influences weather + - Extreme weather scenarios and desasters + - Tornados, poisonous rain that kills crops and animals, bush fires,... +- Survival Pack + - Body temperature becomes survival aspect + - Use local heat as base value + - swimming will cool down + - standing near fire will warm up + - craftable warm clothes + - metal armor will worsen heat issues \ No newline at end of file diff --git a/ca_effects/particles.lua b/ca_effects/particles.lua new file mode 100644 index 0000000..d2e743b --- /dev/null +++ b/ca_effects/particles.lua @@ -0,0 +1,65 @@ +if not climate_mod.settings.particles then return end + +local function get_particle_texture(particles) + if type(particles.textures) == "nil" or next(particles.textures) == nil then + return particles.texture + end + return particles.textures[math.random(#particles.textures)] +end + +local function spawn_particles(player, particles) + local ppos = player:getpos() + local wind_x = climate_mod.state:get_int("wind_x") + local wind_z = climate_mod.state:get_int("wind_z") + local wind = vector.new(wind_x, 0, wind_z) + local wind_pos = vector.multiply(wind, -1) + local wind_speed = vector.length(wind) + + local texture = get_particle_texture(particles) + + local minp = vector.add(vector.add(ppos, particles.min_pos), wind_pos) + local maxp = vector.add(vector.add(ppos, particles.max_pos), wind_pos) + + local vel = vector.new({ + x = wind.x, + y = -particles.falling_speed, + z = wind.z + }) + local acc = vector.new({x=0, y=0, z=0}) + + local exp = particles.exptime + local vertical = math.abs(vector.normalize(vel).y) >= 0.6 + + minetest.add_particlespawner({ + amount = particles.amount, + time = 0.5, + minpos = minp, + maxpos = maxp, + minvel = vel, + maxvel = vel, + minacc = acc, + maxacc = acc, + minexptime = exp, + maxexptime = exp, + minsize = particles.size, + maxsize = particles.size, + collisiondetection = true, + collision_removal = true, + vertical = vertical, + texture = texture, + player = player:get_player_name() + }) +end + +local function handle_effect(player_data) + for playername, data in pairs(player_data) do + minetest.chat_send_player(playername, "spam") + local player = minetest.get_player_by_name(playername) + for weather, value in pairs(data) do + spawn_particles(player, value) + end + end +end + +climate_api.register_effect("climate_api:particles", handle_effect, "tick") +climate_api.set_effect_cycle("climate_api:particles", climate_api.SHORT_CYCLE) \ No newline at end of file diff --git a/ca_effects/skybox.lua b/ca_effects/skybox.lua new file mode 100644 index 0000000..e876f36 --- /dev/null +++ b/ca_effects/skybox.lua @@ -0,0 +1,35 @@ +if not climate_mod.settings.skybox then return end +if not minetest.get_modpath("skylayer") then return end + +local SKYBOX_NAME = "climate_api:skybox" + +local function set_skybox(player, sky) + sky.name = SKYBOX_NAME + skylayer.add_layer(player:get_player_name(), sky) +end + +local function remove_skybox(player) + skylayer.remove_layer(player:get_player_name(), SKYBOX_NAME) +end + +local function handle_effect(player_data) + for playername, data in pairs(player_data) do + local player = minetest.get_player_by_name(playername) + local sky = {} + for weather, value in pairs(data) do + climate_api.utility.merge_tables(sky, value) + end + set_skybox(player, sky) + 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_skybox(player) + end +end + +climate_api.register_effect("climate_api:skybox", handle_effect, "tick") +climate_api.register_effect("climate_api:skybox", remove_effect, "end") +climate_api.set_effect_cycle("climate_api:skybox", climate_api.LONG_CYCLE) \ No newline at end of file diff --git a/ca_effects/sound.lua b/ca_effects/sound.lua new file mode 100644 index 0000000..c11b948 --- /dev/null +++ b/ca_effects/sound.lua @@ -0,0 +1,14 @@ +if not climate_mod.settings.sound then return end + +return + +local function update_effect(player_data) + for playername, data in pairs(player_data) do + for weather, value in pairs(data) do + climate_mod.effects.play_sound(player, value) + end + end +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 diff --git a/depends.txt b/depends.txt deleted file mode 100644 index 511ef53..0000000 --- a/depends.txt +++ /dev/null @@ -1,5 +0,0 @@ -default -datastorage? -lightning? -player_monoids? -playerphysics? \ No newline at end of file diff --git a/description.txt b/description.txt deleted file mode 100644 index 1705973..0000000 --- a/description.txt +++ /dev/null @@ -1,2 +0,0 @@ -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. \ No newline at end of file diff --git a/init.lua b/init.lua index 4780d4a..4e838a6 100644 --- a/init.lua +++ b/init.lua @@ -1,56 +1,42 @@ -assert(minetest.add_particlespawner, "Believable Weather requires a more current version of Minetest") -weather_mod = {} +assert(minetest.add_particlespawner, "[Climate API] This mod requires a more current version of Minetest") -weather_mod.modname = "believable_weather" -weather_mod.modpath = minetest.get_modpath(weather_mod.modname) +climate_api = {} +climate_mod = {} + +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) local function getBoolSetting(name, default) - return minetest.is_yes(minetest.settings:get_bool(weather_mod.modname .. "_" .. name) or default) + return minetest.is_yes(minetest.settings:get_bool("climate_api_" .. name) or default) end local function getNumericSetting(name, default) - return tonumber(minetest.settings:get(weather_mod.modname .. "_" .. name) or default) + return tonumber(minetest.settings:get("climate_api_" .. name) or default) end -- load settings from config file -weather_mod.settings = { - damage = getBoolSetting("damage", true), +climate_mod.settings = { particles = getBoolSetting("particles", true), - leaves = getBoolSetting("leaves", true), - snow = getBoolSetting("snow_layers", true), - puddles = getBoolSetting("puddles", true), skybox = getBoolSetting("skybox", true), - raycasting = getBoolSetting("raycasting", true), + sound = getBoolSetting("sound", true), wind = getBoolSetting("wind", true), - wind_slow = getBoolSetting("wind_slow", true), - flowers = getBoolSetting("flowers", true), - fruit = getBoolSetting("fruit", true), - soil = getBoolSetting("soil", true), seasons = getBoolSetting("seasons", true), - heat = getNumericSetting("base_heat", 0), - humidity = getNumericSetting("base_humidity", 0), - max_height = getNumericSetting("max_height", 120), - min_height = getNumericSetting("min_height", -50) + heat = getNumericSetting("heat_base", 0), + humidity = getNumericSetting("humidity_base", 0) } -dofile(weather_mod.modpath.."/lib/datastorage.lua") -weather_mod.state = weather_mod.get_storage() +climate_mod.current_weather = {} +climate_mod.current_effects = {} -- import core API -dofile(weather_mod.modpath.."/lib/player.lua") -dofile(weather_mod.modpath.."/lib/environment.lua") -dofile(weather_mod.modpath.."/lib/wind.lua") -dofile(weather_mod.modpath.."/lib/calendar_dictionary.lua") -dofile(weather_mod.modpath.."/lib/calendar.lua") -dofile(weather_mod.modpath.."/lib/main.lua") -dofile(weather_mod.modpath.."/lib/commands.lua") +climate_mod.state = dofile(modpath .. "/lib/datastorage.lua") +climate_api = dofile(modpath .. "/lib/api.lua") +climate_api.utility = dofile(modpath .. "/lib/api_utility.lua") +climate_api.environment = dofile(modpath .. "/lib/environment.lua") +climate_mod.world = dofile(modpath .. "/lib/world.lua") +climate_mod.trigger = dofile(modpath .. "/lib/trigger.lua") +dofile(modpath.."/lib/main.lua") --- import individual weather types -dofile(weather_mod.modpath.."/weathers/rain.lua") -dofile(weather_mod.modpath.."/weathers/rain_heavy.lua") -dofile(weather_mod.modpath.."/weathers/snow.lua") -dofile(weather_mod.modpath.."/weathers/snow_heavy.lua") -dofile(weather_mod.modpath.."/weathers/storm.lua") -dofile(weather_mod.modpath.."/weathers/sandstorm.lua") -dofile(weather_mod.modpath.."/weathers/hail.lua") -dofile(weather_mod.modpath.."/weathers/pollen.lua") +-- import predefined environment effects +dofile(modpath .. "/ca_effects/particles.lua") +dofile(modpath .. "/ca_effects/skybox.lua") diff --git a/lib/api.lua b/lib/api.lua new file mode 100644 index 0000000..65d6df6 --- /dev/null +++ b/lib/api.lua @@ -0,0 +1,39 @@ +local api = {} + +api.SHORT_CYCLE = 0 -- for particles and fast animations +api.DEFAULT_CYCLE = 0 -- for most effect types +api.LONG_CYCLE = 0 -- for write operations and skybox changes + +climate_mod.weathers = {} +climate_mod.effects = {} +climate_mod.cycles = {} + +function api.register_weather(name, conditions, effects) + -- TODO: check and sanitize + climate_mod.weathers[name] = { + conditions = conditions, + effects = effects, + active_players = {} + } +end + +function api.register_effect(name, handler, htype) + -- check for valid handler types + if htype ~= "start" and htype ~= "tick" and htype ~= "stop" then + minetest.log("warn", "[Climate API] Invalid effect handler type: " .. htype) + return + end + -- create effect handler registry if not existent yet + if type(climate_mod.effects[name]) == "nil" then + climate_mod.effects[name] = { start = {}, tick = {}, stop = {} } + climate_mod.cycles[name] = { timespan = DEFAULT_CYCLE, timer = 0 } + end + -- store effect handler + table.insert(climate_mod.effects[name][htype], handler) +end + +function api.set_effect_cycle(name, cycle) + climate_mod.cycles[name].timespan = cycle +end + +return api diff --git a/lib/api_utility.lua b/lib/api_utility.lua new file mode 100644 index 0000000..c5dbaa3 --- /dev/null +++ b/lib/api_utility.lua @@ -0,0 +1,63 @@ +local mod_player_monoids = minetest.get_modpath("player_monoids") ~= nil +local mod_playerphysics = minetest.get_modpath("playerphysics") ~= nil + +local utility = {} + +function utility.rangelim(value, min, max) + return math.min(math.max(value, min), max) +end + +-- from https://stackoverflow.com/a/29133654 +-- merges two tables together +-- if in conflict, b will override values of a +function utility.merge_tables(a, b) + if type(a) == "table" and type(b) == "table" then + for k,v in pairs(b) do + if type(v)=="table" and type(a[k] or false)=="table" then + merge(a[k],v) + else a[k]=v end + end + end + return a +end + +-- see https://en.wikipedia.org/wiki/Logistic_function +function utility.logistic_growth(value, max, growth, midpoint) + return max / (1 + math.exp(-growth * (value - midpoint))) +end + +-- generates a wave of cycle length 1 +-- maps parameters to values between 0 and 1 +-- 0 is mapped to 0 and 0.5 to 1 +function utility.normalized_cycle(value) + return math.cos((2 * value + 1) * math.pi) / 2 + 0.5 +end + +-- override player physics +-- use utility mod if possible to avoid conflict +function utility.add_physics(id, player, effect, value) + if mod_player_monoids then + player_monoids[effect]:add_change(player, value, id) + elseif mod_playerphysics then + playerphysics.add_physics_factor(player, effect, id, value) + else + local override = {} + override[effect] = value + player:set_physics_override(override) + end +end + +-- reset player phsysics to normal +function utility.remove_physics(id, player, effect) + if mod_player_monoids then + player_monoids[effect]:del_change(player, id) + elseif mod_playerphysics then + playerphysics.remove_physics_factor(player, effect, id) + else + local override = {} + override[effect] = 1 + player:set_physics_override(override) + end +end + +return utility diff --git a/lib/calendar.lua b/lib/calendar.lua deleted file mode 100644 index 8601cf8..0000000 --- a/lib/calendar.lua +++ /dev/null @@ -1,18 +0,0 @@ -function weather_mod.get_time_heat() - local time = minetest.get_timeofday() - return math.cos((2 * time + 1) * math.pi) / 3 + 1 -end - -function weather_mod.get_calendar_heat() - -- European heat center in August instead of June - local progression = (weather_mod.state.time.day + 61) / 365 - return math.cos((2 * progression + 1) * math.pi) / 3 + 1 -end - -function weather_mod.handle_time_progression() - local time = minetest.get_timeofday() - if time < weather_mod.state.time.last_check then - weather_mod.state.time.day = weather_mod.state.time.day + 1 - end - weather_mod.state.time.last_check = time -end \ No newline at end of file diff --git a/lib/calendar_dictionary.lua b/lib/calendar_dictionary.lua deleted file mode 100644 index cf28ca7..0000000 --- a/lib/calendar_dictionary.lua +++ /dev/null @@ -1,58 +0,0 @@ -weather_mod.weekdays = { - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", - "Sunday" -} - -weather_mod.months = { - { name = "January", days = 31 }, - { name = "February", days = 28 }, - { name = "March", days = 31 }, - { name = "April", days = 30 }, - { name = "May", days = 31 }, - { name = "June", days = 30 }, - { name = "July", days = 31 }, - { name = "August", days = 31 }, - { name = "September", days = 30 }, - { name = "October", days = 31 }, - { name = "November", days = 30 }, - { name = "December", days = 31 } -} - -weather_mod.seasons = { - { name = "spring" }, - { name = "summer" }, - { name = "autumn" }, - { name = "winter" } -} - -function weather_mod.get_weekday() - return (weather_mod.state.time.day - 1) % 7 + 1 -end - -function weather_mod.get_month() - local day = (weather_mod.state.time.day - 1) % 365 + 1 - local sum = 0 - for i, month in ipairs(weather_mod.months) do - sum = sum + month.days - if sum >= day then - return i - end - end -end - -function weather_mod.get_season() - local month = weather_mod.get_month() - return math.floor((month - 1) / 3 + 1) -end - -function weather_mod.print_date() - local weekday = weather_mod.weekdays[weather_mod.get_weekday()] - local date = (weather_mod.state.time.day - 1) % 365 + 1 - local month = weather_mod.months[weather_mod.get_month()].name - return weekday .. ", " .. date .. ". " .. month -end \ No newline at end of file diff --git a/lib/commands.lua b/lib/commands.lua deleted file mode 100644 index 79a9d03..0000000 --- a/lib/commands.lua +++ /dev/null @@ -1,94 +0,0 @@ -minetest.register_privilege("weather", { - description = "Change the weather", - give_to_singleplayer = false -}) - -minetest.register_chatcommand("date", { - func = function(playername, param) - local date = weather_mod.print_date() - minetest.chat_send_player(playername, date) - end -}) - --- Force a weather effect to override environment -minetest.register_chatcommand("set_weather", { - params = "", - description = "Set weather to a registered type of effect\ - show all types when no parameters are given", -- full description - privs = {weather = true}, - func = function(name, param) - if param == nil or param == "" or param == "?" then - local types="auto" - for i,_ in pairs(weather_mod.weathers) do - types=types..", "..i - end - minetest.chat_send_player(name, "avalible weather types: "..types) - else - if type(weather_mod.weathers[param]) == "nil" and param ~= "auto" then - minetest.chat_send_player(name, "This type of weather is not registered.\n".. - "To list all types of weather run the command without parameters.") - else - weather_mod.state.current_weather = param - end - end - end -}) - --- Set wind speed and direction -minetest.register_chatcommand("set_wind", { - params = "", - description = "Set wind to the given x,z direction", -- full description - privs = {weather = true}, - func = function(name, param) - if param==nil or param=="" then - minetest.chat_send_player(name, "please provide two comma seperated numbers") - return - end - local x,z = string.match(param, "^([%d.-]+)[, ] *([%d.-]+)$") - x=tonumber(x) - z=tonumber(z) - if x and z then - weather_mod.state.wind = vector.new(x,0,z) - else - minetest.chat_send_player(name, param.." are not two comma seperated numbers") - end - end -}) - --- Set base value of global heat level -minetest.register_chatcommand("set_heat", { - params = "", - description = "Set base value of global heat level", -- full description - privs = {weather = true}, - func = function(name, param) - if param==nil or param=="" then - minetest.chat_send_player(name, "please provide a heat value") - return - end - v = tonumber(param) - if v then - weather_mod.state.heat = v - else - minetest.chat_send_player(name, param.." is not a valid heat level") - end - end -}) - --- Set base value of global humidity level -minetest.register_chatcommand("set_humidity", { - params = "", - description = "Set base value of global humidity level", -- full description - privs = {weather = true}, - func = function(name, param) - if param==nil or param=="" then - minetest.chat_send_player(name, "please provide a humidity value") - return - end - v = tonumber(param) - if v then - weather_mod.state.humidity = v - else - minetest.chat_send_player(name, param.." is not a valid humidity level") - end - end -}) \ No newline at end of file diff --git a/lib/datastorage.lua b/lib/datastorage.lua index e6738bd..5a26088 100644 --- a/lib/datastorage.lua +++ b/lib/datastorage.lua @@ -1,48 +1,16 @@ local default_state = { heat = 1, humidity = 1, - wind = vector.new(0, 0, -0.25), - current_weather = "auto", - time = { - last_check = 0, - day = 1 - } + wind_x = 0.5, + wind_z = 0.5, + time_last_check = 0, + time_current_day = 1 } -local function use_datastorage() - local state = datastorage.get(weather_mod.modname, "weather_state") - for key, val in pairs(default_state) do - if type(state[key]) == "nil" then - state[key] = val - end - end - return state +local state = minetest.get_mod_storage() + +if not state:contains("time_last_check") then + state:from_table({ fields = default_state }) end -local function use_filesystem() - local file_name = minetest.get_worldpath() .. "/" .. weather_mod.modname - minetest.register_on_shutdown(function() - local file = io.open(file_name, "w") - file:write(minetest.serialize(weather_mod.state)) - file:close() - end) - - local file = io.open(file_name, "r") - if file ~= nil then - local storage = minetest.deserialize(file:read("*a")) - file:close() - if type(storage) == "table" then - return storage - end - end - return default_state -end - -function weather_mod.get_storage() - local mod_datastorage = minetest.get_modpath("datastorage") ~= nil - if mod_datastorage then - return use_datastorage() - else - return use_filesystem() - end -end +return state \ No newline at end of file diff --git a/lib/environment.lua b/lib/environment.lua index 9d57c70..22348a6 100644 --- a/lib/environment.lua +++ b/lib/environment.lua @@ -1,80 +1,36 @@ -local mod_lightning = minetest.get_modpath("lightning") +local environment = {} -local LIGHTNING_CHANCE = 1000 -if mod_lightning then - lightning.auto = false +local function get_heat_time() + local time = minetest.get_timeofday() + return climate_api.utility.normalized_cycle(time) * 0.4 + 0.3 end -function weather_mod.get_heat(pos) - local base = weather_mod.settings.heat; +local function get_heat_calendar() + -- European heat center in August instead of June + local day = climate_mod.state:get("time_current_day") + local progression = ((day + 61) % 365) / 365 + return climate_api.utility.normalized_cycle(progression) * 0.4 + 0.3 +end + +local function get_heat_height(y) + return climate_api.utility.rangelim(-y / 15, -10, 10) +end + +function environment.get_heat(pos) + local base = climate_mod.settings.heat local biome = minetest.get_heat(pos) - local height = math.min(math.max(-pos.y / 15, -10), 10) - local time = weather_mod.get_time_heat() - local date = weather_mod.get_calendar_heat() - local random = weather_mod.state.heat; - return (base + biome + height) * time * date + random + local height = get_heat_height(pos.y) + local time = get_heat_time() + local date = get_heat_calendar() + local random = climate_mod.state:get_int("heat_random"); + return (base + biome + height) * time * date end -function weather_mod.get_humidity(pos) - local base = weather_mod.settings.humidity +function environment.get_humidity(pos) + local base = climate_mod.settings.humidity local biome = minetest.get_humidity(pos) - local random = weather_mod.state.humidity; - return (base + biome) + random + local random = climate_mod.state:get_int("humidity_random"); + return (base + biome) end -function weather_mod.get_climate(pos) - local climate = {pos = pos} - climate.heat = weather_mod.get_heat(pos) - climate.humidity = weather_mod.get_humidity(pos) - climate.windspeed = vector.length(weather_mod.state.wind) - return climate -end - -local function is_acceptable_weather_param(value, attr, config) - local min = config.conditions["min_" .. attr] or -math.huge - local max = config.conditions["max_" .. attr] or math.huge - return value > min and value <= max -end - -function weather_mod.get_effects(climate) - local forced_weather = weather_mod.state.current_weather - if type(forced_weather) ~= nil and forced_weather ~= "auto" then - return { forced_weather } - end - local params = {} - params.heat = climate.heat - params.humidity = climate.humidity - params.windspeed = vector.length(weather_mod.state.wind) - params.height = climate.pos.y - - local effects = {} - local attributes = { "heat", "humidity", "windspeed", "height" } - for name, effect in pairs(weather_mod.weathers) do - if type(effect.config.conditions) == "nil" then - table.insert(effects, name) - goto continue - end - - for _, attr in ipairs(attributes) do - if not is_acceptable_weather_param(params[attr], attr, effect.config) then - goto continue - end - end - table.insert(effects, name) - ::continue:: - end - return effects -end - -function weather_mod.handle_events(player, flags) - local ppos = player:get_pos() - if mod_lightning and weather_mod.settings.lightning and type(flags["lightning"]) ~= "nil" then - local random = rng:next(1, LIGHTNING_CHANCE) - if random == 1 then - lightning.strike(ppos) - end - end - if type(flags["damage"]) ~= "nil" then - weather_mod.damage_player(player, 1) - end -end \ No newline at end of file +return environment \ No newline at end of file diff --git a/lib/main.lua b/lib/main.lua index 231fd9e..29cc23b 100644 --- a/lib/main.lua +++ b/lib/main.lua @@ -1,124 +1,27 @@ -local GSCYCLE = 0.05 -local RECALCCYCLE = 0.2 +local GSCYCLE = 0 +local WORLD_CYCLE = 0 -weather_mod.weathers = {} -function weather_mod.register_effect(name, config, override) - -- TODO: check and sanitize - weather_mod.weathers[name] = { - config = config, - override = override, - sound_handles = {}, - sound_volumes = {} - } -end - --- from https://stackoverflow.com/a/29133654 -local function merge(a, b) - if type(a) == 'table' and type(b) == 'table' then - for k,v in pairs(b) do if type(v)=='table' and type(a[k] or false)=='table' then merge(a[k],v) else a[k]=v end end - end - return a -end - -local function build_effect_config(weather, climate) - local config = weather.config - local override = weather.override - if type(override) == "nil" then - return config - end - local dynamic_config = override(climate) - return merge(config, dynamic_config) -end - -local function get_texture(particles) - if type(particles.textures) == "nil" or next(particles.textures) == nil then - return particles.texture - end - return particles.textures[math.random(#particles.textures)] -end - -local function spawn_particles(player, particles, wind) - local ppos = player:getpos() - local wind_pos = vector.multiply(weather_mod.state.wind,-1) - local wind_speed = vector.length(weather_mod.state.wind) - - local texture = get_texture(particles) - - local minp = vector.add(vector.add(ppos, particles.min_pos),wind_pos) - local maxp = vector.add(vector.add(ppos, particles.max_pos),wind_pos) - - local vel = vector.new({ - x=weather_mod.state.wind.x, - y=-particles.falling_speed, - z=weather_mod.state.wind.z - }) - local acc = vector.new({x=0, y=0, z=0}) - - local exp = particles.exptime - local vertical = math.abs(vector.normalize(vel).y) >= 0.6 - - minetest.add_particlespawner({ - amount=particles.amount, - time=0.5, - minpos=minp, - maxpos=maxp, - minvel=vel, - maxvel=vel, - minacc=acc, - maxacc=acc, - minexptime=exp, - maxexptime=exp, - minsize=particles.size, - maxsize=particles.size, - collisiondetection=true, - collision_removal=true, - vertical=vertical, - texture=texture, - player=player:get_player_name() - }) -end - -local function handle_weather_effects(player) - local ppos = player:getpos() - local climate = weather_mod.get_climate(ppos) - local active_effects = weather_mod.get_effects(climate) - local environment_flags = {} - local sounds = {} - - for _, effect in ipairs(active_effects) do - local weather = weather_mod.weathers[effect] - local config = build_effect_config(weather, climate) - - local outdoors = weather_mod.is_outdoors(player) - if type(config.particles) ~= "nil" and outdoors then - spawn_particles(player, config.particles, weather_mod.state.wind) - end - if type(config.sound) ~= "nil" and outdoors then - sounds[effect] = config.sound - end - if type(config.environment) ~= "nil" and outdoors then - for flag, value in pairs(config.environment) do - if value ~= false then - environment_flags[flag] = value - end - end - end - end - weather_mod.handle_sounds(player, sounds) - weather_mod.handle_events(player, environment_flags) -end - -local timer = 0 +local gs_timer = 0 +local world_timer = 0 minetest.register_globalstep(function(dtime) - timer = timer + dtime - if timer < GSCYCLE then return end - for _, player in ipairs(minetest.get_connected_players()) do - handle_weather_effects(player) - if timer >= RECALCCYCLE then - weather_mod.set_clouds(player) - weather_mod.set_headwind(player) - weather_mod.handle_time_progression() + gs_timer = gs_timer + dtime + world_timer = world_timer + dtime + + if gs_timer + dtime < GSCYCLE then return else gs_timer = 0 end + + if world_timer >= WORLD_CYCLE then + local noise_timer = climate_mod.state:get_float("noise_timer") + world_timer + world_timer = 0 + climate_mod.state:set_float("noise_timer", noise_timer) + climate_mod.world.update_status(noise_timer) + end + + local effects = climate_mod.trigger.get_active_effects() + + for name, effect in pairs(climate_mod.effects) do + if climate_mod.cycles[name].timespan < climate_mod.cycles[name].timer + dtime then + climate_mod.cycles[name].timer = 0 + climate_mod.trigger.call_handlers(name, effects[name]) end end - timer = 0 end) \ No newline at end of file diff --git a/lib/player.lua b/lib/player.lua deleted file mode 100644 index 1ed74ba..0000000 --- a/lib/player.lua +++ /dev/null @@ -1,92 +0,0 @@ -local mod_player_monoids = minetest.get_modpath("player_monoids") ~= nil -local mod_playerphysics = minetest.get_modpath("playerphysics") ~= nil - -function weather_mod.add_physics(player, effect, value) - local id = weather_mod.modname .. ":" .. effect - if mod_player_monoids then - player_monoids[effect]:add_change(player, value, id) - elseif mod_playerphysics then - playerphysics.add_physics_factor(player, effect, id, value) - else - local override = {} - override[effect] = value - player:set_physics_override(override) - end -end - -function weather_mod.remove_physics(player, effect) - local id = weather_mod.modname .. ":" .. effect - if mod_player_monoids then - player_monoids[effect]:del_change(player, id) - elseif mod_playerphysics then - playerphysics.remove_physics_factor(player, effect, id) - else - local override = {} - override[effect] = 1 - player:set_physics_override(override) - end -end - -function weather_mod.is_outdoors(player) - return minetest.get_node_light(player:getpos(), 0.5) == 15 -end - -function weather_mod.set_clouds(player) - if not weather_mod.settings.skybox then - return - end - local ppos = player:get_pos() - local humidity = weather_mod.get_humidity(ppos) / 100 - local clouds = {} - clouds.speed = vector.multiply(weather_mod.state.wind, 2) - clouds.color = "#fff0f0c5" - clouds.density = math.max(math.min(humidity, 0.8), 0.1) - player:set_clouds(clouds) -end - -function weather_mod.play_sound(player, effect) - local playername = player:get_player_name() - if not effect.sound_handles[playername] then - local handle = minetest.sound_play(effect.config.sound, { - to_player = playername, - loop = true - }) - if handle then - effect.sound_handles[playername] = handle - effect.sound_volumes[playername] = effect.config.sound.gain or 1 - end - end -end - -function weather_mod.stop_sound(player, effect) - local playername = player:get_player_name() - if effect.sound_handles[playername] then - minetest.sound_stop(effect.sound_handles[playername]) - effect.sound_handles[playername] = nil - effect.sound_volumes[playername] = nil - end -end - -function weather_mod.handle_sounds(player, sounds) - local playername = player:get_player_name() - for name, effect in pairs(weather_mod.weathers) do - if type(effect.sound_handles[playername]) == "nil" and type(sounds[name]) ~= "nil" then - weather_mod.play_sound(player, effect) - elseif type(effect.sound_handles[playername]) ~= "nil" and type(sounds[name]) == "nil" then - weather_mod.stop_sound(player, effect) - elseif type(effect.sound_handles[playername]) ~= "nil" and type(sounds[name]) ~= "nil" then - local volume = sounds[name].gain or 1 - if effect.sound_volumes[playername] ~= volume then - minetest.sound_fade(effect.sound_handles[playername], 1, volume) - end - end - end -end - -function weather_mod.damage_player(player, amount, reason) - if not weather_mod.settings.damage then - return - end - local hp = player:get_hp() - player:set_hp(hp - amount, reason) -end \ No newline at end of file diff --git a/lib/trigger.lua b/lib/trigger.lua new file mode 100644 index 0000000..7d7b691 --- /dev/null +++ b/lib/trigger.lua @@ -0,0 +1,89 @@ +local trigger = {} + +local function get_player_environment(player) + local ppos = player:get_pos() + local wind_x = climate_mod.state:get_int("wind_x") + local wind_z = climate_mod.state:get_int("wind_z") + + local env = {} + env.player = player + env.pos = pos + env.wind = vector.new(wind_x, 0, wind_z) + env.windspeed = vector.length(env.wind) + env.heat = climate_api.environment.get_heat(ppos) + env.humidity = climate_api.environment.get_humidity(ppos) + env.time = minetest.get_timeofday() + env.date = climate_mod.state:get_int("time_current_day") + return env +end + +local function test_condition(condition, env, goal) + local value = env[condition:sub(5)] + if condition:sub(1, 4) == "min_" then + for _, player in ipairs(minetest.get_connected_players()) do + minetest.chat_send_player(player:get_player_name(), dump2(value, goal)) + end + return type(value) ~= "nil" and goal <= value + elseif condition:sub(1, 4) == "max_" then + return type(value) ~= "nil" and goal > value + else + Minetest.log("warning", "[Climate API] Invalid effect condition") + return false + end +end + +local function is_weather_active(player, weather_config, env) + if type(weather_config.conditions) == "function" then + return weather_config.conditions(env) + end + for condition, goal in pairs(weather_config.conditions) do + if not test_condition(condition, env, goal) then + return false + end + end + return true +end + +local function get_weather_effects(player, weather_config, env) + if type(weather_config.effects) == "function" then + return weather_config.effects(env) + end + return weather_config.effects +end + +function trigger.get_active_effects() + local environments = {} + for _, player in ipairs(minetest.get_connected_players()) do + environments[player:get_player_name()] = get_player_environment(player) + end + + local effects = {} + for wname, wconfig in pairs(climate_mod.weathers) do + for _, player in ipairs(minetest.get_connected_players()) do + local pname = player:get_player_name() + local env = environments[pname] + if is_weather_active(player, wconfig, env) then + local player_effects = get_weather_effects(player, wconfig, env) + for effect, value in pairs(player_effects) do + if type(effects[effect]) == "nil" then + effects[effect] = {} + end + if type(effects[effect][pname]) == "nil" then + effects[effect][pname] = {} + end + effects[effect][pname][wname] = value + end + end + end + end + return effects +end + +function trigger.call_handlers(name, effect) + if type(effect) == "nil" then return end + for _, handler in ipairs(climate_mod.effects[name]["tick"]) do + handler(effect) + end +end + +return trigger \ No newline at end of file diff --git a/lib/wind.lua b/lib/wind.lua deleted file mode 100644 index 5722773..0000000 --- a/lib/wind.lua +++ /dev/null @@ -1,12 +0,0 @@ -function weather_mod.set_headwind(player) - local movement = vector.normalize(player:get_player_velocity()) - local product = vector.dot(movement, weather_mod.state.wind) - -- logistic function, scales between 0 and 2 - -- see https://en.wikipedia.org/wiki/Logistic_function - local L = 1.6 -- maximum value - local k = 0.15 -- growth rate - local z = 0.8 -- midpoint - local o = 0.1 -- y offset - local factor = L / (1 + math.exp(-k * (product - z))) + o - weather_mod.add_physics(player, "speed", factor) -end \ No newline at end of file diff --git a/lib/world.lua b/lib/world.lua new file mode 100644 index 0000000..7da5901 --- /dev/null +++ b/lib/world.lua @@ -0,0 +1,92 @@ +local world = {} + +local WIND_SPREAD = 600 +local WIND_SCALE = 3 +local HEAT_SPREAD = 2400 +local HEAT_SCALE = 0.2 +local HUMIDITY_SPREAD = 1200 +local HUMIDITY_SCALE = 0.18 + +local nobj_wind_x +local nobj_wind_z +local nobj_heat +local nobj_humidity + +local pn_wind_speed_x = { + offset = 0, + scale = WIND_SCALE, + spread = {x = WIND_SPREAD, y = WIND_SPREAD, z = WIND_SPREAD}, + seed = 31441, + octaves = 2, + persist = 0.5, + lacunarity = 2 +} + +local pn_wind_speed_z = { + offset = 0, + scale = WIND_SCALE, + spread = {x = WIND_SPREAD, y = WIND_SPREAD, z = WIND_SPREAD}, + seed = 938402, + octaves = 2, + persist = 0.5, + lacunarity = 2 +} + +local pn_heat = { + offset = 0, + scale = HEAT_SCALE, + spread = {x = HEAT_SPREAD, y = HEAT_SPREAD, z = HEAT_SPREAD}, + seed = 24, + octaves = 2, + persist = 0.5, + lacunarity = 2 +} + +local pn_humidity = { + offset = 0, + scale = HUMIDITY_SCALE, + spread = {x = HUMIDITY_SPREAD, y = HUMIDITY_SPREAD, z = HUMIDITY_SPREAD}, + seed = 8374061, + octaves = 3, + persist = 0.5, + lacunarity = 2 +} + +local function update_wind(timer) + nobj_wind_x = nobj_wind_x or minetest.get_perlin(pn_wind_speed_x) + nobj_wind_z = nobj_wind_z or minetest.get_perlin(pn_wind_speed_z) + local n_wind_x = nobj_wind_x:get_2d({x = timer, y = 0}) + local n_wind_z = nobj_wind_z:get_2d({x = timer, y = 0}) + climate_mod.state:set_int("wind_x", n_wind_x) + climate_mod.state:set_int("wind_z", n_wind_z) +end + +local function update_heat(timer) + nobj_heat = nobj_heat or minetest.get_perlin(pn_heat) + local n_heat = nobj_heat:get_2d({x = timer, y = 0}) + climate_mod.state:set_int("heat_random", n_heat) +end + +local function update_humidity(timer) + nobj_humidity = nobj_humidity or minetest.get_perlin(pn_humidity) + local n_humidity = nobj_humidity:get_2d({x = timer, y = 0}) + climate_mod.state:set_int("humidity_random", n_humidity) +end + +local function update_date() + local time = minetest.get_timeofday() + if time < climate_mod.state:get_int("time_last_check") then + local day = climate_mod.state:get_int("time_current_day") + climate_mod.state:set_int("time_current_day ", day + 1) + end + climate_mod.state:set_int("time_last_check", time) +end + +function world.update_status(timer) + update_date() + update_wind(timer) + update_heat(timer) + update_humidity(timer) +end + +return world \ No newline at end of file diff --git a/mod.conf b/mod.conf index 6ed93c4..594b9b6 100644 --- a/mod.conf +++ b/mod.conf @@ -1,4 +1,9 @@ -name = believable_weather -title = Believable Weather +name = climate_api +title = Climate API author = TestificateMods -release = 1 \ No newline at end of file +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. +""" \ No newline at end of file diff --git a/settingtypes.txt b/settingtypes.txt index 2004cb8..f7e666a 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -1,17 +1,8 @@ -believable_weather_damage (Storms and hail cause damage) bool true -believable_weather_particles (Show particle effects) bool true -believable_weather_leaves (Leave color changes in autumn) bool true -believable_weather_snow_layers (Place snow layers on ground) bool true -believable_weather_puddles (Place rain puddles on ground) bool true -believable_weather_skybox (Darken sky during rain) bool true -believable_weather_raycasting (Use more accurate indoors check) bool false -believable_weather_wind (Allow wind to angle rainfall) bool true -believable_weather_wind_slow (Allow wind to impact movement speed) bool true -believable_weather_flowers (Flowers will respawn in spring and die in winter) bool true -believable_weather_fruit (Apples and other fruits will regrow) bool true -believable_weather_soil (Soil turns wet during rain) bool true -believable_weather_seasons (Use seasons instead of permanent summer) bool true -believable_weather_base_heat (Base temperature) float 0 -believable_weather_base_humidity (Base humidity) float 0 -believable_weather_max_height (Maximum height of weather effects) int 120 -believable_weather_min_height (Minimum height of weather effects) int -50 \ No newline at end of file +climate_api_particles (Show particle effects) bool true +climate_api_skybox (Allow weather effects to modify the skybox) bool true +climate_api_sound (Allow weather presets to play ambient sounds) bool true +climate_api_clouds (Override clouds to represent current humidity) bool true +climate_api_wind (Allow wind to angle rainfall) bool true +climate_api_seasons (Change global temperature based on an annual cycle) bool true +climate_api_heat_base (Global base temperature) float 0 +climate_api_humidity_base (Global base humidity) float 0 \ No newline at end of file diff --git a/sounds/weather_hail.ogg b/sounds/weather_hail.ogg deleted file mode 100644 index 0206a9c..0000000 Binary files a/sounds/weather_hail.ogg and /dev/null differ diff --git a/sounds/weather_rain.0.ogg b/sounds/weather_rain.0.ogg deleted file mode 100644 index acff009..0000000 Binary files a/sounds/weather_rain.0.ogg and /dev/null differ diff --git a/sounds/weather_rain.ogg b/sounds/weather_rain.ogg deleted file mode 100644 index acff009..0000000 Binary files a/sounds/weather_rain.ogg and /dev/null differ diff --git a/sounds/weather_wind.ogg b/sounds/weather_wind.ogg deleted file mode 100644 index 4656ca5..0000000 Binary files a/sounds/weather_wind.ogg and /dev/null differ diff --git a/textures/weather_hail1.png b/textures/weather_hail1.png deleted file mode 100644 index c052410..0000000 Binary files a/textures/weather_hail1.png and /dev/null differ diff --git a/textures/weather_hail2.png b/textures/weather_hail2.png deleted file mode 100644 index d5af6ed..0000000 Binary files a/textures/weather_hail2.png and /dev/null differ diff --git a/textures/weather_hail3.png b/textures/weather_hail3.png deleted file mode 100644 index 00860d3..0000000 Binary files a/textures/weather_hail3.png and /dev/null differ diff --git a/textures/weather_hail4.png b/textures/weather_hail4.png deleted file mode 100644 index b2bd4b3..0000000 Binary files a/textures/weather_hail4.png and /dev/null differ diff --git a/textures/weather_hail5.png b/textures/weather_hail5.png deleted file mode 100644 index c7c19de..0000000 Binary files a/textures/weather_hail5.png and /dev/null differ diff --git a/textures/weather_pollen.png b/textures/weather_pollen.png deleted file mode 100644 index 713e045..0000000 Binary files a/textures/weather_pollen.png and /dev/null differ diff --git a/textures/weather_puddle.png b/textures/weather_puddle.png deleted file mode 100644 index de62861..0000000 Binary files a/textures/weather_puddle.png and /dev/null differ diff --git a/textures/weather_rain.png b/textures/weather_rain.png deleted file mode 100644 index 39b153c..0000000 Binary files a/textures/weather_rain.png and /dev/null differ diff --git a/textures/weather_raindrop.png b/textures/weather_raindrop.png deleted file mode 100644 index 1e4d3ac..0000000 Binary files a/textures/weather_raindrop.png and /dev/null differ diff --git a/textures/weather_sand.png b/textures/weather_sand.png deleted file mode 100644 index 148a04d..0000000 Binary files a/textures/weather_sand.png and /dev/null differ diff --git a/textures/weather_snow.png b/textures/weather_snow.png deleted file mode 100644 index 7ae6c77..0000000 Binary files a/textures/weather_snow.png and /dev/null differ diff --git a/textures/weather_snow_cover.png b/textures/weather_snow_cover.png deleted file mode 100644 index 9221a5a..0000000 Binary files a/textures/weather_snow_cover.png and /dev/null differ diff --git a/textures/weather_snowflake1.png b/textures/weather_snowflake1.png deleted file mode 100644 index ebe7d72..0000000 Binary files a/textures/weather_snowflake1.png and /dev/null differ diff --git a/textures/weather_snowflake10.png b/textures/weather_snowflake10.png deleted file mode 100644 index 504b9de..0000000 Binary files a/textures/weather_snowflake10.png and /dev/null differ diff --git a/textures/weather_snowflake11.png b/textures/weather_snowflake11.png deleted file mode 100644 index fb9d678..0000000 Binary files a/textures/weather_snowflake11.png and /dev/null differ diff --git a/textures/weather_snowflake12.png b/textures/weather_snowflake12.png deleted file mode 100644 index eab36a8..0000000 Binary files a/textures/weather_snowflake12.png and /dev/null differ diff --git a/textures/weather_snowflake2.png b/textures/weather_snowflake2.png deleted file mode 100644 index 0efdae4..0000000 Binary files a/textures/weather_snowflake2.png and /dev/null differ diff --git a/textures/weather_snowflake3.png b/textures/weather_snowflake3.png deleted file mode 100644 index cdefe2b..0000000 Binary files a/textures/weather_snowflake3.png and /dev/null differ diff --git a/textures/weather_snowflake4.png b/textures/weather_snowflake4.png deleted file mode 100644 index e6b9cc1..0000000 Binary files a/textures/weather_snowflake4.png and /dev/null differ diff --git a/textures/weather_snowflake5.png b/textures/weather_snowflake5.png deleted file mode 100644 index b16111e..0000000 Binary files a/textures/weather_snowflake5.png and /dev/null differ diff --git a/textures/weather_snowflake6.png b/textures/weather_snowflake6.png deleted file mode 100644 index b64ad12..0000000 Binary files a/textures/weather_snowflake6.png and /dev/null differ diff --git a/textures/weather_snowflake7.png b/textures/weather_snowflake7.png deleted file mode 100644 index ea0b7e5..0000000 Binary files a/textures/weather_snowflake7.png and /dev/null differ diff --git a/textures/weather_snowflake8.png b/textures/weather_snowflake8.png deleted file mode 100644 index c2a5708..0000000 Binary files a/textures/weather_snowflake8.png and /dev/null differ diff --git a/textures/weather_snowflake9.png b/textures/weather_snowflake9.png deleted file mode 100644 index ce3b0a0..0000000 Binary files a/textures/weather_snowflake9.png and /dev/null differ diff --git a/weathers/hail.lua b/weathers/hail.lua deleted file mode 100644 index 535ef33..0000000 --- a/weathers/hail.lua +++ /dev/null @@ -1,38 +0,0 @@ -local name = weather_mod.modname .. ":hail" - -local config = {} - -config.environment = { - spawn_puddles = true, - lightning = true, - damage = true -} - -config.sound = { - name = "weather_hail", - gain = 1 -} - -config.particles = { - min_pos = {x=-9, y=7, z=-9}, - max_pos = {x= 9, y=7, z= 9}, - falling_speed=15, - amount=5, - exptime=0.8, - size=1, - textures = {} -} - -for i = 1,5,1 do - config.particles.textures[i] = "weather_hail" .. i .. ".png" -end - -config.conditions = { - min_height = weather_mod.settings.min_height, - max_height = weather_mod.settings.max_height, - max_heat = 45, - min_humidity = 65, - min_windspeed = 2.5 -} - -weather_mod.register_effect(name, config) diff --git a/weathers/pollen.lua b/weathers/pollen.lua deleted file mode 100644 index e6c52a3..0000000 --- a/weathers/pollen.lua +++ /dev/null @@ -1,26 +0,0 @@ -local name = weather_mod.modname .. ":pollen" - -local config = {} - -config.environment = {} - -config.particles = { - min_pos = {x=-12, y=-4, z=-12}, - max_pos = {x= 12, y= 1, z= 12}, - falling_speed=-0.1, - amount=2, - exptime=5, - size=1, - texture="weather_pollen.png" -} - -config.conditions = { - min_height = weather_mod.settings.min_height, - max_height = weather_mod.settings.max_height, - min_heat = 40, - min_humidity = 30, - max_humidity = 40, - max_windspeed = 2 -} - -weather_mod.register_effect(name, config) diff --git a/weathers/rain.lua b/weathers/rain.lua deleted file mode 100644 index 0686c34..0000000 --- a/weathers/rain.lua +++ /dev/null @@ -1,48 +0,0 @@ -local name = weather_mod.modname .. ":rain" - -local config = {} - -config.environment = { - spawn_puddles = true, - wetten_farmland = true -} - -config.sound = { - name = "weather_rain", - gain = 1 -} - -config.particles = { - min_pos = {x=-9, y=7, z=-9}, - max_pos = {x= 9, y=7, z= 9}, - falling_speed=10, - amount=40, - exptime=0.8, - size=1, - texture = "weather_raindrop.png" -} - -config.conditions = { - min_height = weather_mod.settings.min_height, - max_height = weather_mod.settings.max_height, - min_heat = 30, - min_humidity = 40, - max_humidity = 60 -} - -local function override(params) - local avg_humidity = 40 - local intensity = params.humidity / avg_humidity - local dynamic_config = { - sound = { - gain = math.min(intensity, 1.2) - }, - particles = { - amount = 20 * math.min(intensity, 1.5), - falling_speed = 10 / math.min(intensity, 1.3) - } - } - return dynamic_config -end - -weather_mod.register_effect(name, config, override) diff --git a/weathers/rain_heavy.lua b/weathers/rain_heavy.lua deleted file mode 100644 index 018851b..0000000 --- a/weathers/rain_heavy.lua +++ /dev/null @@ -1,33 +0,0 @@ -local name = weather_mod.modname .. ":rain_heavy" - -local config = {} - -config.environment = { - spawn_puddles = true, - wetten_farmland = true, - lightning = true -} - -config.sound = { - name = "weather_rain", - gain = 1 -} - -config.particles = { - min_pos = {x=-9, y=7, z=-9}, - max_pos = {x= 9, y=7, z= 9}, - falling_speed=10, - amount=20, - exptime=0.8, - size=25, - texture="weather_rain.png" -} - -config.conditions = { - min_height = weather_mod.settings.min_height, - max_height = weather_mod.settings.max_height, - min_heat = 30, - min_humidity = 60 -} - -weather_mod.register_effect(name, config) diff --git a/weathers/sandstorm.lua b/weathers/sandstorm.lua deleted file mode 100644 index e5cb989..0000000 --- a/weathers/sandstorm.lua +++ /dev/null @@ -1,27 +0,0 @@ -local name = weather_mod.modname .. ":sandstorm" - -local config = {} - -config.environment = { - damage = true -} - -config.particles = { - min_pos = {x=-9, y=-5, z=-9}, - max_pos = {x= 9, y= 5, z= 9}, - falling_speed=1, - amount=40, - exptime=0.8, - size=15, - texture="weather_sand.png" -} - -config.conditions = { - min_height = weather_mod.settings.min_height, - max_height = weather_mod.settings.max_height, - min_heat = 50, - max_humidity = 25, - min_windspeed = 6 -} - -weather_mod.register_effect(name, config) diff --git a/weathers/snow.lua b/weathers/snow.lua deleted file mode 100644 index 80b7ed6..0000000 --- a/weathers/snow.lua +++ /dev/null @@ -1,46 +0,0 @@ -local name = weather_mod.modname .. ":snow" - -local config = {} - -config.environment = { - spawn_snow = true -} - -config.particles = { - min_pos = {x=-20, y= 3, z=-20}, - max_pos = {x= 20, y=12, z= 20}, - falling_speed=1, - amount=40, - exptime=8, - size=1, - textures = {} -} - -for i = 1,12,1 do - config.particles.textures[i] = "weather_snowflake" .. i .. ".png" -end - -config.conditions = { - min_height = weather_mod.settings.min_height, - max_height = weather_mod.settings.max_height, - max_heat = 40, - min_humidity = 40, - max_humidity = 55 -} - -local function override(params) - local avg_humidity = 40 - local intensity = params.humidity / avg_humidity - local dynamic_config = { - sound = { - gain = math.min(intensity, 1.2) - }, - particles = { - amount = 50 * math.min(intensity, 1.5), - falling_speed = 1 / math.min(intensity, 1.3) - } - } - return dynamic_config -end - -weather_mod.register_effect(name, config, override) diff --git a/weathers/snow_heavy.lua b/weathers/snow_heavy.lua deleted file mode 100644 index 63948c2..0000000 --- a/weathers/snow_heavy.lua +++ /dev/null @@ -1,41 +0,0 @@ -local name = weather_mod.modname .. ":snow_heavy" - -local config = {} - -config.environment = { - spawn_snow = true -} - -config.particles = { - min_pos = {x=-12, y= 5, z=-12}, - max_pos = {x= 12, y=9, z= 12}, - falling_speed=1, - amount=1, - exptime=8, - size=12, - texture="weather_snow.png" -} - -config.conditions = { - min_height = weather_mod.settings.min_height, - max_height = weather_mod.settings.max_height, - max_heat = 40, - min_humidity = 55 -} - -local function override(params) - local avg_humidity = 55 - local intensity = params.humidity / avg_humidity - local dynamic_config = { - sound = { - gain = math.min(intensity, 1.2) - }, - particles = { - amount = 50 * math.min(intensity, 1.5), - falling_speed = 1 / math.min(intensity, 1.3) - } - } - return dynamic_config -end - -weather_mod.register_effect(name, config, override) diff --git a/weathers/storm.lua b/weathers/storm.lua deleted file mode 100644 index 00161e2..0000000 --- a/weathers/storm.lua +++ /dev/null @@ -1,27 +0,0 @@ -local name = weather_mod.modname .. ":storm" - -local config = {} - -config.sound = { - name = "weather_wind", - gain = 1 -} - -config.conditions = { - min_height = weather_mod.settings.min_height, - max_height = weather_mod.settings.max_height, - min_windspeed = 3.5 -} - -local function override(params) - local avg_windspeed = 5 - local intensity = params.windspeed / avg_windspeed - local dynamic_config = { - sound = { - gain = math.min(intensity, 1.2) - } - } - return dynamic_config -end - -weather_mod.register_effect(name, config, override)