first commit
commit
2f7d73333a
|
@ -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",
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
# Licenses
|
||||
|
||||
- Source code: GPLv3.
|
||||
- Textures: CC BY-SA 4.0
|
|
@ -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
|
|
@ -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 (x−cx)2+(y−cy)2+(z−cz)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)
|
|
@ -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
|
Binary file not shown.
After Width: | Height: | Size: 172 B |
Binary file not shown.
After Width: | Height: | Size: 224 B |
Binary file not shown.
After Width: | Height: | Size: 177 B |
Loading…
Reference in New Issue