Sync first working prototype

This commit is contained in:
Till Affeldt 2020-04-09 09:03:02 +02:00
commit f9df1d732f
39 changed files with 536 additions and 0 deletions

8
README.md Normal file
View File

@ -0,0 +1,8 @@
## Assets
- Rain sounds CC0 by Q.K., taken from mymonths
- Thunder sound and puddle texture DWYWPL by Don, Nathan from mymonths at https://github.com/minetest-mods/mymonths
- Snow cover texture WTFPL, taken from mymonths
- Rain texture CC-BY-SA 3.0 from TeddyDesTodes, taken from his weather branch at https://github.com/TeddyDesTodes/minetest/tree/weather
- Snow flake textures CC BY-SA (3.0) by paramat, found in snowdrift mod at https://github.com/paramat/snowdrift
- Snow texture composited from individual snow flakes by paramat. CC-BY-SA (3.0)
- Wind sound CC-BY (3.0) by InspectorJ from https://freesound.org/people/InspectorJ/sounds/376415/

9
depends.txt Normal file
View File

@ -0,0 +1,9 @@
default
lightning?
farming?
flowers?
bakedclay?
moreplants?
lemontree?
player_monoids?
playerphysics?

2
description.txt Normal file
View File

@ -0,0 +1,2 @@
The ultimate weather mod with support not only for rain, snow, and hail,
but also seasons, dynamic puddles and snow layers, wind, regrowing fruit and much more.

53
init.lua Normal file
View File

@ -0,0 +1,53 @@
assert(minetest.add_particlespawner, "Ultimate Weather requires a more current version of Minetest")
weather_mod = {}
weather_mod.modname = "ultimate_weather"
weather_mod.modpath = minetest.get_modpath(weather_mod.modname)
local function getBoolSetting(name, default)
return minetest.is_yes(minetest.settings:get_bool(weather_mod.modname .. "_" .. name) or default)
end
local function getNumericSetting(name, default)
return tonumber(minetest.settings:get(weather_mod.modname .. "_" .. name) or default)
end
-- load settings from config file
weather_mod.settings = {
damage = getBoolSetting("damage", true),
weather = getBoolSetting("weather", true),
leaves = getBoolSetting("leaves", true),
snow = getBoolSetting("snow_layers", true),
puddles = getBoolSetting("puddles", true),
skybox = getBoolSetting("skybox", true),
raycasting = getBoolSetting("raycasting", true),
wind = getBoolSetting("wind", true),
flowers = getBoolSetting("flowers", true),
fruit = getBoolSetting("fruit", true),
soil = getBoolSetting("soil", true),
seasons = getBoolSetting("seasons", true),
heat = getNumericSetting("heat", 0),
humidity = getNumericSetting("humidity", 0),
max_height = getNumericSetting("max_height", 120),
min_height = getNumericSetting("min_height", -50)
}
weather_mod.state = {
current_weather = weather_mod.modname .. ":snowstorm",
heat = 1,
humidity = 1
}
-- import core API
dofile(weather_mod.modpath.."/lib/player.lua")
dofile(weather_mod.modpath.."/lib/environment.lua")
dofile(weather_mod.modpath.."/lib/lightning.lua")
dofile(weather_mod.modpath.."/lib/main.lua")
-- import individual weather types
dofile(weather_mod.modpath.."/weathers/clear.lua")
dofile(weather_mod.modpath.."/weathers/rain.lua")
dofile(weather_mod.modpath.."/weathers/rainstorm.lua")
dofile(weather_mod.modpath.."/weathers/snow.lua")
dofile(weather_mod.modpath.."/weathers/snowstorm.lua")
dofile(weather_mod.modpath.."/weathers/sandstorm.lua")

62
lib/environment.lua Normal file
View File

