Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
bff54bfb74 | |||
1057342ac6 | |||
e24b0340e5 | |||
c9d0cfca21 | |||
d1bdf92937 | |||
0c5c9f0d15 | |||
a6cfca7745 | |||
241a0a82c1 | |||
18045b1943 |
99
README.md
@ -1,5 +1,8 @@
|
||||
# Climate API
|
||||
A powerful engine for weather presets and visual effects
|
||||
A powerful engine for weather presets and visual effects.
|
||||
Requires a weather pack like [Regional Weather](https://github.com/t-affeldt/regional_weather).
|
||||
|
||||

|
||||
|
||||
Use the regional climate to set up different effects for different regions.
|
||||
Control where your effects are activated based on temperature, humidity, wind,
|
||||
@ -8,8 +11,98 @@ Climate API provides temperature and humidity values on a block-per-block basis
|
||||
that follow the seasons, day / night cycle and random changes.
|
||||
Make it rain, change the sky or poison the player - it's up to you.
|
||||
|
||||
## Troubleshooting
|
||||
Generally speaking, most mods should be compatible.
|
||||
|
||||
If you notice __odd movement speeds__ or jump heights of players, you should check for mods that also modify player physics. Use a compatibility mod like [player_monoids](https://github.com/minetest-mods/player_monoids) or [playerphysics](https://forum.minetest.net/viewtopic.php?t=22172) to get rid of this problem. This requires the conflicting mod to also support the chosen compatibility layer.
|
||||
|
||||
Mods that __modify the sky__ (including skybox, moon, sun, stars and clouds) are sadly not fully compatible because they conflict with Climate API's sky system. You should deactivate the sky features in either mod. You can do this here using the ``Override the skybox`` setting. If you're a mod maker then you can also optionally depend on climate_api and use ``climate_api.skybox.add_layer(playername, layer_name, options)`` to register your skybox change in a compatible way. Note that you need __at least Minetest v5.2.0__ for skybox changes to have any effect.
|
||||
|
||||
Conflicting skybox changes include the ``weather`` mod included in vanilla __Minetest Game__. You will want to disable that mod in order to use the more advanced cloud system introduced by Climate API. Head to ``Settings → All Settings → Games → Minetest Game`` and set ``Enable weather`` to ``Disabled``. This setting will only exist if you are using Minetest Game v5.2.0 or higher.
|
||||
|
||||
The following mods have been created specifically with Climate API in mind:
|
||||
- [Regional Weather](https://github.com/t-affeldt/regional_weather): My own weather pack for climate based weather effects
|
||||
- [Moon Phases](https://github.com/t-affeldt/minetest_moon_phase): Complements weather effects with dynamic sky changes and a full moon cycle
|
||||
- [Sailing Kit](https://github.com/t-affeldt/sailing_kit) (Fork): Uses Climate API's new wind system to sail across the sea.
|
||||
|
||||
The following mods complement Climate API particularly well:
|
||||
- [Lightning](https://github.com/minetest-mods/lightning): Adds to heavy rain by enabling additional lightning effects
|
||||
- [Ambience](https://notabug.org/TenPlus1/ambience): Plays some nice ambient sound effects based on where you are.
|
||||
|
||||
## Chat Commands
|
||||
- ``/weather``: Display information on current weather effects. This command will show you current temperature and humidity, active weather presets and currently playing effects
|
||||
- ``/weather_settings``: Display current mod configuration in the chat
|
||||
- ``/weather_influences``: Display all different factors and how they affect you in this moment.
|
||||
- ``/weather_status``: Display a list of all installed weather presets and whether they have been forced on, turned off, or are running normally (auto).
|
||||
- ``/grant <playername> weather``: Enable a specified player to modify the current weather.
|
||||
- ``/set_heat <value>``: Override the base heat value used to calculate local climate. Positive numbers will increase temperature by X degrees Fahrenheit, whereas negative values will lower it.
|
||||
- ``/set_humidity <value>``: Override the base humidity value used to calculate local climate. Positive numbers will increase humidity by X percent, whereas negative values will lower it.
|
||||
- ``/set_wind <x> <z>``: Override wind speed and direction. Higher absolute values result in stronger wind. The sign indicates direction.
|
||||
- ``/set_weather <weather> <on|off|auto>``: Set a weather preset to always be applied (on), disable it completely (off), or reset it to be applied automatically (auto). Turning presets on manually might result in partially missing effects (like no sound if you enable sandstorms but no storms). Use ``/weather_status`` for a full list of installed weather presets. The prefix is important.
|
||||
|
||||
## Configuration Options
|
||||
You can find all mod configuration options in your Minetest launcher.
|
||||
Go to ``Settings → All Settings → Mods → climate_api`` to change them.
|
||||
Individual weather packs may provide additional configuration options in their respective mod configuration section.
|
||||
|
||||
### Performance
|
||||
- ``Update speed of weather effects`` (default 1.0):
|
||||
This value regulates how often weather presets are recalculated.
|
||||
Higher values will result in smoother transitions between effects as well as faster response times to traveling players.
|
||||
Lower values will significantly increase overall performance at the cost of rougher looking effects.
|
||||
- ``Multiplicator for used particles`` (default 1.0):
|
||||
This value regulated how many particles will be spawned.
|
||||
A value of 1 will use the recommended amount of particles.
|
||||
Lower values can possible increase performance.
|
||||
- ``Dynamically modify nodes`` (default true):
|
||||
If set to true, weather packs are allowed to register node update handlers.
|
||||
These can be used to dynamically place snow layers, melt ice, or hydrate soil.
|
||||
|
||||
### Visuals
|
||||
- ``Show particle effects`` (default true):
|
||||
If set to true, weather effects (like rain) are allowed to render particles.
|
||||
Deactivating this feature will prevent some presets from being visible.
|
||||
For performance considerations it is recommended to decrease the amount of particles instead.
|
||||
- ``Override the skybox`` (default true):
|
||||
If set to true, weather effects are allowed to modify a player's sky.
|
||||
This includes skybox, sun, moon, and clouds (also used for fog effects).
|
||||
Running this mod on Minetest 5.1.2 or earlier versions will automatically disable this feature.
|
||||
- ``Display HUD overlays`` (default true):
|
||||
If set to true, weather effects are allowed to render an image on top of the gameplay.
|
||||
This is usually an optional effect used to increase immersion (like a frozen-over camera in a snow storm).
|
||||
|
||||
### Environment
|
||||
- ``Global base temperature`` (default 0):
|
||||
This value will be added to all biome's base temperatures before applying random modifiers.
|
||||
Every unit here will increase the global base heat by one degree Fahrenheit.
|
||||
Negative values will cool down global base heat respectively.
|
||||
- ``Global base humidity`` (default 0):
|
||||
This value will be added to all biome's base humidity before applying random modifiers.
|
||||
Every unit here will increase the global base humidity by one percent.
|
||||
Negative values will dry up global base humidity respectively.
|
||||
- ``Time rate of weather changes`` (default 1.0):
|
||||
This value regulates how quickly environment factors like heat, humidity and wind are changing.
|
||||
A value of 2 will double the speed at which weather presets change.
|
||||
A value of 0.5 will half the speed respectively.
|
||||
|
||||
### Preferences
|
||||
- ``Show degrees in Fahrenheit instead of Celsius`` (default true):
|
||||
If set to true, temperature information in /weather command will be displayed in Fahrenheit.
|
||||
- ``Play ambient sound loops`` (default true):
|
||||
If set to true, weather effects are allowed to play sound loops.
|
||||
You can also adjust sound levels instead of deactivating this feature completely.
|
||||
Setting this value to false will be slightly more performant than setting the volume to zero.
|
||||
- ``Volume of sound effects`` (default 1.0):
|
||||
This value regulates overall sound volume.
|
||||
A value of 2 will double the volume whereas a value of 0.5 will reduce the volume by half.
|
||||
|
||||
## License
|
||||
- Source Code: *GNU LGPL v3* by me
|
||||
- Sun and moon textures: *CC BY-SA (3.0)* by Cap
|
||||
|
||||
## Assets in screenshots
|
||||
- All screenshots and editing by me: *CC BY-SA (4.0)*
|
||||
- Screenshots and editing by me: *CC BY-SA (3.0)*
|
||||
- Logos and artwork: *CC BY-SA (3.0)* by Cap
|
||||
- Lato Font (for the Logo): *OFL* by Łukasz Dziedzic from http://www.latofonts.com/lato-free-fonts/
|
||||
- Liberation Fonts (for the text): *OFL*, see https://github.com/liberationfonts/liberation-fonts
|
||||
- Source Sans Pro (for the subtitles): *OFL*, see https://fonts.google.com/specimen/Source+Sans+Pro
|
||||
- Used texture pack: Polygonia (128px edition) *CC BY-SA (4.0)* by Lokrates. See https://forum.minetest.net/viewtopic.php?f=4&t=19043
|
24
ROADMAP.md
@ -1,30 +1,15 @@
|
||||
# TODO
|
||||
|
||||
## Required for MVP
|
||||
- Find good values for weather conditions
|
||||
- Make sure all weather presets are working
|
||||
|
||||
## Required for Beta
|
||||
- Ability to register environment conditions dynamically (like the heat)
|
||||
|
||||
## Planned for first release
|
||||
- Improve test_condition function
|
||||
- Write helpful README
|
||||
- Set effects on player join
|
||||
- Improve value structures of particle and skybox effects
|
||||
- Make sounds adjust to changes by weather presets
|
||||
- Ability to force set a wind speed via chat commands
|
||||
- Improve value structures of particle effects
|
||||
- Find good values for weather conditions
|
||||
- Write documentation on how to add weathers and effects
|
||||
|
||||
## Nice to have
|
||||
- Write documentation on how to add weathers and effects
|
||||
- Assign meta data (like "downfall", "wind", etc.) to weather presets
|
||||
- Fog effects
|
||||
- Optimize performance by replacing some particles with animated texture planes
|
||||
- Make switches between effects more smooth
|
||||
- Adjust size of particle boxes based on player speed
|
||||
- Create conditions for time of day, annual progression, biome filters
|
||||
- Fork lightning so that it uses skylayer
|
||||
- Support for sail boats mod
|
||||
- Generate wind based on speed and yaw instead of x and z values
|
||||
|
||||
## Future Plans & Ideas
|
||||
- Complete season system
|
||||
@ -52,3 +37,4 @@
|
||||
- standing near fire will warm up
|
||||
- craftable warm clothes
|
||||
- metal armor will worsen heat issues
|
||||
- A flag indicating wind direction
|
@ -4,9 +4,25 @@ local EFFECT_NAME = "climate_api:hud_overlay"
|
||||
|
||||
local handles = {}
|
||||
local function apply_hud(pname, weather, hud)
|
||||
if handles[pname] == nil then handles[pname] = {} end
|
||||
if handles[pname][weather] ~= nil then return end
|
||||
local player = minetest.get_player_by_name(pname)
|
||||
if handles[pname] == nil then handles[pname] = {} end
|
||||
if handles[pname][weather] ~= nil then
|
||||
player:hud_remove(handles[pname][weather])
|
||||
end
|
||||
|
||||
local file
|
||||
if hud.color_correction then
|
||||
local pos = vector.add(player:get_pos(), {x = 0, y = 1, z = 0})
|
||||
local light = math.floor(math.max(minetest.env:get_node_light(pos) / 15, 0.2) * 256)
|
||||
local shadow = 256 - light
|
||||
|
||||
local dark_file = hud.file .. "^[multiply:#000000ff^[opacity:" .. shadow
|
||||
local light_file = hud.file .. "^[opacity:" .. light
|
||||
file = "(" .. light_file .. ")^(" .. dark_file .. ")"
|
||||
else
|
||||
file = hud.file
|
||||
end
|
||||
|
||||
local handle = player:hud_add({
|
||||
name = weather,
|
||||
hud_elem_type = "image",
|
||||
@ -14,7 +30,7 @@ local function apply_hud(pname, weather, hud)
|
||||
alignment = {x = 1, y = 1},
|
||||
scale = { x = -100, y = -100},
|
||||
z_index = hud.z_index,
|
||||
text = hud.file,
|
||||
text = file,
|
||||
offset = {x = 0, y = 0}
|
||||
})
|
||||
handles[pname][weather] = handle
|
||||
@ -39,7 +55,12 @@ end
|
||||
local function handle_effect(player_data, prev_data)
|
||||
for playername, data in pairs(player_data) do
|
||||
for weather, value in pairs(data) do
|
||||
if prev_data[playername][weather] == nil then
|
||||
if prev_data[playername][weather] == nil
|
||||
or value.color_correction == true
|
||||
or prev_data[playername][weather].color_correction == true
|
||||
or value.file ~= prev_data[playername][weather].file
|
||||
or value.z_index ~= prev_data[playername][weather].z_index
|
||||
then
|
||||
apply_hud(playername, weather, value)
|
||||
end
|
||||
end
|
||||
|
@ -11,44 +11,58 @@ end
|
||||
|
||||
local function spawn_particles(player, particles)
|
||||
local ppos = player:getpos()
|
||||
local wind_x = climate_mod.state:get_float("wind_x")
|
||||
local wind_z = climate_mod.state:get_float("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 wind = climate_api.environment.get_wind()
|
||||
|
||||
local amount = particles.amount * climate_mod.settings.particle_count
|
||||
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
|
||||
if particles.acceleration == nil then
|
||||
particles.acceleration = vector.new({x=0, y=0, z=0})
|
||||
end
|
||||
|
||||
local wind_pos = vector.multiply(
|
||||
vector.normalize(vel),
|
||||
-vector.length(wind)
|
||||
)
|
||||
wind_pos.y = 0
|
||||
local minp = vector.add(vector.add(ppos, particles.min_pos), wind_pos)
|
||||
local maxp = vector.add(vector.add(ppos, particles.max_pos), wind_pos)
|
||||
|
||||
if particles.time == nil then
|
||||
particles.time = 0.5
|
||||
end
|
||||
|
||||
if particles.vertical == nil then
|
||||
particles.vertical = math.abs(vector.normalize(vel).y) >= 0.6
|
||||
end
|
||||
|
||||
if particles.size ~= nil then
|
||||
particles.min_size = particles.size
|
||||
particles.max_size = particles.size
|
||||
end
|
||||
|
||||
minetest.add_particlespawner({
|
||||
amount = amount,
|
||||
time = 0.5,
|
||||
time = particles.time,
|
||||
minpos = minp,
|
||||
maxpos = maxp,
|
||||
minvel = vel,
|
||||
maxvel = vel,
|
||||
minacc = acc,
|
||||
maxacc = acc,
|
||||
minexptime = exp,
|
||||
maxexptime = exp,
|
||||
minsize = particles.size,
|
||||
maxsize = particles.size,
|
||||
minacc = particles.acceleration,
|
||||
maxacc = particles.acceleration,
|
||||
minexptime = particles.exptime,
|
||||
maxexptime = particles.exptime,
|
||||
minsize = particles.min_size,
|
||||
maxsize = particles.max_size,
|
||||
collisiondetection = true,
|
||||
collision_removal = true,
|
||||
vertical = vertical,
|
||||
vertical = particles.vertical,
|
||||
texture = texture,
|
||||
player = player:get_player_name()
|
||||
})
|
||||
|
@ -2,46 +2,30 @@ if not climate_mod.settings.skybox then return end
|
||||
|
||||
local EFFECT_NAME = "climate_api:skybox"
|
||||
|
||||
local function set_skybox(player, sky)
|
||||
if sky.sky_data ~= nil then
|
||||
player:set_sky(sky.sky_data)
|
||||
end
|
||||
if sky.cloud_data ~= nil then
|
||||
player:set_clouds(sky.cloud_data)
|
||||
end
|
||||
if sky.moon_data ~= nil then
|
||||
player:set_moon(sky.moon_data)
|
||||
end
|
||||
if sky.sun_data ~= nil then
|
||||
player:set_sun(sky.sun_data)
|
||||
end
|
||||
if sky.stars_data ~= nil then
|
||||
player:set_sun(sky.stars_data)
|
||||
end
|
||||
end
|
||||
|
||||
local function remove_skybox(player)
|
||||
player:set_sky({ type = "regular", clouds = true})
|
||||
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)
|
||||
local function handle_effect(player_data, prev_data)
|
||||
for playername, data in pairs(prev_data) do
|
||||
for weather, _ in pairs(data) do
|
||||
if player_data[playername] == nil or player_data[playername][weather] == nil then
|
||||
climate_api.skybox.remove_layer(playername, weather)
|
||||
end
|
||||
end
|
||||
set_skybox(player, sky)
|
||||
end
|
||||
for playername, data in pairs(player_data) do
|
||||
for weather, value in pairs(data) do
|
||||
climate_api.skybox.add_layer(playername, weather, value)
|
||||
end
|
||||
climate_api.skybox.update_skybox(playername)
|
||||
end
|
||||
end
|
||||
|
||||
local function remove_effect(player_data)
|
||||
for playername, data in pairs(player_data) do
|
||||
local player = minetest.get_player_by_name(playername)
|
||||
remove_skybox(player)
|
||||
for weather, _ in pairs(data) do
|
||||
climate_api.skybox.remove_layer(playername, weather)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
climate_api.register_effect(EFFECT_NAME, handle_effect, "tick")
|
||||
climate_api.register_effect(EFFECT_NAME, remove_effect, "stop")
|
||||
--climate_api.set_effect_cycle("climate_api:skybox", climate_api.LONG_CYCLE)
|
||||
climate_api.set_effect_cycle("climate_api:skybox", climate_api.MEDIUM_CYCLE)
|
@ -1,29 +1,23 @@
|
||||
if not climate_mod.settings.sound then return end
|
||||
|
||||
local EFFECT_NAME = "climate_api:sound"
|
||||
local FADE_DURATION = climate_api.LONG_CYCLE
|
||||
|
||||
local handles = {}
|
||||
local function start_sound(pname, weather, sound)
|
||||
if handles[pname] == nil then handles[pname] = {} end
|
||||
if handles[pname][weather] ~= nil then return end
|
||||
local handle = minetest.sound_play(sound, {
|
||||
to_player = pname,
|
||||
loop = true
|
||||
})
|
||||
handles[pname][weather] = handle
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
local soundloop = dofile(modpath .. "/lib/soundloop.lua")
|
||||
|
||||
local function start_sound(pname, sound)
|
||||
return soundloop.play(pname, sound, FADE_DURATION)
|
||||
end
|
||||
|
||||
local function stop_sound(pname, weather, sound)
|
||||
if handles[pname] == nil or handles[pname][weather] == nil then return end
|
||||
local handle = handles[pname][weather]
|
||||
minetest.sound_stop(handle)
|
||||
handles[pname][weather] = nil
|
||||
local function stop_sound(pname, sound)
|
||||
return soundloop.stop(pname, sound, FADE_DURATION)
|
||||
end
|
||||
|
||||
local function start_effect(player_data)
|
||||
for playername, data in pairs(player_data) do
|
||||
for weather, value in pairs(data) do
|
||||
start_sound(playername, weather, value)
|
||||
start_sound(playername, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -32,7 +26,7 @@ local function handle_effect(player_data, prev_data)
|
||||
for playername, data in pairs(player_data) do
|
||||
for weather, value in pairs(data) do
|
||||
if prev_data[playername][weather] == nil then
|
||||
start_sound(playername, weather, value)
|
||||
start_sound(playername, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -40,17 +34,16 @@ local function handle_effect(player_data, prev_data)
|
||||
for playername, data in pairs(prev_data) do
|
||||
for weather, value in pairs(data) do
|
||||
if player_data[playername][weather] == nil then
|
||||
stop_sound(playername, weather, value)
|
||||
stop_sound(playername, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function stop_effect(prev_data)
|
||||
minetest.log(dump2(prev_data, "stop_effect"))
|
||||
for playername, data in pairs(prev_data) do
|
||||
for weather, value in pairs(data) do
|
||||
stop_sound(playername, weather, value)
|
||||
stop_sound(playername, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -58,4 +51,4 @@ end
|
||||
climate_api.register_effect(EFFECT_NAME, start_effect, "start")
|
||||
climate_api.register_effect(EFFECT_NAME, handle_effect, "tick")
|
||||
climate_api.register_effect(EFFECT_NAME, stop_effect, "stop")
|
||||
climate_api.set_effect_cycle(EFFECT_NAME, climate_api.LONG_CYCLE)
|
||||
climate_api.set_effect_cycle(EFFECT_NAME, climate_api.MEDIUM_CYCLE)
|
10
init.lua
@ -27,25 +27,33 @@ climate_mod.settings = {
|
||||
wind = get_setting_bool("wind", true),
|
||||
seasons = get_setting_bool("seasons", true),
|
||||
fahrenheit = get_setting_bool("fahrenheit", false),
|
||||
block_updates = get_setting_bool("block_updates", true),
|
||||
heat = get_setting_number("heat_base", 0),
|
||||
humidity = get_setting_number("humidity_base", 0),
|
||||
time_spread = get_setting_number("time_spread", 1),
|
||||
particle_count = get_setting_number("particle_count", 1)
|
||||
particle_count = get_setting_number("particle_count", 1),
|
||||
tick_speed = get_setting_number("tick_speed", 1),
|
||||
volume = get_setting_number("volume", 1)
|
||||
}
|
||||
|
||||
-- initiate empty registers
|
||||
climate_mod.weathers = {}
|
||||
climate_mod.effects = {}
|
||||
climate_mod.cycles = {}
|
||||
climate_mod.global_environment = {}
|
||||
climate_mod.global_influences = {}
|
||||
climate_mod.influences = {}
|
||||
climate_mod.current_weather = {}
|
||||
climate_mod.current_effects = {}
|
||||
climate_mod.forced_weather = {}
|
||||
climate_mod.forced_wind = nil
|
||||
|
||||
-- import core API
|
||||
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.skybox = dofile(modpath .. "/lib/skybox_merger.lua")
|
||||
dofile(modpath .. "/lib/influences.lua")
|
||||
climate_api.environment = dofile(modpath .. "/lib/environment.lua")
|
||||
--climate_api = dofile(modpath .. "/lib/influences.lua")
|
||||
climate_mod.world = dofile(modpath .. "/lib/world.lua")
|
||||
|
26
lib/api.lua
@ -17,7 +17,7 @@ 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("warning", "[Climate API] Invalid effect handler type: " .. htype)
|
||||
minetest.log("warning", "[Climate API] Effect " .. dump(name) .. " uses invalid callback type: " .. dump(htype))
|
||||
return
|
||||
end
|
||||
-- create effect handler registry if not existent yet
|
||||
@ -33,11 +33,17 @@ function api.set_effect_cycle(name, cycle)
|
||||
climate_mod.cycles[name].timespan = cycle
|
||||
end
|
||||
|
||||
--[[function api.register_influence(name, func)
|
||||
function api.register_global_influence(name, func)
|
||||
climate_mod.global_influences[name] = func
|
||||
end
|
||||
|
||||
function api.register_influence(name, func)
|
||||
climate_mod.influences[name] = func
|
||||
end]]
|
||||
end
|
||||
|
||||
function api.register_abm(config)
|
||||
if not climate_mod.settings.block_updates then return end
|
||||
|
||||
local conditions = config.conditions
|
||||
local action = config.action
|
||||
local pos_override = config.pos_override
|
||||
@ -52,19 +58,9 @@ function api.register_abm(config)
|
||||
return action(pos, node, env)
|
||||
end
|
||||
|
||||
minetest.log(dump2(env, "env"))
|
||||
minetest.log(dump2(conditions, "conditions"))
|
||||
|
||||
for condition, goal in pairs(conditions) do
|
||||
local value = env[condition:sub(5)]
|
||||
if condition:sub(1, 4) == "min_" then
|
||||
if type(value) == "nil" or goal > value then return end
|
||||
elseif condition:sub(1, 4) == "max_" then
|
||||
if type(value) == "nil" or goal <= value then return end
|
||||
else
|
||||
value = env[condition]
|
||||
if type(value) == "nil" or goal ~= value then return end
|
||||
end
|
||||
local is_applicable = climate_mod.trigger.test_condition(condition, env, goal)
|
||||
if not is_applicable then return end
|
||||
end
|
||||
return action(pos, node, env)
|
||||
end
|
||||
|
@ -77,6 +77,32 @@ minetest.register_chatcommand("set_humidity", {
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("set_wind", {
|
||||
params = "<wind>",
|
||||
description = "Override the weather algorithm's windspeed",
|
||||
privs = { weather = true },
|
||||
func = function(playername, param)
|
||||
if param == nil or param == "" then
|
||||
minetest.chat_send_player(playername, "Provide a number to modify the base humidity")
|
||||
return
|
||||
end
|
||||
local arguments = {}
|
||||
for w in param:gmatch("%S+") do table.insert(arguments, w) end
|
||||
local wind_x = arguments[1]
|
||||
local wind_z = arguments[2]
|
||||
if wind_x == "auto" then
|
||||
climate_mod.forced_wind = nil
|
||||
else
|
||||
climate_mod.forced_wind = vector.new({
|
||||
x = tonumber(wind_x),
|
||||
y = 0,
|
||||
z = tonumber(wind_z)
|
||||
})
|
||||
end
|
||||
minetest.chat_send_player(playername, "Wind changed")
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("weather_settings", {
|
||||
description = "Print the active Climate API configuration",
|
||||
func = function(playername)
|
||||
@ -130,3 +156,15 @@ minetest.register_chatcommand("weather_status", {
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("weather_influences", {
|
||||
description = "Prints which weather influences cause your current weather",
|
||||
func = function(playername)
|
||||
minetest.chat_send_player(playername, "Current influences rules:\n================")
|
||||
local player = minetest.get_player_by_name(playername)
|
||||
local influences = climate_mod.trigger.get_player_environment(player)
|
||||
for influence, value in pairs(influences) do
|
||||
minetest.chat_send_player(playername, dump2(value, influence))
|
||||
end
|
||||
end
|
||||
})
|
@ -5,13 +5,6 @@ local function get_heat_time()
|
||||
return climate_api.utility.normalized_cycle(time) * 0.6 + 0.7
|
||||
end
|
||||
|
||||
local function get_heat_calendar()
|
||||
-- European heat center in August instead of June
|
||||
local day = minetest.get_day_count()
|
||||
local progression = ((day + 61) % 365) / 365
|
||||
return climate_api.utility.normalized_cycle(progression) * 0.6 + 0.7
|
||||
end
|
||||
|
||||
local function get_heat_height(y)
|
||||
return climate_api.utility.rangelim((-y + 10) / 15, -10, 10)
|
||||
end
|
||||
@ -21,9 +14,8 @@ function environment.get_heat(pos)
|
||||
local biome = minetest.get_heat(pos)
|
||||
local height = get_heat_height(pos.y)
|
||||
local time = get_heat_time()
|
||||
local date = get_heat_calendar()
|
||||
local random = climate_mod.state:get_float("heat_random");
|
||||
return (base + biome + height) * time * date * random
|
||||
return (base + biome + height) * time * random
|
||||
end
|
||||
|
||||
function environment.get_humidity(pos)
|
||||
@ -31,16 +23,18 @@ function environment.get_humidity(pos)
|
||||
local biome = minetest.get_humidity(pos)
|
||||
local random = climate_mod.state:get_float("humidity_random");
|
||||
local random_base = climate_mod.state:get_float("humidity_base");
|
||||
--[[for _, player in ipairs(minetest.get_connected_players()) do
|
||||
local pname = player:get_player_name()
|
||||
minetest.chat_send_player(pname, dump2(biome, "biome"))
|
||||
minetest.chat_send_player(pname, dump2(random_base, "random_base"))
|
||||
minetest.chat_send_player(pname, dump2(random, "random"))
|
||||
minetest.chat_send_player(pname, dump2((base + biome * 0.7 + random_base * 0.3) * random, "total"))
|
||||
end]]
|
||||
return (base + biome * 0.7 + random_base * 0.3) * random
|
||||
end
|
||||
|
||||
function environment.get_wind()
|
||||
if climate_mod.forced_wind ~= nil then
|
||||
return climate_mod.forced_wind
|
||||
end
|
||||
local wind_x = climate_mod.state:get_float("wind_x")
|
||||
local wind_z = climate_mod.state:get_float("wind_z")
|
||||
return vector.new({ x = wind_x, y = 0, z = wind_z })
|
||||
end
|
||||
|
||||
function environment.get_weather_presets(player)
|
||||
local pname = player:get_player_name()
|
||||
local weathers = climate_mod.current_weather[pname]
|
||||
|
@ -1,30 +1,50 @@
|
||||
climate_api.register_influence("heat", function(player)
|
||||
return climate_mod.get_heat(player:get_pos())
|
||||
climate_api.register_influence("heat", function(pos)
|
||||
return climate_api.environment.get_heat(pos)
|
||||
end)
|
||||
|
||||
climate_api.register_influence("humidity", function(player)
|
||||
return climate_mod.get_humidity(player:get_pos())
|
||||
climate_api.register_influence("base_heat", function(pos)
|
||||
return minetest.get_heat(pos)
|
||||
end)
|
||||
|
||||
climate_api.register_influence("windspeed", function(player)
|
||||
local wind_x = climate_mod.state:get_float("wind_x")
|
||||
local wind_z = climate_mod.state:get_float("wind_z")
|
||||
return vector.length({x = wind_x, y = 0, z = wind_z})
|
||||
climate_api.register_influence("humidity", function(pos)
|
||||
return climate_api.environment.get_humidity(pos)
|
||||
end)
|
||||
|
||||
climate_api.register_influence("wind_x", function(player)
|
||||
return climate_mod.state:get_float("wind_x")
|
||||
climate_api.register_influence("base_humidity", function(pos)
|
||||
return minetest.get_humidity(pos)
|
||||
end)
|
||||
|
||||
climate_api.register_influence("wind_z", function(player)
|
||||
return climate_mod.state:get_float("wind_z")
|
||||
climate_api.register_influence("biome", function(pos)
|
||||
local data = minetest.get_biome_data(pos)
|
||||
local biome = minetest.get_biome_name(data.biome)
|
||||
return biome
|
||||
end)
|
||||
|
||||
climate_api.register_influence("height", function(player)
|
||||
local ppos = player:get_pos()
|
||||
return ppos.y
|
||||
climate_api.register_global_influence("windspeed", function()
|
||||
local wind = climate_api.environment.get_wind()
|
||||
return vector.length(wind)
|
||||
end)
|
||||
|
||||
climate_api.register_influence("light", function(player)
|
||||
return minetest.env:get_node_light(player:get_pos(), 0.5)
|
||||
climate_api.register_global_influence("wind_yaw", function()
|
||||
local wind = climate_api.environment.get_wind()
|
||||
if vector.length(wind) == 0 then return 0 end
|
||||
return minetest.dir_to_yaw(wind)
|
||||
end)
|
||||
|
||||
climate_api.register_influence("height", function(pos)
|
||||
return pos.y
|
||||
end)
|
||||
|
||||
climate_api.register_influence("light", function(pos)
|
||||
pos = vector.add(pos, {x = 0, y = 1, z = 0})
|
||||
return minetest.env:get_node_light(pos)
|
||||
end)
|
||||
|
||||
climate_api.register_influence("daylight", function(pos)
|
||||
pos = vector.add(pos, {x = 0, y = 1, z = 0})
|
||||
return minetest.env:get_node_light(pos, 0.5)
|
||||
end)
|
||||
|
||||
climate_api.register_global_influence("time", function()
|
||||
return minetest.get_timeofday()
|
||||
end)
|
@ -1,5 +1,5 @@
|
||||
local GSCYCLE = 0.03
|
||||
local WORLD_CYCLE = 2
|
||||
local GSCYCLE = 0.03 * climate_mod.settings.tick_speed
|
||||
local WORLD_CYCLE = 2 * climate_mod.settings.tick_speed
|
||||
|
||||
local gs_timer = 0
|
||||
local world_timer = 0
|
||||
@ -14,13 +14,15 @@ minetest.register_globalstep(function(dtime)
|
||||
world_timer = 0
|
||||
climate_mod.state:set_float("noise_timer", noise_timer)
|
||||
climate_mod.world.update_status(noise_timer)
|
||||
climate_mod.global_environment = climate_mod.trigger.get_global_environment()
|
||||
end
|
||||
|
||||
local previous_effects = table.copy(climate_mod.current_effects)
|
||||
local current_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
|
||||
local cycle = climate_mod.cycles[name].timespan * climate_mod.settings.tick_speed
|
||||
if cycle < climate_mod.cycles[name].timer + dtime then
|
||||
climate_mod.cycles[name].timer = 0
|
||||
climate_mod.current_effects[name] = current_effects[name]
|
||||
climate_mod.trigger.call_handlers(name, current_effects[name], previous_effects[name])
|
||||
|
109
lib/skybox_merger.lua
Normal file
@ -0,0 +1,109 @@
|
||||
local default_sky = {
|
||||
sky_data = {
|
||||
base_color = nil,
|
||||
type = "regular",
|
||||
textures = nil,
|
||||
clouds = true,
|
||||
sky_color = {
|
||||
day_sky = "#8cbafa",
|
||||
day_horizon = "#9bc1f0",
|
||||
dawn_sky = "#b4bafa",
|
||||
dawn_horizon = "#bac1f0",
|
||||
night_sky = "#006aff",
|
||||
night_horizon = "#4090ff",
|
||||
indoors = "#646464",
|
||||
fog_tint_type = "default"
|
||||
}
|
||||
},
|
||||
cloud_data = {
|
||||
density = 0.4,
|
||||
color = "#fff0f0e5",
|
||||
ambient = "#000000",
|
||||
height = 120,
|
||||
thickness = 16,
|
||||
speed = {x=0, z=-2}
|
||||
},
|
||||
sun_data = {
|
||||
visible = true,
|
||||
texture = "sun.png",
|
||||
tonemap = "sun_tonemap.png",
|
||||
sunrise = "sunrisebg.png",
|
||||
sunrise_visible = true,
|
||||
scale = 1
|
||||
},
|
||||
moon_data = {
|
||||
visible = true,
|
||||
texture = "moon.png",
|
||||
tonemap = "moon_tonemap.png",
|
||||
scale = 1
|
||||
},
|
||||
star_data = {
|
||||
visible = true,
|
||||
count = 1000,
|
||||
star_color = "#ebebff69",
|
||||
scale = 1
|
||||
}
|
||||
}
|
||||
|
||||
local skybox = {}
|
||||
local layers = {}
|
||||
|
||||
-- from https://stackoverflow.com/a/29133654
|
||||
-- merges two tables together
|
||||
-- if in conflict, b will override values of a
|
||||
local function 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_tables(a[k],v)
|
||||
else a[k]=v end
|
||||
end
|
||||
end
|
||||
return a
|
||||
end
|
||||
|
||||
local function set_skybox(playername, sky)
|
||||
local player = minetest.get_player_by_name(playername)
|
||||
if not player.get_stars then return end
|
||||
player:set_sky(sky.sky_data)
|
||||
player:set_clouds(sky.cloud_data)
|
||||
player:set_moon(sky.moon_data)
|
||||
player:set_sun(sky.sun_data)
|
||||
player:set_stars(sky.star_data)
|
||||
end
|
||||
|
||||
function skybox.update_skybox(playername)
|
||||
local p_layers = layers[playername]
|
||||
local sky = table.copy(default_sky)
|
||||
if p_layers == nil then p_layers = {} end
|
||||
local numbered_layers = {}
|
||||
for layer, values in pairs(p_layers) do
|
||||
table.insert(numbered_layers, values)
|
||||
end
|
||||
table.sort(numbered_layers, function(left, right)
|
||||
if left.priority == nil then left.priority = 1 end
|
||||
if right.priority == nil then right.priority = 1 end
|
||||
return left.priority < right.priority
|
||||
end)
|
||||
for i=1,#numbered_layers do
|
||||
sky = merge_tables(sky, numbered_layers[i])
|
||||
end
|
||||
set_skybox(playername, sky)
|
||||
end
|
||||
|
||||
function skybox.add_layer(playername, name, sky)
|
||||
if layers[playername] == nil then layers[playername] = {} end
|
||||
layers[playername][name] = sky
|
||||
end
|
||||
|
||||
function skybox.remove_layer(playername, name)
|
||||
if layers[playername] == nil or layers[playername][name] == nil then return end
|
||||
layers[playername][name] = nil
|
||||
end
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local playername = player:get_player_name()
|
||||
layers[playername] = nil
|
||||
end)
|
||||
|
||||
return skybox
|
57
lib/soundloop.lua
Normal file
@ -0,0 +1,57 @@
|
||||
local soundloop = {}
|
||||
local sounds = {}
|
||||
|
||||
local function parse_sound(sound)
|
||||
if type(sound) == "string" then
|
||||
return { name = sound, gain = 1, pitch = 1 }
|
||||
end
|
||||
if sound.gain == nil then sound.gain = 1 end
|
||||
if sound.pitch == nil then sound.pitch = 1 end
|
||||
return sound
|
||||
end
|
||||
|
||||
soundloop.play = function(player, sound, fade)
|
||||
sound = parse_sound(sound)
|
||||
if fade == nil then fade = 1 end
|
||||
local step
|
||||
local handle
|
||||
local start_gain
|
||||
if sounds[player] == nil then sounds[player] = {} end
|
||||
if sounds[player][sound.name] == nil then
|
||||
step = sound.gain / fade
|
||||
start_gain = 0
|
||||
elseif sounds[player][sound.name] ~= sound.gain then
|
||||
minetest.sound_stop(sounds[player][sound.name].handle)
|
||||
start_gain = sounds[player][sound.name].gain
|
||||
local change = sound.gain - start_gain
|
||||
step = change / fade
|
||||
else
|
||||
return
|
||||
end
|
||||
handle = minetest.sound_play(sound.name, {
|
||||
to_player = player,
|
||||
loop = true,
|
||||
gain = 0
|
||||
})
|
||||
sounds[player][sound.name] = {
|
||||
gain = sound.gain,
|
||||
handle = handle
|
||||
}
|
||||
minetest.sound_fade(handle, step, sound.gain)
|
||||
return handle
|
||||
end
|
||||
|
||||
soundloop.stop = function(player, sound, fade)
|
||||
sound = parse_sound(sound)
|
||||
if sounds[player] == nil or sounds[player][sound.name] == nil then
|
||||
return
|
||||
end
|
||||
if fade == nil then fade = 1 end
|
||||
local handle = sounds[player][sound.name].handle
|
||||
local step = -sounds[player][sound.name].gain / fade
|
||||
minetest.sound_fade(handle, step, 0)
|
||||
sounds[player][sound.name].gain = 0
|
||||
minetest.after(fade, minetest.sound_stop, handle)
|
||||
end
|
||||
|
||||
return soundloop
|
@ -1,19 +1,18 @@
|
||||
local trigger = {}
|
||||
|
||||
function trigger.get_position_environment(pos)
|
||||
local wind_x = climate_mod.state:get_float("wind_x")
|
||||
local wind_z = climate_mod.state:get_float("wind_z")
|
||||
|
||||
function trigger.get_global_environment()
|
||||
local env = {}
|
||||
env.pos = pos
|
||||
env.height = pos.y
|
||||
env.wind = vector.new(wind_x, 0, wind_z)
|
||||
env.windspeed = vector.length(env.wind)
|
||||
env.heat = climate_api.environment.get_heat(pos)
|
||||
env.humidity = climate_api.environment.get_humidity(pos)
|
||||
env.time = minetest.get_timeofday()
|
||||
env.date = minetest.get_day_count()
|
||||
env.light = minetest.get_node_light(vector.add(pos, vector.new({x=0,y=1,z=0})), 0.5)
|
||||
for influence, func in pairs(climate_mod.global_influences) do
|
||||
env[influence] = func()
|
||||
end
|
||||
return env
|
||||
end
|
||||
|
||||
function trigger.get_position_environment(pos)
|
||||
local env = table.copy(climate_mod.global_environment)
|
||||
for influence, func in pairs(climate_mod.influences) do
|
||||
env[influence] = func(pos)
|
||||
end
|
||||
return env
|
||||
end
|
||||
|
||||
@ -24,15 +23,21 @@ function trigger.get_player_environment(player)
|
||||
return env
|
||||
end
|
||||
|
||||
local function test_condition(condition, env, goal)
|
||||
function trigger.test_condition(condition, env, goal)
|
||||
local value = env[condition:sub(5)]
|
||||
if condition:sub(1, 4) == "min_" then
|
||||
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")
|
||||
elseif condition:sub(1, 4) == "has_" then
|
||||
if type(value) == "nil" then return false end
|
||||
for _, g in ipairs(goal) do
|
||||
if value == g then return true end
|
||||
end
|
||||
return false
|
||||
else
|
||||
value = env[condition]
|
||||
return type(value) ~= "nil" and goal == value
|
||||
end
|
||||
end
|
||||
|
||||
@ -45,7 +50,7 @@ local function is_weather_active(player, weather, env)
|
||||
return config.conditions(env)
|
||||
end
|
||||
for condition, goal in pairs(config.conditions) do
|
||||
if not test_condition(condition, env, goal) then
|
||||
if not trigger.test_condition(condition, env, goal) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
@ -145,7 +150,6 @@ function trigger.call_handlers(name, effect, prev_effect)
|
||||
|
||||
-- remaining table lists ending effects
|
||||
if has_stops then
|
||||
minetest.log(dump2(name, "AAAAAAAAAAA"))
|
||||
for _, handler in ipairs(climate_mod.effects[name]["stop"]) do
|
||||
handler(stops)
|
||||
end
|
||||
|
@ -2,11 +2,11 @@ local world = {}
|
||||
|
||||
local WIND_SPREAD = 600
|
||||
local WIND_SCALE = 2
|
||||
local HEAT_SPREAD = 200
|
||||
local HEAT_SPREAD = 400
|
||||
local HEAT_SCALE = 0.3
|
||||
local HUMIDITY_SPREAD = 60
|
||||
local HUMIDITY_SPREAD = 150
|
||||
local HUMIDITY_SCALE = 0.5
|
||||
local HUMIDITY_BASE_SPREAD = 600
|
||||
local HUMIDITY_BASE_SPREAD = 800
|
||||
local HUMIDITY_BASE_SCALE = 40
|
||||
|
||||
local nobj_wind_x
|
||||
|
2
mod.conf
@ -1,7 +1,7 @@
|
||||
name = climate_api
|
||||
title = Climate API
|
||||
author = TestificateMods
|
||||
release = 1
|
||||
release = 2
|
||||
optional_depends = skylayer, player_monoids, playerphysics
|
||||
description = """
|
||||
A powerful engine for weather presets and visual effects.
|
||||
|
BIN
screenshot.2.png
Before Width: | Height: | Size: 2.0 MiB |
BIN
screenshot.3.png
Before Width: | Height: | Size: 2.0 MiB |
BIN
screenshot.png
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.6 MiB |
@ -1,11 +1,64 @@
|
||||
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_hud_overlay (Allow weather presets to display a HUD overlay) 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
|
||||
climate_api_time_spread (Regulates how quickly the weather changes) float 1 0.1 10
|
||||
[Performance]
|
||||
|
||||
# This value regulates how often weather presets are recalculated.
|
||||
# Higher values will result in smoother transitions between effects as well as faster response times to traveling players.
|
||||
# Lower values will significantly increase overall performance at the cost of rougher looking effects.
|
||||
climate_api_tick_speed (Update speed of weather effects) float 1 0.1 10
|
||||
|
||||
# This value regulated how many particles will be spawned.
|
||||
# A value of 1 will use the recommended amount of particles.
|
||||
# Lower values can possible increase performance.
|
||||
climate_api_particle_count (Multiplicator for used particles) float 1 0.1 2
|
||||
|
||||
# If set to true, weather packs are allowed to register node update handlers.
|
||||
# These can be used to dynamically place snow layers, melt ice, or hydrate soil.
|
||||
climate_api_block_updates (Dynamically modify nodes) bool true
|
||||
|
||||
|
||||
[Visuals]
|
||||
# If set to true, weather effects (like rain) are allowed to render particles.
|
||||
# Deactivating this feature will prevent some presets from being visible.
|
||||
# For performance considerations it is recommended to decrease the amount of particles instead.
|
||||
climate_api_particles (Show particle effects) bool true
|
||||
|
||||
# If set to true, weather effects are allowed to modify a player's sky.
|
||||
# This includes skybox, sun, moon, and clouds (also used for fog effects).
|
||||
# Running this mod on Minetest 5.1.2 or earlier versions will automatically disable this feature.
|
||||
climate_api_skybox (Override the skybox) bool true
|
||||
|
||||
# If set to true, weather effects are allowed to render an image on top of the gameplay.
|
||||
# This is usually an optional effect used to increase immersion (like a frozen-over camera in a snow storm).
|
||||
climate_api_hud_overlay (Display HUD overlays) bool true
|
||||
|
||||
|
||||
[Environment]
|
||||
|
||||
# This value will be added to all biome's base temperatures before applying random modifiers.
|
||||
# Every unit here will increase the global base heat by one degree Fahrenheit.
|
||||
# Negative values will cool down global base heat respectively.
|
||||
climate_api_heat_base (Global base temperature) float 0
|
||||
|
||||
# This value will be added to all biome's base humidity before applying random modifiers.
|
||||
# Every unit here will increase the global base humidity by one percent.
|
||||
# Negative values will dry up global base humidity respectively.
|
||||
climate_api_humidity_base (Global base humidity) float 0
|
||||
|
||||
# This value regulates how quickly environment factors like heat, humidity and wind are changing.
|
||||
# A value of 2 will double the speed at which weather presets change.
|
||||
# A value of 0.5 will half the speed respectively.
|
||||
climate_api_time_spread (Time rate of weather changes) float 1 0.1 10
|
||||
|
||||
|
||||
[Preferences]
|
||||
|
||||
# If set to true, temperature information in /weather command will be displayed in Fahrenheit.
|
||||
climate_api_fahrenheit (Show degrees in Fahrenheit instead of Celsius) bool false
|
||||
|
||||
# If set to true, weather effects are allowed to play sound loops.
|
||||
# You can also adjust sound levels instead of deactivating this feature completely.
|
||||
# Setting this value to false will be slightly more performant than setting the volume to zero.
|
||||
climate_api_sound (Play ambient sound loops) bool true
|
||||
|
||||
# This value regulates overall sound volume.
|
||||
# A value of 2 will double the volume whereas a value of 0.5 will reduce the volume by half.
|
||||
climate_api_volume (Volume of sound effects) float 1 0 10
|
||||
|
Before Width: | Height: | Size: 2.2 MiB |
BIN
textures/moon.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
textures/sun.png
Normal file
After Width: | Height: | Size: 1.2 KiB |