first commit

master
runs 2021-01-24 17:58:59 +01:00
commit 2f7d73333a
9 changed files with 267 additions and 0 deletions

18
.luacheckrc Normal file
View File

@ -0,0 +1,18 @@
unused_args = false
allow_defined_top = true
globals = {
"minetest",
}
read_globals = {
string = {fields = {"split"}},
table = {fields = {"copy", "getn"}},
-- Builtin
"vector", "ItemStack",
"dump", "DIR_DELIM", "VoxelArea", "Settings",
-- MTG
"default", "sfinv", "creative",
}

4
LICENSE.md Normal file
View File

@ -0,0 +1,4 @@
# Licenses
- Source code: GPLv3.
- Textures: CC BY-SA 4.0

9
climatez.conf Normal file
View File

@ -0,0 +1,9 @@
#Chance of the a new area climate to be created
##in seconds
climate_change_ratio = 1200
#Area of the regional climates (sphere)
climate_radius = 80
#Average time of the climate
climate_duration = 120
#Random deviation for the duration
climate_duration_random_ratio = 0.45

222
engine.lua Normal file
View File

@ -0,0 +1,222 @@
local modpath = ...
local climatez = {}
climatez.wind = {}
climatez.climates = {}
climatez.settings = {}
--Settings
local settings = Settings(modpath .. "/climatez.conf")
climatez.settings.climate_change_ratio = tonumber(settings:get("climate_change_ratio"))
climatez.settings.radius = tonumber(settings:get("climate_radius"))
climatez.settings.climate_duration = tonumber(settings:get("climate_duration"))
climatez.settings.duration_random_ratio = tonumber(settings:get("climate_duration_random_ratio"))
local check_light = minetest.is_yes(minetest.settings:get_bool('light_roofcheck', true))
--Helper Functions
local function player_inside_climate(player_pos)
--If sphere's centre coordinates is (cx,cy,cz) and its radius is r,
--then point (x,y,z) is in the sphere if (xcx)2+(ycy)2+(zcz)2<r2.
for i, climate in ipairs(climatez.climates) do
local climate_center = climatez.climates[i].center
if climatez.settings.radius > math.sqrt((player_pos.x - climate_center.x)^2+
(player_pos.y - climate_center.y)^2 +
(player_pos.z - climate_center.z)^2
) then
return i
end
end
return false
end
local function has_light(minp, maxp)
local manip = minetest.get_voxel_manip()
local e1, e2 = manip:read_from_map(minp, maxp)
local area = VoxelArea:new{MinEdge=e1, MaxEdge=e2}
local data = manip:get_light_data()
local node_num = 0
local light = false
for i in area:iterp(minp, maxp) do
node_num = node_num + 1
if node_num < 5 then
if data[i] and data[i] == 15 then
light = true
break
end
else
node_num = 0
end
end
return light
end
local function array_remove(tab, idx)
tab[idx] = nil
local new_tab = {}
for _, value in pairs(tab) do
new_tab[ #new_tab+1] = value
end
return new_tab
end
--DOWNFALLS REGISTRATIONS
climatez.registered_downfalls = {}
local function register_downfall(name, def)
local new_def = table.copy(def)
climatez.registered_downfalls[name] = new_def
end
register_downfall("rain", {
min_pos = {x = -15, y = 10, z = -15},
max_pos = {x = 15, y = 10, z = 15},
falling_speed = 10,
amount = 25,
exptime = 1,
size = 1,
texture = "climatez_rain.png",
})
register_downfall("snow", {
min_pos = {x = -15, y = 10, z= -15},
max_pos = {x = 15, y = 10, z = 15},
falling_speed = 5,
amount = 15,
exptime = 7,
size = 1,
texture= "climatez_snow.png",
})
register_downfall("sand", {
min_pos = {x = -20, y = -4, z = -20},
max_pos = {x = 20, y = 4, z = 20},
falling_speed = -1,
amount = 40,
exptime = 1,
size = 1,
texture = "climatez_sand.png",
})
--WIND STUFF
local function create_wind()
local wind = {
x = math.random(0,10),
y = 0,
z = math.random(0,10)
}
return wind
end
function get_player_wind(player)
local player_pos = player:get_pos()
local climate_id = player_inside_climate(player_pos)
if climate_id then
return climatez.climates[climate_id].wind
else
return create_wind()
end
end
--CLIMATE FUNCTIONS
local function create_climate(player_pos)
--get some data
local biome_data = minetest.get_biome_data(player_pos)
local biome_heat = biome_data.heat
local biome_humidity = biome_data.humidity
local downfall
if biome_heat > 40 and biome_humidity > 50 then
downfall = "rain"
elseif biome_heat > 50 and biome_humidity < 20 then
downfall = "sand"
else
downfall = "snow"
end
if not downfall then
return
end
--create wind
local wind = create_wind()
--create climate
local climate_id = #climatez.climates+1
climatez.climates[climate_id]= {
center = player_pos,
downfall = downfall,
wind = wind,
}
--program climate's end
local climate_duration = climatez.settings.climate_duration
local climate_duration_random_ratio = climatez.settings.duration_random_ratio
local random_end_time = (math.random(climate_duration- (climate_duration*climate_duration_random_ratio),
climate_duration+ (climate_duration*climate_duration_random_ratio)))
minetest.after(random_end_time, function()
climatez.climates = array_remove(climatez.climates, climate_id)
end)
end
local function apply_climate(player, player_pos, climate_id)
local climate = climatez.climates[climate_id]
local downfall = climatez.registered_downfalls[climate.downfall]
local wind = climatez.climates[climate_id].wind
local wind_pos = vector.multiply(wind, -1)
local minp = vector.add(vector.add(player_pos, downfall.min_pos), wind_pos)
local maxp = vector.add(vector.add(player_pos, downfall.max_pos), wind_pos)
--Check if in player in interiors or not
if check_light and not has_light(minp, maxp) then
return
end
local vel = {x = wind.x, y = - downfall.falling_speed, z = wind.z}
local acc = {x = 0, y = 0, z = 0}
local exp = downfall.exptime
minetest.add_particlespawner({
amount = downfall.amount, time=0.5,
minpos = minp, maxpos = maxp,
minvel = vel, maxvel = vel,
minacc = acc, maxacc = acc,
minexptime = exp, maxexptime = exp,
minsize = downfall.size, maxsize= downfall.size,
collisiondetection = true, collision_removal = true,
vertical = true,
texture = downfall.texture, playername = player:get_player_name()
})
end
--CLIMATE CORE: GLOBALSTEP
local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime;
local player_pos, climate_id
for _, player in ipairs(minetest.get_connected_players()) do
player_pos = player:get_pos()
climate_id = player_inside_climate(player_pos)
if climate_id then
apply_climate(player, player_pos, climate_id)
else
if timer >= 1 then
local chance = math.random(climatez.settings.climate_change_ratio)
if chance == 1 then
create_climate(player_pos)
end
timer = 0
end
end
end
end)

12
init.lua Normal file
View File

@ -0,0 +1,12 @@
--
-- Climatez
-- License:GPLv3
--
local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
local mg_name = minetest.get_mapgen_setting("mg_name")
if mg_name ~= "v6" and mg_name ~= "singlenode" then
assert(loadfile(modpath .. "/engine.lua"))(modpath)
end

2
mod.conf Normal file
View File

@ -0,0 +1,2 @@
name = climatez
description = A weather mod

BIN
textures/climatez_rain.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

BIN
textures/climatez_sand.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

BIN
textures/climatez_snow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B