Compare commits

...

22 commits

Author SHA1 Message Date
Till Affeldt
e161676210 Fix ambient saturation adjustment 2024-09-27 00:15:31 +02:00
Till Affeldt
6c150faaaf Decrease strength of lighting effects 2023-04-02 10:58:41 +02:00
Till Affeldt
1a20676883 Remove unused translation 2023-04-02 10:58:22 +02:00
Till Affeldt
222f708760 Add additional constraints 2023-02-24 09:51:14 +01:00
Till Affeldt
d04daec67d Reconfigure fog to only show up in the morning and always heavy, remove puddle sound 2023-02-24 08:24:31 +01:00
Till Affeldt
5edea29484 Move check for MTG weather to Climate API instead 2023-02-23 04:33:44 +01:00
Till Affeldt
932546a3d5 Enable shadows, increase puddle transparency, tweak player speed buffs 2023-02-22 05:22:45 +01:00
mazes-80
351c11b3c7
Modernize API calls
* Textures: fix invalid srgb profiles

* Deprecated get_player_velocity -> get_velocity

* Deprecated: boolean value for use_texture_alpha

---------

Co-authored-by: mazes 80 <>
2023-02-22 03:12:24 +01:00
Till Affeldt
4b44f25ef8 Fix crash when MTG weather is enabled 2020-10-10 12:53:48 +02:00
Till Affeldt
f3e6d48b97 use improved indoors check 2020-10-08 22:03:00 +02:00
Till Affeldt
5e2cba0ae8 Delete puddles and snow faster, don't mark puddles as water by default 2020-10-08 15:42:43 +02:00
Till Affeldt
1079f9a762 Make snow griefing optional 2020-10-08 14:29:17 +02:00
Till Affeldt
0fd6942225 Implement i18n support 2020-05-29 22:02:12 +02:00
Till Affeldt
920f80e044 Disable snow in deserts, improve puddle clustering 2020-05-29 21:53:33 +02:00
Till Affeldt
da4062206d Fix minor typo 2020-05-16 16:28:47 +02:00
Till Affeldt
ffdbdf792e Fix MTG warning, add configurability for lightning chances, nerf movement penalties 2020-05-16 16:20:47 +02:00
Till Affeldt
e6f0067f3b Add feature toggles for movement modifier and hydrating puddles 2020-05-16 05:02:01 +02:00
Till Affeldt
a0c56052dd Bump version number 2020-05-13 16:05:54 +02:00
Till Affeldt
2d289abbd1 Update to new wind system, make puddles rotational, change hail conditions 2020-05-13 16:05:21 +02:00
Till Affeldt
e874daa894 Adjust lightning chances and update speed buff to new API 2020-05-12 16:01:13 +02:00
Till Affeldt
231642af2f Update to new particle API, improve night visibility, move damage effect, improve cloud height calculation 2020-04-28 01:23:46 +02:00
Till Affeldt
72716122d7 Improve heavy snow performance, add pedology support, add documentation 2020-04-26 18:10:46 +02:00
31 changed files with 619 additions and 357 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*.code-workspace

View file

