diff --git a/ROADMAP.md b/ROADMAP.md index d43a9e0..d85c423 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -8,7 +8,6 @@ - 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 @@ -23,7 +22,6 @@ - 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 ## Future Plans & Ideas diff --git a/ca_effects/skybox.lua b/ca_effects/skybox.lua index e2ae393..6c529da 100644 --- a/ca_effects/skybox.lua +++ b/ca_effects/skybox.lua @@ -3,6 +3,7 @@ if not climate_mod.settings.skybox then return end local EFFECT_NAME = "climate_api:skybox" local function set_skybox(player, sky) + if not player.get_stars then return end if sky.sky_data ~= nil then player:set_sky(sky.sky_data) end @@ -21,6 +22,7 @@ local function set_skybox(player, sky) end local function remove_skybox(player) + if not player.get_stars then return end player:set_sky({ type = "regular", clouds = true}) end diff --git a/ca_effects/sound.lua b/ca_effects/sound.lua index 19eaf72..49db21c 100644 --- a/ca_effects/sound.lua +++ b/ca_effects/sound.lua @@ -1,23 +1,44 @@ 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 removables = {} +local function end_sound(pname, weather, sound) + if removables[pname] == nil + or removables[pname][weather] == nil then return end + local handle = removables[pname][weather] + minetest.sound_stop(handle) + removables[pname][weather] = nil +end + local function start_sound(pname, weather, sound) + local handle 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 - }) + if removables[pname] == nil or removables[pname][weather] == nil then + handle = minetest.sound_play(sound.name, { + to_player = pname, + loop = true, + gain = 0 + }) + else + handle = removables[pname][weather] + removables[pname][weather] = nil + end + minetest.sound_fade(handle, sound.gain / FADE_DURATION, sound.gain) handles[pname][weather] = handle 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) + minetest.sound_fade(handle, -sound.gain / FADE_DURATION, 0) + if removables[pname] == nil then removables[pname] = {} end + removables[pname][weather] = handle handles[pname][weather] = nil + minetest.after(FADE_DURATION, end_sound, pname, weather, sound) end local function start_effect(player_data) @@ -58,4 +79,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) \ No newline at end of file +climate_api.set_effect_cycle(EFFECT_NAME, climate_api.MEDIUM_CYCLE) \ No newline at end of file diff --git a/init.lua b/init.lua index adbce1c..8376730 100644 --- a/init.lua +++ b/init.lua @@ -30,7 +30,8 @@ climate_mod.settings = { 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) } -- initiate empty registers @@ -46,6 +47,7 @@ climate_mod.forced_weather = {} climate_mod.state = dofile(modpath .. "/lib/datastorage.lua") climate_api = dofile(modpath .. "/lib/api.lua") climate_api.utility = dofile(modpath .. "/lib/api_utility.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") diff --git a/lib/api.lua b/lib/api.lua index 639835e..4a88e88 100644 --- a/lib/api.lua +++ b/lib/api.lua @@ -33,9 +33,9 @@ function api.set_effect_cycle(name, cycle) climate_mod.cycles[name].timespan = cycle end ---[[function api.register_influence(name, func) +function api.register_influence(name, func) climate_mod.influences[name] = func -end]] +end function api.register_abm(config) local conditions = config.conditions @@ -52,19 +52,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 diff --git a/lib/environment.lua b/lib/environment.lua index e060e68..6302595 100644 --- a/lib/environment.lua +++ b/lib/environment.lua @@ -31,13 +31,6 @@ 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 diff --git a/lib/influences.lua b/lib/influences.lua index 6536080..6e3ebfc 100644 --- a/lib/influences.lua +++ b/lib/influences.lua @@ -1,30 +1,43 @@ -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("humidity", function(pos) + return climate_api.environment.get_humidity(pos) end) -climate_api.register_influence("windspeed", function(player) +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("windspeed", function(_) 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}) end) -climate_api.register_influence("wind_x", function(player) +climate_api.register_influence("wind_x", function(_) return climate_mod.state:get_float("wind_x") end) -climate_api.register_influence("wind_z", function(player) +climate_api.register_influence("wind_z", function(_) return climate_mod.state:get_float("wind_z") end) -climate_api.register_influence("height", function(player) - local ppos = player:get_pos() - return ppos.y +climate_api.register_influence("height", function(pos) + return pos.y end) -climate_api.register_influence("light", function(player) - return minetest.env:get_node_light(player:get_pos(), 0.5) +climate_api.register_influence("light", function(pos) + return minetest.env:get_node_light(pos) +end) + +climate_api.register_influence("daylight", function(pos) + return minetest.env:get_node_light(pos, 0.5) +end) + +climate_api.register_influence("time", function(_) + return minetest.get_timeofday() end) \ No newline at end of file diff --git a/lib/main.lua b/lib/main.lua index 8028ab0..4f0bd9b 100644 --- a/lib/main.lua +++ b/lib/main.lua @@ -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 @@ -20,7 +20,8 @@ minetest.register_globalstep(function(dtime) 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]) diff --git a/lib/trigger.lua b/lib/trigger.lua index aa86934..02afafd 100644 --- a/lib/trigger.lua +++ b/lib/trigger.lua @@ -4,7 +4,7 @@ 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") - local env = {} + --[[local env = {} env.pos = pos env.height = pos.y env.wind = vector.new(wind_x, 0, wind_z) @@ -13,7 +13,11 @@ function trigger.get_position_environment(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) + env.light = minetest.get_node_light(vector.add(pos, vector.new({x=0,y=1,z=0})), 0.5)]] + local env = {} + for influence, func in pairs(climate_mod.influences) do + env[influence] = func(pos) + end return env end @@ -24,15 +28,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 +55,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 diff --git a/settingtypes.txt b/settingtypes.txt index 7bbee51..7dfd942 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -8,4 +8,5 @@ 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 climate_api_particle_count (Multiplicator for used particles) float 1 0.1 2 -climate_api_fahrenheit (Show degrees in Fahrenheit instead of Celsius) bool false \ No newline at end of file +climate_api_fahrenheit (Show degrees in Fahrenheit instead of Celsius) bool false +climate_api_tick_speed (Update speed of weather effects) float 1 0.1 10 \ No newline at end of file