@ -0,0 +1,62 @@
function weather_mod.get_heat(pos)
local base = weather_mod.settings.heat;
local biome = minetest.get_heat(pos)
local height = math.min(math.max(-pos.y / 15, -10), 10)
local random = weather_mod.state.heat;
return (base + biome + height) * random
end
function weather_mod.get_humidity(pos)
local base = weather_mod.settings.humidity
local biome = minetest.get_humidity(pos)
local random = weather_mod.state.humidity;
return (base + biome) * random
end
local function is_acceptable_weather_param(value, attr, config)
local min = config.conditions["min_" .. attr] or -10000
local max = config.conditions["max_" .. attr] or math.huge
minetest.log(attr .. ": " .. value .. " <=> " .. min .. "," .. max)
return value > min and value <= max
end
function weather_mod.get_weather(pos, wind)
local params = {}
params.heat = weather_mod.get_heat(pos)
params.humidity = weather_mod.get_humidity(pos)
params.windspeed = vector.length(wind)
minetest.log(params.heat .. ", " .. params.humidity .. ", " .. params.windspeed)
local weather
local priority = -1
local attributes = { "heat", "humidity", "windspeed" }
for name, config in pairs(weather_mod.weathers) do
minetest.log(dump2(priority, "p"))
if type(priority) ~= "nil" and config.priority < priority then
minetest.log("skipped " .. name)
elseif type(config.conditions) == "nil" then
weather = name
priority = config.priority
minetest.log("selected (nil) " .. name)
else
local check = true
for _, attr in ipairs(attributes) do
if not is_acceptable_weather_param(params[attr], attr, config) then
check = false
end
end
if check then
weather = name
priority = config.priority
minetest.log("selected " .. name)
end
end
end
if type(weather) == "nil" then
minetest.log("error", "[Ultimate Weather] No default weather registered")
end
minetest.log(weather)
return weather
end

3
lib/lightning.lua Normal file
View File

@ -0,0 +1,3 @@
if minetest.get_modpath("lightning") then
lightning.auto = false
end

130
lib/main.lua Normal file
View File