@ -25,6 +25,7 @@ The following mods are recommended to be installed alongside Regional Weather:
- [Lightning](https://github.com/minetest-mods/lightning): Adds to heavy rain by enabling additional lightning effects
- [Farming](https://github.com/minetest/minetest_game/tree/master/mods/farming) (as part of MTG) or [Farming Redo](https://forum.minetest.net/viewtopic.php?t=9019): Add farmland and crops to grow food. Farmland wil turn wet during rain effects.
- [Fire](https://github.com/minetest/minetest_game/tree/master/mods/fire) (as part of MTG): Adds fires that can be caused by lightning strikes and other effects and will be extinguished during rain effects.
- [Pedology](https://forum.minetest.net/viewtopic.php?f=11&t=9429) Adds a lot of nodes with dynamic wetness and dryness states.
- [Ambience](https://notabug.org/TenPlus1/ambience): Plays some nice ambient sound effects based on where you are.
For easier installation, you can get a lot of these mods as part of my [Climate Modpack](https://github.com/t-affeldt/climate).
@ -35,8 +36,6 @@ Go to ``Settings → All Settings → Mods → regional_weather`` to change them
Also check out the options inside the ``climate_api`` section for additional configuration options, including performance tweaks and feature switches.
### Features
- ``Cause player damage`` (default true):
If set to true, sand storms and hail will damage affected players over time.
- ``Place snow layers`` (default true):
If set to true, snow layers will stack up during snowy weather.
- ``Freeze river water`` (default true):
@ -50,6 +49,9 @@ Also check out the options inside the ``climate_api`` section for additional con
- ``Extinguish fire`` (bool true):
If set to true, fires will be extinguished during rain showers.
Requires *fire* mod.
- ``Wetten pedology nodes`` (default true):
If set to true, rain will wetten or dry nodes from pedology mod.
Requires *pedology* mod.
### World Configuration
- ``Maximum height of weather effects`` (default 120):
@ -58,6 +60,10 @@ Also check out the options inside the ``climate_api`` section for additional con
- ``Minimum height of weather effects`` (default -50):
No visual effects will be applied below this height.
This will prevent unwanted visuals within large underground caves.
- ``Cloud height`` (default 120)
Average height of cloud bases
- ``Cloud height variation`` (default 40)
Maxmial variation of cloud height from base value
## License information
### Source Code
@ -81,7 +87,6 @@ The entire source code is available on [Github](https://github.com/t-affeldt/reg
- Light Rain sounds: *CC BY 3.0* by Arctura from https://freesound.org/people/Arctura/sounds/34065/
- 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/
- Puddle footstep sound: *CC0* by swordofkings128 from https://freesound.org/people/swordofkings128/sounds/398032/
### HUD Overlays
- Frost HUD: *CC BY-SA (3.0)* by Cap

View file

@ -12,9 +12,11 @@ climate_api.register_abm({
conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_humidity = 55,
min_humidity = 50,
min_biome_humidity = 26,
max_heat = 85,
daylight = 15
daylight = 15,
indoors = false
},
action = function (pos, node, env)

View file

@ -5,12 +5,22 @@ then return end
local BLOCK_NAME = "regional_weather:ice"
local S = regional_weather.i18n
minetest.register_node(BLOCK_NAME, {
description = S("Thin Ice"),
tiles = {"(default_ice.png^[colorize:#ffffff:50)^[opacity:200"},
paramtype = "light",
groups = {cracky = 3, cools_lava = 1, slippery = 3, dig_immediate = 2},
groups = {
cracky = 3,
cools_lava = 1,
slippery = 3,
dig_immediate = 2,
melts = 1
},
freezemelt = "default:river_water_source",
sounds = default.node_sound_glass_defaults(),
use_texture_alpha = true,
use_texture_alpha = "blend",
drop = "",
on_destruct = function(pos)
-- asynchronous to avoid destruction loop
@ -32,8 +42,9 @@ climate_api.register_abm({
conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
max_heat = 25,
daylight = 15
max_heat = 35,
daylight = 15,
indoors = false
},
action = function (pos, node, env)
@ -51,8 +62,9 @@ climate_api.register_abm({
conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_heat = 40,
daylight = 15
min_heat = 35,
daylight = 15,
indoors = false
},
action = function (pos, node, env)

29
abms/pedology.lua Normal file
View file

@ -0,0 +1,29 @@
if not regional_weather.settings.pedology
or not minetest.get_modpath("pedology")
then return end
climate_api.register_abm({
label = "wetten or dry pedology nodes",
nodenames = { "group:sucky" },
neighbors = { "air" },
interval = 25,
chance = 30,
catch_up = false,
conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_heat = 25,
daylight = 15,
indoors = false,
},
action = function (pos, node, env)
local wetness = minetest.get_item_group(node.name, "wet") or 0
if wetness < 2 and env.humidity > 50 then
pedology.wetten(pos)
elseif wetness > 0 and wetness < 3 and env.humidity < 40 then
pedology.dry(pos)
end
end
})

View file

@ -1,98 +1,130 @@
local BLOCK_PREFIX = "regional_weather:puddle_"
local VARIANT_COUNT = 39
local MIN_DISTANCE = 4
local CHECK_DISTANCE = 4
local MAX_AMOUNT = 3
local GROUND_COVERS = {
"group:soil",
"group:stone",
"group:sand",
"group:wood",
"default:permafrost",
"default:permafrost_with_moss",
"default:permafrost_with_stones"
}
local S = regional_weather.i18n
-- clean up puddles if disabled
if not regional_weather.settings.puddles then
for i=1,VARIANT_COUNT do
for r=0,270,90 do
minetest.register_alias(BLOCK_PREFIX .. i .. "_" .. r, "air")
-- set all puddle nodes to air
minetest.register_alias("regional_weather:puddle", "air")
for i = 1, VARIANT_COUNT do
for flip = 0, 1 do
local name = BLOCK_PREFIX .. i
if flip == 1 then
name = name .. "_flipped"
end
minetest.register_alias(name, "air")
end
end
-- return air instead of a puddle
function regional_weather.get_random_puddle()
return { name = "air" }
end
-- end puddle execution
return
end
local node_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -0.49, 0.5}
fixed = { -0.5, -0.5, -0.5, 0.5, -0.49, 0.5 }
}
for i = 1,VARIANT_COUNT do
for rotation = 0,270,90 do
for flip = 0,1 do
local name = BLOCK_PREFIX .. i .. "_" .. rotation
local index = i
if i < 10 then index = "0" .. i end
local texture = "weather_puddle_" .. index .. ".png^[opacity:128"
if flip == 1 or rotation > 0 then
texture = texture .. "^[transform"
end
if flip == 1 then
name = name .. "_flipped"
texture = texture .. "FX"
end
if rotation > 0 then
texture = texture .. "R" .. rotation
end
minetest.register_node(name, {
tiles = { texture },
drawtype = "nodebox",
pointable = false,
buildable_to = true,
floodable = true,
walkable = false,
sunlight_propagates = true,
paramtype = "light",
use_texture_alpha = true,
node_box = node_box,
groups = {
not_in_creative_inventory = 1,
crumbly = 3,
attached_node = 1,
slippery = 1,
flora = 1,
water = 1,
regional_weather_puddle = 1
},
drop = "",
sounds = {
footstep = {
name = "weather_puddle",
gain = 0.8
}
}
})
local apply_water_group
if regional_weather.settings.puddles_water then
apply_water_group = 1
end
for i = 1, VARIANT_COUNT do
for flip = 0, 1 do
local name = BLOCK_PREFIX .. i
local index = i
if i < 10 then index = "0" .. i end
local texture = "weather_puddle_" .. index .. ".png^[opacity:24"
if flip == 1 then
name = name .. "_flipped"
texture = texture .. "^[transformFX"
end
minetest.register_node(name, {
description = S("Puddle"),
tiles = { texture },
drawtype = "nodebox",
pointable = false,
buildable_to = true,
floodable = true,
walkable = false,
sunlight_propagates = true,
paramtype = "light",
paramtype2 = "facedir",
use_texture_alpha = "blend",
node_box = node_box,
groups = {
not_in_creative_inventory = 1,
crumbly = 3,
attached_node = 1,
slippery = 1,
flora = 1,
water = apply_water_group,
weather_puddle = 1
},
drop = ""
})
end
end
minetest.register_alias("regional_weather:puddle", BLOCK_PREFIX .. "14_0")
minetest.register_alias("regional_weather:puddle", BLOCK_PREFIX .. "14")
local function get_random_puddle()
function regional_weather.get_random_puddle()
local index = math.random(1, VARIANT_COUNT)
local rotation = math.random(0, 3) * 90
local flip = math.random(0, 1)
local name = BLOCK_PREFIX .. index .. "_" .. rotation
local name = BLOCK_PREFIX .. index
if flip == 1 then
name = name .. "_flipped"
end
return name
local param2 = minetest.dir_to_facedir(minetest.yaw_to_dir(rotation))
return { name = name, param2 = param2 }
end
-- Makes Puddles when raining
climate_api.register_abm({
label = "create rain puddles",
nodenames = { "group:soil", "group:stone" },
nodenames = GROUND_COVERS,
neighbors = { "air" },
interval = 15,
chance = 50,
interval = 8,
chance = 150,
catch_up = false,
conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_humidity = 55,
min_heat = 30,
daylight = 15
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_heat = 35,
min_humidity = 50,
min_biome_humidity = 26,
daylight = 15,
indoors = false,
not_biome = {
"cold_desert",
"cold_desert_ocean",
"desert",
"desert_ocean",
"sandstone_desert",
"sandstone_desert_ocean",
"tundra"
}
},
pos_override = function(pos)
@ -100,26 +132,28 @@ climate_api.register_abm({
end,
action = function (pos, node, env)
-- only override air nodes
if minetest.get_node(pos).name ~= "air" then return end
if minetest.find_node_near(pos, MIN_DISTANCE, "group:regional_weather_puddle") then return end
local puddle_name = get_random_puddle()
minetest.set_node(pos, {name = puddle_name})
-- do not place puddle if area is not fully loaded
if minetest.find_node_near(pos, CHECK_DISTANCE, "ignore") then return end
-- do not place puddle if already enpugh puddles
local pos1 = vector.add(pos, { x = -CHECK_DISTANCE, y = -1, z = -CHECK_DISTANCE })
local pos2 = vector.add(pos, { x = CHECK_DISTANCE, y = 1, z = CHECK_DISTANCE })
local preplaced = minetest.find_nodes_in_area(pos1, pos2, "group:weather_puddle")
if preplaced ~= nil and #preplaced >= MAX_AMOUNT then return end
minetest.set_node(pos, regional_weather.get_random_puddle())
end
})
-- Makes puddles dry up when not raining
climate_api.register_abm({
label = "remove rain puddles",
nodenames = { "group:regional_weather_puddle" },
interval = 10,
chance = 3,
nodenames = { "group:weather_puddle" },
interval = 25,
chance = 30,
catch_up = true,
action = function (pos, node, env)
if env.humidity < 55 then
minetest.remove_node(pos)
elseif env.heat < 30 and regional_weather.settings.snow_cover then
minetest.set_node(pos, {name = "regional_weather:snow_cover_1"})
end
minetest.remove_node(pos)
end
})

View file

@ -1,4 +1,8 @@
local BLOCK_PREFIX = "regional_weather:snow_cover_"
local CHECK_DISTANCE = 5
local MAX_AMOUNT = 20
local S = regional_weather.i18n
if not minetest.get_modpath("default")
or default.node_sound_snow_defaults == nil
@ -23,6 +27,7 @@ for i = 1,5 do
}
minetest.register_node(BLOCK_PREFIX .. i, {
description = S("Snow Cover"),
tiles = { "default_snow.png" },
drawtype = "nodebox",
buildable_to = i < 3,
@ -35,7 +40,7 @@ for i = 1,5 do
crumbly = 3,
falling_node = 1,
snowy = 1,
regional_weather_snow_cover = i
weather_snow_cover = i
},
sounds = default.node_sound_snow_defaults(),
drop = "default:snow " .. math.ceil(i / 2),
@ -61,15 +66,25 @@ climate_api.register_abm({
},
neighbors = { "air" },
interval = 25,
chance = 40,
chance = 80,
catch_up = false,
conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_humidity = 55,
max_heat = 30,
daylight = 15
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
max_heat = 35,
min_humidity = 50,
min_biome_humidity = 26,
not_biome = {
"cold_desert",
"cold_desert_ocean",
"desert",
"desert_ocean",
"sandstone_desert",
"sandstone_desert_ocean"
},
daylight = 15,
indoors = false
},
pos_override = function(pos)
@ -77,66 +92,88 @@ climate_api.register_abm({
end,
action = function (pos, node, env)
if minetest.get_node(pos).name ~= "air" then return end
local base = minetest.get_node(vector.add(pos, {x=0, y=-1, z=0})).name
local is_soil = minetest.get_item_group(base, "soil") or 0
local is_stone = minetest.get_item_group(base, "stone") or 0
if not (is_soil == 0 and is_stone == 0) then
minetest.set_node(pos, { name = BLOCK_PREFIX .. "1" })
end
-- only override air nodes
if node.name ~= "air" then return end
-- do not place snow if area is not fully loaded
if minetest.find_node_near(pos, CHECK_DISTANCE, "ignore") then return end
-- do not place snow if already enpugh snow
local pos1 = vector.add(pos, { x = -CHECK_DISTANCE, y = -1, z = -CHECK_DISTANCE })
local pos2 = vector.add(pos, { x = CHECK_DISTANCE, y = 1, z = CHECK_DISTANCE })
local preplaced = minetest.find_nodes_in_area(pos1, pos2, "group:weather_snow_cover")
if preplaced ~= nil and #preplaced >= MAX_AMOUNT then return end
minetest.set_node(pos, { name = BLOCK_PREFIX .. "1" })
end
})
climate_api.register_abm({
label = "replace flora with snow covers and stack covers higher",
nodenames = {
"group:flora",
"group:grass",
"group:plant",
"group:regional_weather_snow_cover"
},
neighbors = { "air" },
interval = 25,
chance = 30,
catch_up = false,
if regional_weather.settings.snow_griefing then
climate_api.register_abm({
label = "replace flora with snow covers and stack covers higher",
nodenames = {
"group:flora",
"group:grass",
"group:plant",
"group:weather_snow_cover"
},
neighbors = { "air" },
interval = 25,
chance = 160,
catch_up = false,
conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_humidity = 55,
max_heat = 30,
daylight = 15
},
conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_humidity = 55,
max_heat = 30,
not_biome = {
"cold_desert",
"cold_desert_ocean",
"desert",
"desert_ocean",
"sandstone_desert",
"sandstone_desert_ocean"
},
daylight = 15,
indoors = false
},
action = function (pos, node, env)
local node_name = minetest.get_node(pos).name
local value = minetest.get_item_group(node_name, "regional_weather_snow_cover")
if value == nil then value = 0 end
if value < 5 then
minetest.set_node(pos, { name = BLOCK_PREFIX .. (value + 1) })
action = function (pos, node, env)
local value = minetest.get_item_group(node.name, "weather_snow_cover") or 0
if value == 0 then
-- do not override plants unless marked as buildable_to
local def = minetest.registered_nodes[node.name]
if def == nil or not def.buildable_to then return end
-- do not override plants of the frost_resistance group
local resistance = minetest.get_item_group(node.name, "frost_resistance") or 0
if resistance > 0 then return end
end
-- do not place snow if area is not fully loaded
if minetest.find_node_near(pos, CHECK_DISTANCE, "ignore") then return end
-- do not place snow if already enpugh snow
local pos1 = vector.add(pos, { x = -CHECK_DISTANCE, y = -1, z = -CHECK_DISTANCE })
local pos2 = vector.add(pos, { x = CHECK_DISTANCE, y = 1, z = CHECK_DISTANCE })
local preplaced = minetest.find_nodes_in_area(pos1, pos2, "group:weather_snow_cover")
if preplaced ~= nil and #preplaced >= MAX_AMOUNT then return end
if value < 5 then
minetest.set_node(pos, { name = BLOCK_PREFIX .. (value + 1) })
end
end
end
})
})
end
climate_api.register_abm({
label = "melt snow covers",
nodenames = { "group:regional_weather_snow_cover" },
nodenames = { "group:weather_snow_cover" },
interval = 25,
chance = 10,
chance = 85,
catch_up = true,
conditions = {
min_heat = 30
},
action = function (pos, node, env)
local node_name = minetest.get_node(pos).name
local value = minetest.get_item_group(node_name, "regional_weather_snow_cover")
local value = minetest.get_item_group(node.name, "weather_snow_cover")
if value == nil then value = 0 end
if value > 1 then
minetest.set_node(pos, { name = BLOCK_PREFIX .. (value - 1) })
elseif regional_weather.settings.puddles then
minetest.set_node(pos, { name = "regional_weather:puddle" })
minetest.set_node(pos, regional_weather.get_random_puddle())
else
minetest.set_node(pos, { name = "air" })
end

View file

@ -12,9 +12,10 @@ if farming ~= nil and farming.mod == "redo" then
conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_humidity = 55,
min_heat = 30,
min_light = 15
min_humidity = 50,
min_heat = 35,
daylight = 15,
indoors = false
},
action = function (pos, node, env)
@ -33,9 +34,10 @@ else
conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_humidity = 55,
min_heat = 30,
min_light = 15
min_humidity = 50,
min_heat = 35,
daylight = 15,
indoors = false
},
action = function (pos, node, env)

View file

@ -1,22 +0,0 @@
if not minetest.is_yes(minetest.settings:get_bool("enable_damage"))
or not regional_weather.settings.damage then return end
local EFFECT_NAME = "regional_weather:damage"
local rng = PcgRandom(7819792)
local function handle_effect(player_data)
for playername, data in pairs(player_data) do
local player = minetest.get_player_by_name(playername)
local hp = player:get_hp()
for weather, dmg in pairs(data) do
if rng:next(1, dmg.chance) == 1 then
hp = hp - dmg.value
end
end
player:set_hp(hp, "weather damage")
end
end
climate_api.register_effect(EFFECT_NAME, handle_effect, "tick")
climate_api.set_effect_cycle(EFFECT_NAME, climate_api.MEDIUM_CYCLE)

View file

@ -1,8 +1,15 @@
--[[
# Lightning Effect
Use this effect to cause lightning strikes.
Requires lightning mod in order to function. Uses default lightning configuration.
Expects an integer indicating a chance (between 0 and 1) for lightning to strike (per cycle and player).
]]
if not minetest.get_modpath("lightning") then return end
if regional_weather.settings.lightning == 0 then return end
local EFFECT_NAME = "regional_weather:lightning"
local LIGHTNING_CHANCE = 20
lightning.auto = false
local rng = PcgRandom(82492402425)
@ -32,8 +39,15 @@ end
local function handle_effect(player_data)
for playername, data in pairs(player_data) do
local random = rng:next(1, LIGHTNING_CHANCE)
if random == 1 then
local chance = 0
for weather, value in pairs(data) do
if type(value) ~= "number" then
value = 1/20
end
chance = chance + value - (chance * value)
end
local random = math.random()
if random <= chance * regional_weather.settings.lightning then
local player = minetest.get_player_by_name(playername)
local ppos = player:get_pos()
local position = choose_pos(ppos)

View file

@ -1,3 +1,11 @@
--[[
# Player Speed Effect
Use this effect to modify a player's movement speed.
Expects a numeric value that will be multiplied with the current speed physics.
]]
if not regional_weather.settings.player_speed then return end
local EFFECT_NAME = "regional_weather:speed_buff"
local function handle_effect(player_data)
@ -7,14 +15,14 @@ local function handle_effect(player_data)
for weather, value in pairs(data) do
product = product * value
end
climate_api.utility.add_physics(EFFECT_NAME, player, "speed", product)
climate_api.player_physics.add(EFFECT_NAME, player, "speed", product)
end
end
local function remove_effect(player_data)
for playername, data in ipairs(player_data) do
local player = minetest.get_player_by_name(playername)
climate_api.utility.remove_physics(EFFECT_NAME, player, "speed")
climate_api.player_physics.remove(EFFECT_NAME, player, "speed")
end
end

View file

@ -1,19 +1,62 @@
local name = "regional_weather:ambient"
local CLOUD_SPEED = 1.8
local conditions = {}
-- see https://en.wikipedia.org/wiki/Cloud_base
local function calc_cloud_height(heat, humidity, dewpoint)
local base = regional_weather.settings.cloud_height
-- much lower scale like 20 instead of 1000 fitting for Minetest
local scale = regional_weather.settings.cloud_scale
local spread = heat - dewpoint
local variation = spread / 4.4 * scale * 0.3
return base + climate_api.utility.rangelim(variation, -scale, scale)
end
-- maps range of 0 to 1 to any other range
local function map_range(val, low, high)
return val * (high - low) + low
end
local function generate_effects(params)
local override = {}
local wind = climate_api.environment.get_wind()
local cloud_density = climate_api.utility.rangelim(params.humidity / 100, 0.15, 0.65)
local cloud_thickness = climate_api.utility.rangelim(params.biome_humidity * 0.2, 1, 18)
local cloud_height = calc_cloud_height(params.heat, params.humidity, params.dewpoint)
local wind = climate_api.environment.get_wind({ x = 0, y = cloud_height, z = 0 })
-- diffuse shadows when cloudy
-- cloud_shadows at zero at cloud density 0.65 and one at 0.15
local cloud_shadows = 1 - ((cloud_density - 0.15) / (0.65 - 0.15))
-- diffuse shadows at dawn / dusk
-- 15 hours between dawn and dusk accoring to https://wiki.minetest.net/Time_of_day
local daylight_duration = 15 / 24
local daytime = climate_api.utility.rangelim(minetest.get_timeofday(), 0.1875, 0.8125)
-- zero at dawn / dusk and one at midday
local daytime_shadows = 1 - (math.abs(0.5 - daytime) * 2 / daylight_duration)
local shadow_intensity = map_range((cloud_shadows + daytime_shadows) / 2, 0.5, 2)
local light_saturation = map_range((cloud_shadows + daytime_shadows) / 2, 0.75, 1.25)
local skybox = {priority = 10}
skybox.cloud_data = {
density = climate_api.utility.rangelim(params.humidity / 100, 0.25, 0.75),
speed = vector.multiply(wind, CLOUD_SPEED),
thickness = climate_api.utility.rangelim(params.base_humidity * 0.2, 1, 18)
density = cloud_density,
speed = wind,
thickness = cloud_thickness,
height = cloud_height,
ambient = "#0f0f1050"
}
skybox.light_data = {
shadow_intensity = shadow_intensity,
saturation = light_saturation
}
if params.height > -100 and params.humidity > 40 then
skybox.cloud_data.color = "#b2a4a4b0"
end
if params.height > -100 and params.humidity > 65 then
skybox.sky_data = {
type = "regular",
@ -27,20 +70,25 @@ local function generate_effects(params)
night_horizon = "#315d9b"
}
}
skybox.cloud_data.color = "#828e97b5"
skybox.cloud_data.ambient = "#20212250"
end
override["climate_api:skybox"] = skybox
local movement = params.player:get_player_velocity()
local movement_direction
if (vector.length(movement) < 0.1) then
movement_direction = vector.new(0, 0, 0)
else
movement_direction = vector.normalize(movement)
if params.height > - 50 and not params.indoors then
local movement = params.player:get_velocity()
local movement_direction
if (vector.length(movement) < 0.1) then
movement_direction = vector.new(0, 0, 0)
else
movement_direction = vector.normalize(movement)
end
local vector_product = vector.dot(movement_direction, wind)
local movement_penalty = climate_api.utility.sigmoid(vector_product, 1.5, 0.15, 0.9) + 0.2
override["regional_weather:speed_buff"] = movement_penalty
end
local vector_product = vector.dot(movement_direction, wind)
local movement_penalty = climate_api.utility.sigmoid(vector_product, 1.6, 0.2, 0.8) + 0.2
override["regional_weather:speed_buff"] = movement_penalty
return override
end

View file

@ -18,6 +18,10 @@ effects["climate_api:skybox"] = {
},
moon_data = { visible = false },
star_data = { visible = false },
light_data = {
shadow_intensity = 0,
saturation = 1
},
priority = 100
}

View file

@ -3,17 +3,35 @@ local name = "regional_weather:fog"
local conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_humidity = 40,
min_humidity = 25,
max_humidity = 50,
max_windspeed = 2,
min_heat = 40,
max_heat = 50
max_heat = 50,
min_time = 4 / 24,
max_time = 8 / 24,
not_biome = {
"cold_desert",
"cold_desert_ocean",
"desert",
"desert_ocean",
"sandstone_desert",
"sandstone_desert_ocean",
"tundra"
}
}
local effects = {}
effects["climate_api:hud_overlay"] = {
file = "weather_hud_fog.png^[opacity:100",
z_index = -200,
color_correction = true
}
effects["climate_api:skybox"] = {
sky_data = {
type = "plain",
base_color = "#c0c0c08f",
clouds = true
},
cloud_data = {
@ -22,6 +40,10 @@ effects["climate_api:skybox"] = {
thickness = 40,
speed = {x=0,y=0,z=0}
},
light_data = {
shadow_intensity = 0.1,
saturation = 0.5
},
priority = 50
}

View file

@ -1,32 +0,0 @@
local name = "regional_weather:fog_heavy"
local conditions = {
min_height = regional_weather.settings.min_height * 0.9,
max_height = regional_weather.settings.max_height * 0.9,
min_humidity = 43,
max_humidity = 47,
max_windspeed = 1.5,
min_heat = 43,
max_heat = 47
}
local effects = {}
effects["climate_api:hud_overlay"] = {
file = "weather_hud_fog.png^[opacity:100",
z_index = -200,
color_correction = true
}
effects["climate_api:skybox"] = {
sky_data = {
type = "plain",
base_color = "#c0c0c08f"
},
cloud_data = {
color = "#ffffffc0",
},
priority = 51
}
climate_api.register_weather(name, conditions, effects)

View file

@ -1,19 +1,34 @@
local name = "regional_weather:hail"
local conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
max_heat = 45,
min_humidity = 65,
min_windspeed = 2.5,
daylight = 15
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_heat = 30,
max_heat = 45,
min_humidity = 65,
min_biome_humidity = 26,
min_windspeed = 2.5,
indoors = false,
not_biome = {
"cold_desert",
"cold_desert_ocean",
"desert",
"desert_ocean",
"sandstone_desert",
"sandstone_desert_ocean"
}
}
local effects = {}
effects["regional_weather:damage"] = {
chance = 15,
value = 3
effects["climate_api:damage"] = {
rarity = 15,
value = 3,
check = {
type = "raycast",
height = 7,
velocity = 20
}
}
effects["climate_api:sound"] = {
@ -21,18 +36,21 @@ effects["climate_api:sound"] = {
gain = 1
}
effects["climate_api:particles"] = {
min_pos = {x=-9, y=7, z=-9},
max_pos = {x= 9, y=7, z= 9},
falling_speed=20,
amount=6,
exptime=0.7,
size=1,
textures = {}
}
effects["regional_weather:lightning"] = 1 / 30
for i = 1,5,1 do
effects["climate_api:particles"].textures[i] = "weather_hail" .. i .. ".png"
local textures = {}
for i = 1,5 do
textures[i] = "weather_hail" .. i .. ".png"
end
effects["climate_api:particles"] = {
boxsize = { x = 18, y = 0, z = 18 },
v_offset = 7,
velocity = 20,
amount = 6,
expirationtime = 0.7,
texture = textures,
glow = 5
}
climate_api.register_weather(name, conditions, effects)

View file

@ -7,7 +7,7 @@ local conditions = {
min_humidity = 30,
max_humidity = 40,
max_windspeed = 2,
daylight = 15,
indoors = false,
has_biome = {
"default",
"deciduous_forest",
@ -34,14 +34,15 @@ local conditions = {
local effects = {}
effects["climate_api:particles"] = {
min_pos = {x=-12, y=-4, z=-12},
max_pos = {x= 12, y= 1, z= 12},
falling_speed = -0.1,
acceleration = {x=0,y=-0.03,z=0},
amount = 1,
exptime = 5,
boxsize = { x = 24, y = 0, z = 24 },
vbox = 5,
v_offset = -1,
velocity = -0.1,
acceleration = -0.03,
expirationtime = 5,
size = 0.8,
texture = "weather_pollen.png"
texture = "weather_pollen.png",
glow = 2
}
climate_api.register_weather(name, conditions, effects)

View file

@ -1,12 +1,22 @@
local name = "regional_weather:rain"
local conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_heat = 35,
min_humidity = 50,
max_humidity = 65,
daylight = 15
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_heat = 35,
min_humidity = 50,
max_humidity = 65,
min_biome_humidity = 26,
indoors = false,
not_biome = {
"cold_desert",
"cold_desert_ocean",
"desert",
"desert_ocean",
"sandstone_desert",
"sandstone_desert_ocean",
"tundra"
}
}
local effects = {}
@ -17,14 +27,15 @@ effects["climate_api:sound"] = {
}
effects["climate_api:particles"] = {
min_pos = {x=-9, y=8, z=-9},
max_pos = {x= 9, y=6, z= 9},
exptime = 1.1,
boxsize = { x = 18, y = 2, z = 18 },
v_offset = 6,
expirationtime = 1.6,
size = 2,
amount = 15,
falling_speed = 6,
acceleration={x=0, y=-0.05, z=0},
texture = "weather_raindrop.png"
velocity = 6,
acceleration = 0.05,
texture = "weather_raindrop.png",
glow = 5
}
climate_api.register_weather(name, conditions, effects)

View file

@ -1,33 +1,53 @@
local name = "regional_weather:rain_heavy"
local conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_heat = 40,
min_humidity = 65,
daylight = 15
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_heat = 40,
min_humidity = 65,
min_biome_humidity = 26,
indoors = false,
not_biome = {
"cold_desert",
"cold_desert_ocean",
"desert",
"desert_ocean",
"sandstone_desert",
"sandstone_desert_ocean",
"tundra"
}
}
local effects = {}
effects["climate_api:skybox"] = {
cloud_data = {
color = "#5e676eb5"
},
priority = 11
}
effects["climate_api:sound"] = {
name = "weather_rain_heavy",
gain = 1
}
effects["regional_weather:lightning"] = 1 / 20
effects["climate_api:particles"] = {
min_pos = {x=-9, y=7, z=-9},
max_pos = {x= 9, y=7, z= 9},
falling_speed=7,
amount=17,
exptime=0.8,
min_size=25,
max_size=35,
textures={
boxsize = { x = 18, y = 0, z = 18 },
v_offset = 7,
velocity = 7,
amount = 17,
expirationtime = 1.2,
minsize = 25,
maxsize = 35,
texture = {
"weather_rain.png",
"weather_rain.png",
"weather_rain_medium.png"
}
},
glow = 5
}
climate_api.register_weather(name, conditions, effects)

View file

@ -3,16 +3,11 @@ local name = "regional_weather:sandstorm"
local conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_heat = 50,
max_humidity = 25,
min_windspeed = 4.5,
min_windspeed = 3,
has_biome = {
"cold_desert",
"cold_desert_ocean",
"desert",
"desert_ocean",
"sandstone_desert",
"sandstone_desert_ocean"
"sandstone_desert"
}
}
@ -24,22 +19,28 @@ effects["climate_api:hud_overlay"] = {
color_correction = true
}
effects["regional_weather:damage"] = {
chance = 3,
value = 1
effects["climate_api:damage"] = {
rarity = 3,
value = 1,
check = {
type = "raycast",
height = 0,
velocity = 0.3
}
}
effects["climate_api:particles"] = {
min_pos = {x=-5, y=-4, z=-5},
max_pos = {x= 5, y= 4.5, z= 5},
falling_speed=1.2,
acceleration={x=0,y=0.8,z=0},
amount=40,
exptime=1.8,
size=20,
textures={
boxsize = { x = 8, y = 4.5, z = 8 },
velocity = 0.6,
acceleration = -0.2,
amount = 12,
expirationtime = 0.7,
size = 25,
texture = {
"weather_sandstorm.png",
"weather_sandstorm.png^[transformR180"
"weather_sandstorm.png^[transformFY",
"weather_sandstorm.png^[transformR180",
"weather_sandstorm.png^[transformFYR180"
}
}

View file

@ -3,27 +3,37 @@ local name = "regional_weather:snow"
local conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
max_heat = 35,
min_humidity = 50,
max_humidity = 65,
daylight = 15
max_heat = 35,
min_humidity = 50,
max_humidity = 65,
min_biome_humidity = 26,
indoors = false,
not_biome = {
"cold_desert",
"cold_desert_ocean",
"desert",
"desert_ocean",
"sandstone_desert",
"sandstone_desert_ocean"
}
}
local effects = {}
effects["climate_api:particles"] = {
min_pos = {x=-12, y=2, z=-12},
max_pos = {x= 12, y=8, z= 12},
amount = 4,
exptime = 7,
size = 1,
falling_speed = 0.85,
acceleration = {x=0, y=0.06, z=0},
textures = {}
}
local textures = {}
for i = 1,12,1 do
effects["climate_api:particles"].textures[i] = "weather_snowflake" .. i .. ".png"
textures[i] = "weather_snowflake" .. i .. ".png"
end
effects["climate_api:particles"] = {
boxsize = { x = 24, y = 6, z = 24 },
v_offset = 2,
amount = 4,
expirationtime = 7,
velocity = 0.85,
acceleration = -0.06,
texture = textures,
glow = 6
}
climate_api.register_weather(name, conditions, effects)

View file

@ -3,13 +3,29 @@ local name = "regional_weather:snow_heavy"
local conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
max_heat = 30,
min_humidity = 65,
daylight = 15
max_heat = 30,
min_humidity = 65,
min_biome_humidity = 26,
indoors = false,
not_biome = {
"cold_desert",
"cold_desert_ocean",
"desert",
"desert_ocean",
"sandstone_desert",
"sandstone_desert_ocean"
}
}
local effects = {}
effects["climate_api:skybox"] = {
cloud_data = {
color = "#5e676eb5"
},
priority = 11
}
effects["climate_api:hud_overlay"] = {
file = "weather_hud_frost.png",
z_index = -100,
@ -17,24 +33,14 @@ effects["climate_api:hud_overlay"] = {
}
effects["climate_api:particles"] = {
min_pos = {x=-8, y=3, z=-8},
max_pos = {x= 8, y=6, z= 8},
exptime=6,
size=10,
texture="weather_snow.png"
boxsize = { x = 14, y = 3, z = 14 },
v_offset = 3,
expirationtime = 7.5,
size = 15,
amount = 6,
velocity = 0.75,
texture = "weather_snow.png",
glow = 6
}
local function generate_effects(params)
local avg_humidity = 55
local intensity = params.humidity / avg_humidity
local override = {}
override["climate_api:particles"] = {
amount = 16 * math.min(intensity, 1.5),
falling_speed = 1 / math.min(intensity, 1.3)
}
return climate_api.utility.merge_tables(effects, override)
end
climate_api.register_weather(name, conditions, generate_effects)
climate_api.register_weather(name, conditions, effects)

View file

@ -4,7 +4,7 @@ local conditions = {
min_height = regional_weather.settings.min_height,
max_height = regional_weather.settings.max_height,
min_windspeed = 3,
daylight = 15
indoors = false,
}
local effects = {}
@ -19,7 +19,7 @@ local function generate_effects(params)
local override = {}
override["climate_api:sound"] = {
gain = math.min(intensity, 1.2)
gain = math.min(intensity, 1)
}
return climate_api.utility.merge_tables(effects, override)

View file

@ -1,41 +1,46 @@
local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
local function get_setting_bool(name, default)
local value = minetest.settings:get_bool("regional_weather_" .. name)
local function get_setting_bool(name, default, is_global)
local prefix = ""
if not is_global then prefix = "regional_weather_" end
local value = minetest.settings:get_bool(prefix .. name)
if type(value) == "nil" then value = default end
return minetest.is_yes(value)
end
local function get_setting_number(name, default)
local value = minetest.settings:get("regional_weather_" .. name)
local function get_setting_number(name, default, is_global)
local prefix = ""
if not is_global then prefix = "regional_weather_" end
local value = minetest.settings:get(prefix .. name)
if type(value) == "nil" then value = default end
return tonumber(value)
end
regional_weather = {}
regional_weather.settings = {}
regional_weather.settings.damage = get_setting_bool("damage", true)
regional_weather.settings.snow = get_setting_bool("snow_layers", true)
regional_weather.settings.puddles = get_setting_bool("puddles", true)
regional_weather.settings.soil = get_setting_bool("soil", true)
regional_weather.settings.fire = get_setting_bool("fire", true)
regional_weather.settings.ice = get_setting_bool("ice", true)
regional_weather.settings.max_height = get_setting_number("max_height", 120)
regional_weather.settings.min_height = get_setting_number("min_height", -50)
regional_weather.settings.player_speed = get_setting_bool("player_speed", false)
regional_weather.settings.snow = get_setting_bool("snow_layers", true)
regional_weather.settings.snow_griefing = get_setting_bool("snow_griefing", true)
regional_weather.settings.puddles = get_setting_bool("puddles", true)
regional_weather.settings.puddles_water = get_setting_bool("puddles_water", false)
regional_weather.settings.soil = get_setting_bool("soil", true)
regional_weather.settings.fire = get_setting_bool("fire", true)
regional_weather.settings.ice = get_setting_bool("ice", true)
regional_weather.settings.pedology = get_setting_bool("pedology", true)
regional_weather.settings.lightning = get_setting_number("lightning", 1)
regional_weather.settings.max_height = get_setting_number("max_height", 120)
regional_weather.settings.min_height = get_setting_number("min_height", -50)
regional_weather.settings.cloud_height = get_setting_number("cloud_height", 120)
regional_weather.settings.cloud_scale = get_setting_number("cloud_scale", 40)
-- warn about clouds being overriden by MTG weather
if climate_mod.settings.skybox
and minetest.get_modpath("weather")
and get_setting_bool("enable_weather", true) then
minetest.log("warning", "[Regional Weather] Disable MTG weather for the best experience")
end
local S = minetest.get_translator("regional_weather")
regional_weather.i18n = S
-- import individual weather types
dofile(modpath.."/ca_weathers/ambient.lua")
dofile(modpath.."/ca_weathers/deep_cave.lua")
dofile(modpath.."/ca_weathers/fog.lua")
dofile(modpath.."/ca_weathers/fog_heavy.lua")
dofile(modpath.."/ca_weathers/hail.lua")
dofile(modpath.."/ca_weathers/pollen.lua")
dofile(modpath.."/ca_weathers/rain.lua")
@ -46,7 +51,6 @@ dofile(modpath.."/ca_weathers/snow_heavy.lua")
dofile(modpath.."/ca_weathers/storm.lua")
-- register environment effects
dofile(modpath.."/ca_effects/damage.lua")
dofile(modpath.."/ca_effects/lightning.lua")
dofile(modpath.."/ca_effects/speed_buff.lua")
@ -55,4 +59,5 @@ dofile(modpath .. "/abms/puddle.lua")
dofile(modpath .. "/abms/snow_cover.lua")
dofile(modpath .. "/abms/fire.lua")
dofile(modpath .. "/abms/ice.lua")
dofile(modpath .. "/abms/pedology.lua")
dofile(modpath .. "/abms/soil.lua")

View file

@ -0,0 +1,4 @@
# textdomain:regional_weather
Thin Ice=Dünnes Eis
Puddle=Pfütze
Snow Cover=Schnee

4
locale/template.txt Normal file
View file

@ -0,0 +1,4 @@
# textdomain:regional_weather
Thin Ice=
Puddle=
Snow Cover=

View file

@ -1,9 +1,8 @@
name = regional_weather
title = Regional Weather
author = TestificateMods
release = 1
depends = climate_api
optional_depends = default, lightning, farming, fire
optional_depends = default, lightning, farming, fire, pedology
description = """
Not every biome is the same and neither should their weather be.
Regional Weather controls it's effects with the local climate in mind.

View file

@ -1,11 +1,14 @@
[Features]
# If set to true, sand storms and hail will damage affected players over time.
regional_weather_damage (Cause player damage) bool true
# If set to true, wind will boost or penalize player movements based on direction.
regional_weather_player_speed (Change movement speed based on wind) bool false
# If set to true, snow layers will stack up during snowy weather.
regional_weather_snow_layers (Place snow layers) bool true
# If set to true, snow layers will destroy crops
regional_weather_snow_griefing (Destructive snow layers) bool true
# If set to true, river water sources will freeze at low temperatures and melt when it gets warmer again.
# This process does not affect regular ice blocks because it adds its own temporary ones.
regional_weather_ice (Freeze river water) bool true
@ -13,19 +16,35 @@ regional_weather_ice (Freeze river water) bool true
# If set to true, water puddles will form during rain or when snow layers have melted.
regional_weather_puddles (Place rain puddles) bool true
# If set to true, puddles will be marked as water and hydrate farmland.
# Not compatible with some ambient sound or mob mods
regional_weather_puddles_water (Hydrate farmland near puddles) bool false
# If set to true, rain will cause dry farmland to turn wet.
regional_weather_soil (Hydrate farmland) bool true
regional_weather_soil (Hydrate farmland during rain) bool true
# If set to true, fires will be extinguished during rain showers.
regional_weather_fire (Extinguish fire) bool true
# If set to true, rain will wetten or dry nodes from pedology mod.
regional_weather_pedology (Wetten pedology nodes) bool true
# Multiplier for lightning strike chances
# Requires lightning mod to be installed
regional_weather_lightning (Lightning chance modifier) float 1 0 20
[World Configuration]
# No visual effects will be applied below this height.
# This will prevent unwanted visuals within large underground caves.
regional_weather_min_height (Minimum height of weather effects) int -50
# No visual effects will be applied above this height.
# This value defaults to normal cloud height (120 nodes above sea level).
regional_weather_max_height (Maximum height of weather effects) int 120
# No visual effects will be applied below this height.
# This will prevent unwanted visuals within large underground caves.
regional_weather_min_height (Minimum height of weather effects) int -50
# Average height of cloud bases
regional_weather_cloud_height (Cloud height) int 120
# Maxmial variation of cloud height from base value
regional_weather_cloud_scale (Cloud height variation) int 40

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 510 KiB

After

Width:  |  Height:  |  Size: 93 KiB