Updates of erosion and getting wet. Add some shared functions.

master
SFENCE 2019-10-30 16:09:36 +01:00
parent 08d9ed0706
commit cef53cb32e
4 changed files with 299 additions and 6 deletions

View File

@ -1,4 +1,6 @@
local S = default.S;
--
-- Changeable nodes
--

View File

@ -2,28 +2,105 @@
local S = default.S;
function default.erosion_air(pos, node)
minetest.log("warning", "Air erosion of node "..node.name.." pos X:"..tostring(pos.x).." Y:"..tostring(pos.y).." Z:"..tostring(pos.z))
minetest.log("warning", "Air erosion of node "..node.name.." pos X:"..tostring(pos.x).." Y:"..tostring(pos.y).." Z:"..tostring(pos.z))
local positions = default.shared_positions_in_sphere(pos, 1, false);
local erosion_chance = 0.0;
local erosion_air = minetest.get_item_group(node.name, "erosion_air")/100.0;
for check_index,check_pos in pairs(positions) do
check_node = minetest.get_node(check_pos);
if ((check_node.name=="air") or (minetest.get_item_group(check_node.name, "air")>0)) then
erosion_chance = default.shared_add_chance_happen(erosion_chance, erosion_air);
end
end
local chance = default.random_generator:next(0, 16777215)/16777215.0;
if (chance<=erosion_chance) then
default.apply_node_change(pos, node, "erosion");
end
end
function default.erosion_water(pos, node)
minetest.log("warning", "Water erosion of node "..node.name.." pos X:"..tostring(pos.x).." Y:"..tostring(pos.y).." Z:"..tostring(pos.z))
minetest.log("warning", "Water erosion of node "..node.name.." pos X:"..tostring(pos.x).." Y:"..tostring(pos.y).." Z:"..tostring(pos.z))
local positions = default.shared_positions_in_sphere(pos, 1, false);
local erosion_chance = 0.0;
local erosion_water = minetest.get_item_group(node.name, "erosion_water")/100.0;
for check_index,check_pos in pairs(positions) do
check_node = minetest.get_node(check_pos);
if (minetest.get_item_group(check_node.name, "water")>0) then
check_def = minetest.registered_nodes[check_node.name];
local erosion_part = 0.2;
if (check_def.liquidtype=="flowing") then
erosion_part = erosion_part + 0.8 * minetest.get_node_level(check_pos)/minetest.get_node_max_level(check_pos);
end
erosion_chance = default.shared_add_chance_happen(erosion_chance, erosion_part*erosion_water);
end
end
local chance = default.random_generator:next(0, 16777215)/16777215.0;
if (chance<=erosion_chance) then
default.apply_node_change(pos, node, "erosion");
end
end
function default.erosion_heat(pos, node)
minetest.log("warning", "Heat erosion of node "..node.name.." pos X:"..tostring(pos.x).." Y:"..tostring(pos.y).." Z:"..tostring(pos.z))
default.apply_node_change(pos, node, "erosion");
minetest.log("warning", "Heat erosion of node "..node.name.." pos X:"..tostring(pos.x).." Y:"..tostring(pos.y).." Z:"..tostring(pos.z))
default.apply_node_change(pos, node, "erosion");
end
function default.erosion_dry(pos, node)
minetest.log("warning", "Dry erosion of node "..node.name.." pos X:"..tostring(pos.x).." Y:"..tostring(pos.y).." Z:"..tostring(pos.z))
minetest.log("warning", "Dry erosion of node "..node.name.." pos X:"..tostring(pos.x).." Y:"..tostring(pos.y).." Z:"..tostring(pos.z))
local erosion_chance = 0.0;
local erosion_dry = minetest.get_item_group(node.name, "erosion_dry")/100.0;
if (minetest.get_item_group(node.name, "dry")>0) then
erosion_chance = default.shared_add_chance_happen(erosion_chance, erosion_dry);
end
local chance = default.random_generator:next(0, 16777215)/16777215.0;
if (chance<=erosion_chance) then
default.apply_node_change(pos, node, "erosion");
end
end
function default.erosion_wet(pos, node)
minetest.log("warning", "Wet erosion of node "..node.name.." pos X:"..tostring(pos.x).." Y:"..tostring(pos.y).." Z:"..tostring(pos.z))
minetest.log("warning", "Wet erosion of node "..node.name.." pos X:"..tostring(pos.x).." Y:"..tostring(pos.y).." Z:"..tostring(pos.z))
local positions = default.shared_positions_in_sphere(pos, 1, false);
local erosion_chance = 0.0;
local erosion_wet = minetest.get_item_group(node.name, "erosion_wet")/100.0;
local erosion_part = 0.0;
if (minetest.get_item_group(node.name, "damp")>0) then
erosion_part = 0.33;
end
if (minetest.get_item_group(node.name, "wet")>0) then
erosion_part = 0.97;
end
if (minetest.get_item_group(node.name, "soggy")>0) then
erosion_part = 1.0;
end
if (erosion_part>0.0) then
erosion_chance = default.shared_add_chance_happen(erosion_chance, erosion_part*erosion_wet);
end
local chance = default.random_generator:next(0, 16777215)/16777215.0;
if (chance<=erosion_chance) then
default.apply_node_change(pos, node, "erosion");
end
end
minetest.register_abm({
@ -36,3 +113,39 @@ minetest.register_abm({
action = default.erosion_air,
})
minetest.register_abm({
label = "Water erosion",
nodenames = {"group:erosion_water"},
neighbors = {"group:water"},
interval = 60,
chance = 2,
catch_up = false,
action = default.erosion_water,
})
minetest.register_abm({
label = "Heat erosion",
nodenames = {"group:erosion_heat"},
interval = 60,
chance = 2,
catch_up = false,
action = default.erosion_heat,
})
minetest.register_abm({
label = "Dry erosion",
nodenames = {"group:erosion_dry"},
interval = 60,
chance = 2,
catch_up = false,
action = default.erosion_dry,
})
minetest.register_abm({
label = "Wet erosion",
nodenames = {"group:erosion_wet"},
interval = 60,
chance = 2,
catch_up = false,
action = default.erosion_wet,
})

133
mods/default/shared.lua Normal file
View File

@ -0,0 +1,133 @@
local S = default.S;
--
-- shared functions
--
function default.shared_positions_in_cube(pos, distance, include_pos)
local positions = {};
local check_pos = table.copy(pos);
distance = math.floor(distance);
for x_diff = -distance,distance,1 do
check_pos.x = pos.x + x_diff;
for y_diff = -distance,distance,1 do
check_pos.y = pos.y + y_diff;
for z_diff = -distance,distance,1 do
check_pos.z = pos.z + z_diff;
if (include_pos==true) then
table.insert(positions, table.copy(check_pos));
else
if ((check_pos.x~=pos.x)or(check_pos.y~=pos.y)or(check_pos.z~=pos.z)) then
table.insert(positions, table.copy(check_pos));
end
end
end
end
end
return positions;
end
function default.shared_positions_with_distance_in_cube(pos, distance, include_pos)
local positions_and_distance = {};
local check_pos = table.copy(pos);
distance = math.floor(distance);
for x_diff = -distance,distance,1 do
check_pos.x = pos.x + x_diff;
for y_diff = -distance,distance,1 do
check_pos.y = pos.y + y_diff;
for z_diff = -distance,distance,1 do
check_pos.z = pos.z + z_diff;
local check_distance = vector.distance(check_pos, pos);
if (include_pos==true) then
table.insert(positions_and_distance, {pos=table.copy(check_pos),distance=check_distance});
else
if ((check_pos.x~=pos.x)or(check_pos.y~=pos.y)or(check_pos.z~=pos.z)) then
table.insert(positions_and_distance, {pos=table.copy(check_pos),distance=check_distance});
end
end
end
end
end
return positions_and_distance;
end
function default.shared_positions_in_sphere(pos, distance, include_pos)
local positions = {};
local check_pos = table.copy(pos);
local diff_limit = math.floor(distance);
for x_diff = -diff_limit,diff_limit,1 do
check_pos.x = pos.x + x_diff;
for y_diff = -diff_limit,diff_limit,1 do
check_pos.y = pos.y + y_diff;
for z_diff = -diff_limit,diff_limit,1 do
check_pos.z = pos.z + z_diff;
local check_distance = vector.distance(check_pos, pos);
if (check_distance<=distance) then
if (include_pos==true) then
table.insert(positions, table.copy(check_pos));
else
if ((check_pos.x~=pos.x)or(check_pos.y~=pos.y)or(check_pos.z~=pos.z)) then
table.insert(positions, table.copy(check_pos));
end
end
end
end
end
end
return positions;
end
function default.shared_positions_with_distance_in_sphere(pos, distance, include_pos)
local positions_and_distance = {};
local check_pos = table.copy(pos);
local diff_limit = math.floor(distance);
for x_diff = -diff_limit,diff_limit,1 do
check_pos.x = pos.x + x_diff;
for y_diff = -diff_limit,diff_limit,1 do
check_pos.y = pos.y + y_diff;
for z_diff = -diff_limit,diff_limit,1 do
check_pos.z = pos.z + z_diff;
local check_distance = vector.distance(check_pos, pos);
if (check_distance<=distance) then
if (include_pos==true) then
table.insert(positions_and_distance, {pos=table.copy(check_pos),distance=check_distance});
else
if ((check_pos.x~=pos.x)or(check_pos.y~=pos.y)or(check_pos.z~=pos.z)) then
table.insert(positions_and_distance, {pos=table.copy(check_pos),distance=check_distance});
end
end
end
end
end
end
return positions_and_distance;
end
function default.shared_add_chance_happen(chance_happen, add_happen_chance)
return (1.0-((1.0-chance_happen)*(1.0-add_happen_chance));
end
function default.shared_add_chance_no_happen(chance_happen, add_no_happen_chance)
return (1.0-((1.0-chance_happen)*add_no_happen_chance);
end

View File

@ -1,6 +1,51 @@
local S = default.S;
function default.wet_more_wet(pos, node)
minetest.log("warning", "Wet of node "..node.name.." pos X:"..tostring(pos.x).." Y:"..tostring(pos.y).." Z:"..tostring(pos.z))
local positions = default.shared_positions_in_sphere(pos, 1, false);
local wet_chance = 0.0;
local absorbing_power = minetest.get_item_group(node.name, "absorbing_power")/100.0;
local near_water_pos = minetest.find_node_near(pos, 50, {"group:water"});
local wet_power = 0.2;
if (near_water_pos~=nil) then
local water_distance = vector.distance(pos, near_water_pos);
wet_power = wet_power + water_distance/50;
end
for check_index,check_pos in pairs(positions) do
check_node = minetest.get_node(check_pos);
local absorbing_part = 0.0;
if (minetest.get_item_group(check_node.name, "water")>0) then
check_def = minetest.registered_nodes[check_node.name];
if (check_def.liquidtype=="flowing") then
absorbing_part = 0.33 + 0.67 * minetest.get_node_level(check_pos)/minetest.get_node_max_level(check_pos);
else
absorbing_part = 1.0;
end
elseif (minetest.get_item_group(node.name, "damp")>0) then
absorbing_part = wet_power * 0.083; --0.25 * 0.33;
elseif (minetest.get_item_group(node.name, "wet")>0) then
absorbing_part = wet_power * 0.167; -- 0.50 * 0.33;
elseif (minetest.get_item_group(node.name, "soggy")>0) then
absorbing_part = wet_power * 0.25; -- 0.75 * 0.33;
end
if (absorbing_part>0.0) then
erosion_chance = default.shared_add_chance_happen(erosion_chance, absorbing_part*erosion_water);
end
end
local chance = default.random_generator:next(0, 16777215)/16777215.0;
if (chance<=erosion_chance) then
default.apply_node_change(pos, node, "erosion");
end
end
minetest.register_abm({
label = "Wet of dry",
nodenames = {"group:absorbing_power"},