@ -0,0 +1,130 @@
local GSCYCLE = 0
local temperature = 10
local humidity = 100
local wind = vector.new(10, 0, -0.25)
weather_mod.weathers = {}
function weather_mod.register_weather(name, weather)
-- TODO: check and sanitize
weather_mod.weathers[name] = weather
end
function weather_mod.set_weather(name)
if type(weather_mod.weathers[name]) == nil then
minetest.log("warning", "[Ultimate Weathers] Weather does not exist")
return
end
weather_mod.state.current_weather = name
end
local function is_outside(player, wind)
local ppos = player:getpos()
local wind_pos = vector.multiply(wind,-1)
local skylight_pos = vector.add(ppos, vector.new(0, 40, 0))
local downfall_origin = vector.add(skylight_pos,wind_pos)
return weather_mod.is_outdoors(player, downfall_origin)
end
local function get_texture(particles)
if type(particles.textures) == "nil" or next(particles.textures) == nil then
return particles.texture
end
return particles.textures[math.random(#particles.textures)]
end
local function spawn_particles(player, particles, wind)
local ppos = player:getpos()
local wind_pos = vector.multiply(wind,-1)
local wind_speed = vector.length(wind)
local texture = get_texture(particles)
local minp = vector.add(vector.add(ppos, particles.min_pos),wind_pos)
local maxp = vector.add(vector.add(ppos, particles.max_pos),wind_pos)
local vel = {x=wind.x,y=-particles.falling_speed,z=wind.z}
local acc = {x=0, y=0, z=0}
local exp = particles.exptime
local vertical = wind_speed < 3
minetest.add_particlespawner({
amount=particles.amount,
time=0.5,
minpos=minp,
maxpos=maxp,
minvel=vel,
maxvel=vel,
minacc=acc,
maxacc=acc,
minexptime=exp,
maxexptime=exp,
minsize=particles.size,
maxsize=particles.size,
collisiondetection=true,
collision_removal=true,
vertical=vertical,
texture=texture,
player=player:get_player_name()
})
end
local sound_handles = {}
local function play_sound(player, sound)
local playername = player:get_player_name()
if not sound_handles[playername] then
local handle = minetest.sound_play(sound, {
to_player = playername,
loop = true
})
if handle then
sound_handles[playername] = handle
end
end
end
local function stop_sound(player)
local playername = player:get_player_name()
if sound_handles[playername] then
minetest.sound_stop(sound_handles[playername])
sound_handles[playername] = nil
end
end
local function handle_weather()
for _, player in ipairs(minetest.get_connected_players()) do
local ppos = player:getpos()
weather_mod.set_weather(weather_mod.get_weather(ppos, wind))
if ppos.y < weather_mod.settings.min_height or ppos.y > weather_mod.settings.max_height then
return
end
local weather = weather_mod.weathers[weather_mod.state.current_weather]
local clouds = weather.clouds
clouds.speed = vector.multiply(wind, 2)
player:set_clouds(clouds)
weather_mod.set_headwind(player, wind)
--player:set_clouds({ density = 0.6, color = "#a4a0b6e5", speed = wind })
local outdoors = is_outside(player, wind)
if type(weather.particles) ~= "nil" and outdoors then
spawn_particles(player, weather.particles, wind)
end
if type(weather.sound) ~= "nil" and outdoors then
play_sound(player, weather.sound)
else
stop_sound(player)
end
end
end
local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer < GSCYCLE then return end
timer = 0
handle_weather()
end)

72
lib/player.lua Normal file
View File

@ -0,0 +1,72 @@
local mod_player_monoids = minetest.get_modpath("player_monoids") ~= nil
local mod_playerphysics = minetest.get_modpath("playerphysics") ~= nil
function weather_mod.add_physics(player, effect, value)
local id = weather_mod.modname .. ":" .. effect
if mod_player_monoids then
player_monoids[effect].add_change(player, value, id)
elseif mod_playerphysics then
playerphysics.add_physics_factor(player, effect, id, value)
else
local override = {}
override[effect] = value
player:set_physics_override(override)
end
end
function weather_mod.remove_physics(player, effect)
local id = weather_mod.modname .. ":" .. effect
if mod_player_monoids then
player_monoids[effect].del_change(player, id)
elseif mod_playerphysics then
playerphysics.remove_physics_factor(player, effect, id)
else
local override = {}
override[effect] = 1
player:set_physics_override(override)
end
end
-- function taken from weather mod
-- see https://github.com/theFox6/minetest_mod_weather/blob/master/weather/api.lua#L110
local function raycast(player, origin)
local hitpos = vector.add(player:get_pos(),vector.new(0,1,0))
local ray = minetest.raycast(origin,hitpos)
local o = ray:next()
if not o then return false end
if o.type~="object" then return false end -- hit node or something
if not o.ref:is_player() then return false end -- hit different object
if o.ref:get_player_name() ~= player:get_player_name() then
return false --hit other player
end
o = ray:next()
if o then
minetest.log("warning","[ultimate_weather] raycast hit more after hitting the player\n"..
dump2(o,"o"))
end
return true
end
local function check_light(player)
return minetest.get_node_light(player:getpos(), 0.5) == 15
end
function weather_mod.is_outdoors(player, origin)
if weather_mod.settings.raycasting then
return raycast(player, origin)
else
return check_light(player)
end
end
function weather_mod.set_headwind(player, wind)
local movement = vector.normalize(player:get_player_velocity())
local product = vector.dot(movement, wind)
-- logistic function, scales between 0 and 2
-- see https://en.wikipedia.org/wiki/Logistic_function
local L = 2 -- maximum value
local k = 0.1 -- growth rate
local z = 1 -- midpoint
local factor = L / (1 + math.exp(-k * (product - z)))
weather_mod.add_physics(player, "speed", factor)
end

8
mod.conf Normal file
View File

@ -0,0 +1,8 @@
name = ultimate_weather
title = Ultimate Weather
author = TestificateMods
release = 1
description = """
The ultimate weather mod with support not only for rain, snow, and hail,
but also seasons, dynamic puddles and snow layers, wind, regrowing fruit and much more.
"""

16
settingtypes.txt Normal file
View File

@ -0,0 +1,16 @@
ultimate_weather_damage (Storms and hail cause damage) bool true
ultimate_weather_weather (Enable weather effects) bool true
ultimate_weather_leaves (Leave color changes in autumn) bool true
ultimate_weather_snow_layers (Place snow layers on ground) bool true
ultimate_weather_puddles (Place rain puddles on ground) bool true
ultimate_weather_skybox (Darken sky during rain) bool true
ultimate_weather_raycasting (Use performance-heavy indoors check) bool false
ultimate_weather_wind (Allow wind to angle rainfall) bool true
ultimate_weather_flowers (Flowers will respawn in spring and die in winter) bool true
ultimate_weather_fruit (Apples and other fruits will regrow) bool true
ultimate_weather_soil (Soil turns wet during rain) bool true
ultimate_weather_seasons (Use seasons instead of permanent summer) bool true
ultimate_weather_base_temperature (Base temperature) float 0
ultimate_weather_base_humidity (Base humidity) float 0
ultimate_weather_max_height (Maximum height of weather effects) int 120
ultimate_weather_min_height (Minimum height of weather effects) int -50

BIN
sounds/weather_rain1.ogg Normal file

Binary file not shown.

BIN
sounds/weather_rain2.ogg Normal file

Binary file not shown.

BIN
sounds/weather_thunder.ogg Normal file

Binary file not shown.

BIN
sounds/weather_wind.ogg Normal file

Binary file not shown.

BIN
textures/weather_hail.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
textures/weather_puddle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 556 B

BIN
textures/weather_rain.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
textures/weather_sand.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
textures/weather_snow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 647 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

12
weathers/clear.lua Normal file
View File

@ -0,0 +1,12 @@
local name = weather_mod.modname .. ":clear"
local weather = {
priority = 0
}
weather.clouds = {
density = 0.3,
color = "#fff0f0c5"
}
weather_mod.register_weather(name, weather)

30
weathers/rain.lua Normal file
View File

@ -0,0 +1,30 @@
local name = weather_mod.modname .. ":rain"
local weather = {
priority = 10,
spawn_puddles = true,
wetten_farmland = true,
sound = "weather_rain1"
}
weather.particles = {
min_pos = {x=-9, y=7, z=-9},
max_pos = {x= 9, y=7, z= 9},
falling_speed=10,
amount=20,
exptime=0.8,
size=25,
texture="weather_rain.png"
}
weather.clouds = {
density = 0.5,
color = "#a4a0b6e5"
}
weather.conditions = {
min_heat = 30,
min_humidity = 40
}
weather_mod.register_weather(name, weather)

33
weathers/rainstorm.lua Normal file
View File

@ -0,0 +1,33 @@
local name = weather_mod.modname .. ":rainstorm"
local weather = {
priority = 30,
damage = true,
spawn_puddles = true,
wetten_farmland = true,
lightning = true,
sound = "weather_rain2"
}
weather.particles = {
min_pos = {x=-9, y=7, z=-9},
max_pos = {x= 9, y=7, z= 9},
falling_speed=10,
amount=25,
exptime=0.8,
size=25,
texture="weather_rain.png"
}
weather.clouds = {
density = 0.7,
color = "#a4a0b6f5"
}
weather.conditions = {
min_heat = 30,
min_humidity = 60,
min_windspeed = 5
}
weather_mod.register_weather(name, weather)

30
weathers/sandstorm.lua Normal file
View File

@ -0,0 +1,30 @@
local name = weather_mod.modname .. ":sandstorm"
local weather = {
priority = 50,
damage = true,
sound = "weather_wind"
}
weather.particles = {
min_pos = {x=-9, y=-5, z=-9},
max_pos = {x= 9, y= 5, z= 9},
falling_speed=1,
amount=40,
exptime=0.8,
size=15,
texture="weather_sand.png"
}
weather.clouds = {
density = 0.3,
color = "#a4a0b685"
}
weather.conditions = {
min_heat = 50,
max_humidity = 25,
min_windspeed = 6
}
weather_mod.register_weather(name, weather)

32
weathers/snow.lua Normal file
View File

@ -0,0 +1,32 @@
local name = weather_mod.modname .. ":snow"
local weather = {
priority = 20,
spawn_snow = true
}
weather.particles = {
min_pos = {x=-20, y= 3, z=-20},
max_pos = {x= 20, y=12, z= 20},
falling_speed=1,
amount=50,
exptime=15,
size=1,
textures = {}
}
for i = 1,12,1 do
weather.particles.textures[i] = "weather_snowflake" .. i .. ".png"
end
weather.clouds = {
density = 0.5,
color = "#a4a0b6e5"
}
weather.conditions = {
max_heat = 30,
min_humidity = 40
}
weather_mod.register_weather(name, weather)

36
weathers/snowstorm.lua Normal file
View File

@ -0,0 +1,36 @@
local name = weather_mod.modname .. ":snowstorm"
local weather = {
priority = 40,
damage = true,
lightning = true,
spawn_snow = true,
sound = "weather_wind"
}
weather.particles = {
min_pos = {x=-9, y=-5, z=-9},
max_pos = {x= 9, y= 5, z= 9},
falling_speed=1.5,
amount=70,
exptime=6,
size=1,
textures = {}
}
for i = 1,12,1 do
weather.particles.textures[i] = "weather_snowflake" .. i .. ".png"
end
weather.clouds = {
density = 0.7,
color = "#a4a0b6f5"
}
weather.conditions = {
max_heat = 30,
min_humidity = 60,
min_windspeed = 5
}
weather_mod.register_weather(name, weather)