pedology/init.lua
2014-06-10 16:55:14 +02:00

510 lines
17 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

pedology = {}
pedology.wetnames = {[0] = "dry", "wet", "watery", "sludgy", "muddy", "slurry" }
dofile(minetest.get_modpath("pedology").."/settings.lua")
if pedology.USE_DRIPS == true then
dofile(minetest.get_modpath("pedology").."/drip.lua")
end
--[[ ABMs ]]
function pedology.ooze(pos, node, active_object_count, active_object_wider)
local wet = minetest.get_item_group(node.name, "wet")
if wet == 0 then return end
--[[ This table contain the nodes which are either neighbors
of node or which touch the node at an edge or corner and which are
not on a heigher y-level than
of node
]]
local neighbors = {
{ -- neighbor directly below
{x=pos.x, y=pos.y-1, z=pos.z},
minwet=1
},
{ -- touching the lower sides
{x=pos.x, y=pos.y-1, z=pos.z-1},
{x=pos.x, y=pos.y-1, z=pos.z+1},
{x=pos.x-1, y=pos.y-1, z=pos.z},
{x=pos.x+1, y=pos.y-1, z=pos.z},
minwet=1
},
{ -- touching the lower corners
{x=pos.x-1, y=pos.y-1, z=pos.z-1},
{x=pos.x-1, y=pos.y-1, z=pos.z+1},
{x=pos.x-1, y=pos.y-1, z=pos.z-1},
{x=pos.x+1, y=pos.y-1, z=pos.z+1},
{x=pos.x+1, y=pos.y-1, z=pos.z+1},
minwet=1
},
{ -- sides on the same level
{x=pos.x-1, y=pos.y, z=pos.z}, -- left
{x=pos.x+1, y=pos.y, z=pos.z}, -- right
{x=pos.x, y=pos.y, z=pos.z-1}, -- before
{x=pos.x, y=pos.y, z=pos.z+1}, -- behind
minwet=2
},
{ -- touching at the side on the same level
{x=pos.x-1, y=pos.y, z=pos.z-1},
{x=pos.x-1, y=pos.y, z=pos.z+1},
{x=pos.x+1, y=pos.y, z=pos.z-1},
{x=pos.x+1, y=pos.y, z=pos.z+1},
minwet=2
},
}
for i=1,#neighbors do
for j=1,#neighbors[i] do
local node = minetest.get_node(neighbors[i][j])
local name = node.name
local destwet = minetest.get_item_group(name, "wet")
if(
(destwet < wet) and
(minetest.get_item_group(name, "sucky") >= 1)) and
(neighbors[i].minwet <= (wet - destwet)) then
pedology.wetten(neighbors[i][j])
pedology.dry(pos)
return
end
end
end
end
--[[ This is an ABM action which wettens the node iff many water nodes
are neighbors of it or touching it at an edge or corner.]]
function pedology.suck(pos, node, active_object_count, active_object_wider)
local wet = minetest.get_item_group(node.name, "wet")
local score = 0
-- These three tables contain the positions of all nodes around node
local neighbors= {
{ -- sides
{x=pos.x, y=pos.y-1, z=pos.z}, -- below
{x=pos.x-1, y=pos.y, z=pos.z}, -- left
{x=pos.x+1, y=pos.y, z=pos.z}, -- right
{x=pos.x, y=pos.y+1, z=pos.z}, -- above
{x=pos.x, y=pos.y, z=pos.z-1}, -- before
{x=pos.x, y=pos.y, z=pos.z+1}, -- behind
rating = 1
},
{ -- edges
{x=pos.x, y=pos.y-1, z=pos.z-1},
{x=pos.x, y=pos.y-1, z=pos.z+1},
{x=pos.x, y=pos.y+1, z=pos.z-1},
{x=pos.x, y=pos.y+1, z=pos.z+1},
{x=pos.x-1, y=pos.y, z=pos.z-1},
{x=pos.x-1, y=pos.y, z=pos.z+1},
{x=pos.x+1, y=pos.y, z=pos.z-1},
{x=pos.x+1, y=pos.y, z=pos.z+1},
{x=pos.x-1, y=pos.y-1, z=pos.z},
{x=pos.x-1, y=pos.y+1, z=pos.z},
{x=pos.x+1, y=pos.y-1, z=pos.z},
{x=pos.x+1, y=pos.y+1, z=pos.z},
rating=0.5
},
{ -- corners
{x=pos.x-1, y=pos.y-1, z=pos.z-1},
{x=pos.x-1, y=pos.y-1, z=pos.z+1},
{x=pos.x-1, y=pos.y+1, z=pos.z-1},
{x=pos.x-1, y=pos.y+1, z=pos.z+1},
{x=pos.x-1, y=pos.y-1, z=pos.z-1},
{x=pos.x+1, y=pos.y+1, z=pos.z+1},
{x=pos.x+1, y=pos.y+1, z=pos.z-1},
{x=pos.x+1, y=pos.y-1, z=pos.z+1},
{x=pos.x+1, y=pos.y-1, z=pos.z+1},
rating=0.25
}
}
for i=1,#neighbors do
for j=1,#neighbors[i] do
local neighbor = minetest.get_node(neighbors[i][j])
local name = neighbor.name
local water = minetest.get_item_group(name, "water")
if(water >= 1) then
score = score + neighbors[i].rating
end
end
end
local wetten = false
if(wet == 0 and score >= 1) then
wetten=true
elseif(wet == 1 and score >= 2) then
wetten= true
elseif(wet == 2 and score >= 3) then
wetten=true
elseif(wet == 3 and score >= 5) then
wetten=true
elseif(wet == 4 and score >= 8) then
wetten=true
elseif(wet == 5 and score >= 11) then
-- erosion: turn node into water
-- TODO: Also drop the drops
minetest.set_node(pos, {name="pedology:water_fresh_source"})
return
end
if(wetten==true) then
pedology.wetten(pos)
end
end
--[[ ABM action which dries out a node when it is in direct sunlight ]]
function pedology.sun_dry(pos, node, active_object_count, active_object_wider)
if(minetest.get_item_group(node.name, "wet") < 6) then
-- dont dry off if there is water nearby
if(not minetest.find_node_near(pos, 1, {"group:water"})) then
local light = minetest.get_node_light(pos, minetest.get_timeofday())
if light >= pedology.DRY_LIGHT then
pedology.dry(pos)
end
end
end
end
--[[ air and vacuum]]
minetest.register_node("pedology:vacuum", {
description = "vacuum",
inventory_image="unknown_node.png",
wield_image="unknown_node.png",
paramtype="light",
drawtype="airlike",
damage_per_second=8,
drowning=8,
sunlight_propagates=true,
walkable=false,
pointable=false,
diggable=false,
buildable_to=true,
groups={not_in_creative_inventory=1}
})
minetest.register_node("pedology:thinair2", {
description = "very thin air",
inventory_image="unknown_node.png",
wield_image="unknown_node.png",
paramtype="light",
drawtype="airlike",
sunlight_propagates=true,
walkable=false,
pointable=false,
diggable=false,
buildable_to=true,
groups={not_in_creative_inventory=1}
})
minetest.register_node("pedology:thinair1", {
description = "thin air",
inventory_image="unknown_node.png",
wield_image="unknown_node.png",
paramtype="light",
drawtype="airlike",
sunlight_propagates=true,
walkable=false,
pointable=false,
diggable=false,
buildable_to=true,
groups={not_in_creative_inventory=1}
})
--[[ liquids ]]
function pedology.register_liquid(basename, description, alpha, viscosity, drowning, damage_per_second, post_effect_color, additional_groups)
flowing_groups = {wet=6,not_in_creative_inventory=1}
source_groups = {wet=6}
for k,v in pairs(additional_groups) do
flowing_groups[k] = v
source_groups[k] = v
end
local tile = "pedology_"..basename..".png"
local nodedef_source = {
description = description.." source",
inventory_image = minetest.inventorycube(tile),
tiles = {tile},
alpha = alpha,
paramtype = "light",
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
drop = "",
liquid_alternative_flowing = "pedology:"..basename.."_flowing",
liquid_alternative_source = "pedology:"..basename.."_source",
liquid_viscosity = viscosity,
post_effect_color = post_effect_color,
drowning = drowning,
damage_per_second = damage_per_second,
drawtype = "liquid",
liquidtype = "source",
groups = source_groups,
}
minetest.register_node("pedology:"..basename.."_source", nodedef_source)
local nodedef_flowing = {
description = description.." flowing",
inventory_image = minetest.inventorycube(tile),
tiles = {tile},
alpha = alpha,
paramtype = "light",
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
drop = "",
liquid_alternative_flowing = "pedology:"..basename.."_flowing",
liquid_alternative_source = "pedology:"..basename.."_source",
liquid_viscosity = viscosity,
post_effect_color = post_effect_color,
drowning = drowning,
damage_per_second = damage_per_second,
drawtype = "flowingliquid",
liquidtype = "flowing",
groups = flowing_groups,
paramtype2 = "flowingliquid",
}
minetest.register_node("pedology:"..basename.."_flowing", nodedef_flowing)
end
pedology.register_liquid("water_fresh", "freshwater", 100, 1, 2, 0, {a=60, r=100, b=200, g=100}, {water=1})
--pedology.register_liquid("water_salt", "salt water", 180, 2, 4, 0, {a=80, r=120, b=200, g=120}, {water=1})
pedology.register_liquid("water_ponding", "ponding water", 234, 4, 3, 0, {a=128, r=85, g=85, g=60}, {water=1})
--[[
TODO: Decide wheather to keep or to remove lava
pedology.register_liquid("lava_1", "very hot lava", 230, 2, 10, 8, {a=230, r=255, g=0, b=0}, {hot=6000, lava=1})
pedology.register_liquid("lava_2", "hot lava", 230, 3, 9, 7, {a=230, r=255, g=0, b=0}, {hot=5000, lava=1})
pedology.register_liquid("lava_3", "lava", 230, 4, 8, 6, {a=230, r=255, g=0, b=0}, {hot=4000, lava=1})
pedology.register_liquid("lava_4", "cold lava", 230, 5, 7, 6, {a=230, r=255, g=0, b=0}, {hot=3000, lava=1})
]]
--[[ register a sucky/oozing node to this mod ]]
function pedology.register_sucky(basename, description, wetness, oozing, sucky, melting_point, sounds, additional_groups)
local wetname = basename.."_"..tostring(wetness)
local noncreative
local groups = { sucky=sucky, oozing=oozing, wet=wetness, melting_point=melting_point, not_in_creative_inventory = noncreative, [basename]=1 }
if additional_groups ~= nil then
for k,v in pairs(additional_groups) do
groups[k] = v
end
end
-- If the node is not dry, do not add it into the creative inventory
if wetness == 0 then noncreative = 0 else noncreative = 1 end
local nodedef = {
description = description,
inventory_image = minetest.inventorycube("pedology_"..wetname..".png"),
tiles = {"pedology_"..wetname..".png"},
paramtype = "light",
-- drop = "pedology:"..basename.."_lump 4",
groups = groups,
sounds = sounds,
}
local name = "pedology:"..wetname
minetest.register_node(name, nodedef)
end
--[[
This function registers a couple of sucky/oozing nodes, including all their “wet” variants.
It also registers an ABM.
parameters:
basename: The internal name piece from which the concrete basenames will be build. The wetness level will be appended.
basedescription. The description of the nodes. A proper wetness adjective (“dry”, “wet”, …) will be prepended.
maxwet: The maximum wetness level of this node group (minimum: 0, maximum: 5)
oozeinterval: The interval in seconds in which it the node may ooze. the Minimal value: 1
oozechance: The inverted chance (1/x) to ooze
melttable: Table of melting_point values for each wetness level
sounds: Sound specification for all nodes
additional_groups: table of additional groups of all the nodes. May be empty or nil (meaning no additional groups).
]]
function pedology.register_sucky_group(basename, basedescription, maxwet, oozeinterval, oozechance, melttable, sounds, additional_groups)
local oozing, dripinterval
local m -- melting_point
for w=0, maxwet do
if(w==0) then oozing=0 else oozing=1 end
if (w==maxwet and w ~= 5) then sucky=0 else sucky=1 end
if melttable == nil then m = 0 else m = melttable[w] end
pedology.register_sucky(basename, (pedology.wetnames[w]).." "..basedescription, w, oozing, sucky, m, sounds, additional_groups)
-- register dripping
if(w>0 and pedology.USE_DRIPS == true) then
minetest.register_abm({
nodenames = {"pedology:"..basename.."_"..tostring(w)},
neighbors = {"air"},
interval = math.max(oozeinterval/4,2),
chance = math.max(oozechance,22),
action = pedology.create_drip,
})
end
end
if(maxwet > 0) then
minetest.register_abm({
nodenames = {"group:"..basename},
neighbors = {"group:sucky"},
interval = oozeinterval,
chance = oozechance,
action = pedology.ooze,
})
end
end
do
local sound_clay = {footstep = {name="pedology_clay_footstep", gain=0.5}}
local sound_silt_fine = {footstep = {name="pedology_silt_footstep", gain=0.3}}
local sound_silt_medium = {footstep = {name="pedology_silt_footstep", gain=0.35}}
local sound_silt_coarse = {footstep = {name="pedology_silt_footstep", gain=0.4}}
local sound_sand_fine = {footstep = {name="pedology_sand_footstep", gain=0.2}}
local sound_sand_medium = {footstep = {name="pedology_sand_footstep", gain=0.25}}
local sound_sand_coarse = {footstep = {name="pedology_sand_footstep", gain=0.3}}
local sound_gravel_fine = {footstep = {name="pedology_gravel_footstep", gain=1}}
local sound_gravel_medium = {footstep = {name="pedology_gravel_footstep", gain=1}}
local sound_gravel_coarse = {footstep = {name="pedology_gravel_footstep", gain=1}}
--[[ register sucky and oozing nodes ]]
--[[ ground nodes ]]
pedology.register_sucky_group("clay", "clay",
5, 60, 1.25, {3000, 3100, 3200, 3500, 3550, 3600}, sound_clay, { crumbly = 3, sun_dry = 1})
pedology.register_sucky_group("silt_fine", "fine silt",
5, 45, 1.25, {2800, 2900, 3000, 3100, 3200, 3300}, sound_silt_fine, { crumbly = 3, sun_dry = 1 })
pedology.register_sucky_group("silt_medium", "medium silt",
4, 30, 1.25, {2600, 2800, 3200, 3800, 4200}, sound_silt_medium, { crumbly = 3, sun_dry = 1 })
pedology.register_sucky_group("silt_coarse", "coarse silt",
3, 20, 1.25, {2000, 2200, 2400, 2800}, sound_silt_coarse, { crumbly = 3, sun_dry = 1 })
pedology.register_sucky_group("sand_fine", "fine sand",
2, 10, 1.111111, {1100, 1200, 1300}, sound_sand_fine, { crumbly = 3, sand = 1, sun_dry = 1 })
pedology.register_sucky_group("sand_medium", "medium sand",
1, 5, 1.111111, {990, 1100}, sound_sand_medium, { crumbly = 3, sand = 1, sun_dry = 1 })
pedology.register_sucky_group("sand_coarse", "coarse sand",
0, nil, nil, {900}, sound_sand_coarse, { crumbly = 3, sand = 1, sun_dry = 1 })
pedology.register_sucky_group("gravel_fine", "fine gravel",
1, 2, 1, {670, 770}, sound_gravel_fine, { crumbly = 2, sun_dry = 1 })
pedology.register_sucky_group("gravel_medium", "medium gravel",
2, 1.5, 1, {600, 800, 1250}, sound_gravel_medium, { crumbly = 2, sun_dry = 1})
pedology.register_sucky_group("gravel_coarse", "coarse gravel",
2, 1, 1, {500, 750, 1000}, sound_gravel_coarse, { crumbly = 1, sun_dry = 1 })
--[[ TODO: clay mud
pedology.register_liquid("clay_3", "sludgy clay", 192, 6, 5, 0, {a=192, r=104, g=23, b=0}, {oozing=1})
pedology.register_liquid("clay_4", "muddy clay", 156, 4, 5, 0, {a=156, r=123, g=57, b=6}, {oozing=1})
pedology.register_liquid("clay_5", "slurry clay", 128, 2, 5, 0, {a=128, r=146, g=85, b=73}, {oozing=1})
]]
--[[ turf ]]
--[[pedology.register_sucky_group("turf_fibric", "fibric turf",
2, 120, 1.25, {1000, 1100, 1200}, sound_silt_coarse, { crumbly = 3, flammable = 1 } )
pedology.register_sucky_group("turf_hemic", "hemic turf",
2, 180, 1.225, {1100, 1200, 1300}, sound_silt_coarse, { crumbly = 3, flammable = 1 } )
pedology.register_sucky_group("turf_sapric", "sapric turf",
2, 240, 1.2, {1200, 1300, 1400}, sound_silt_coarse, { crumbly = 3, flammable = 1 } )]]
pedology.register_sucky("turf_fibric", "dry fibric turf", 0, 0, 1, 1000, sound_silt_coarse, { crumbly = 3, flammable = 1 } )
pedology.register_sucky("turf_fibric", "wet fibric turf", 1, 1, 1, 1100, sound_silt_coarse, { crumbly = 3 } )
pedology.register_sucky("turf_fibric", "watery fibric turf", 2, 1, 0, 1200, sound_silt_coarse, { crumbly = 3 } )
pedology.register_sucky("turf_hemic", "dry hemic turf", 0, 0, 1, 1100, sound_silt_coarse, { crumbly = 3, flammable = 1 } )
pedology.register_sucky("turf_hemic", "wet hemic turf", 1, 1, 1, 1200, sound_silt_coarse, { crumbly = 3 } )
pedology.register_sucky("turf_hemic", "watery hemic turf", 2, 1, 0, 1300, sound_silt_coarse, { crumbly = 3 } )
pedology.register_sucky("turf_sapric", "dry sapric turf", 0, 0, 1, 1200, sound_silt_coarse, { crumbly = 3, flammable = 1 } )
pedology.register_sucky("turf_sapric", "wet sapric turf", 1, 1, 1, 1300, sound_silt_coarse, { crumbly = 3 } )
pedology.register_sucky("turf_sapric", "watery sapric turf", 2, 1, 0, 1400, sound_silt_coarse, { crumbly = 3 } )
minetest.register_abm({
nodenames = {"group:turf_fibric"}, neighbors = {"group:sucky"}, interval = 120, chance = 1.25, action = pedology.ooze
})
minetest.register_abm({
nodenames = {"group:turf_hemic"}, neighbors = {"group:sucky"}, interval = 180, chance = 1.225, action = pedology.ooze
})
minetest.register_abm({
nodenames = {"group:turf_sapric"}, neighbors = {"group:sucky"}, interval = 240, chance = 1.5, action = pedology.ooze
})
end
pedology.maxwet = {}
pedology.maxwet.clay = 5
pedology.maxwet.silt_fine = 5
pedology.maxwet.silt_medium = 4
pedology.maxwet.silt_coarse = 3
pedology.maxwet.sand_fine = 2
pedology.maxwet.sand_medium = 1
pedology.maxwet.sand_coarse = 0
pedology.maxwet.gravel_fine = 1
pedology.maxwet.gravel_medium = 2
pedology.maxwet.gravel_coarse = 2
pedology.maxwet.turf_fibric = 2
pedology.maxwet.turf_hemic = 2
pedology.maxwet.turf_sapric = 2
--[[ “API” functions ]]
--[[ Replace the node at <pos> with a node with a “drier” version of it, if available ]]
function pedology.dry(pos)
local node = minetest.get_node(pos)
local wet = minetest.get_item_group(node.name, "wet")
local dried = tostring(wet - 1)
if wet <= 0 then
return
end
local newbasename = string.sub(node.name,1,#node.name-1)
newbasename = newbasename .. dried
minetest.set_node(pos, {name=newbasename, param1=0, param2=0})
end
--[[ Replace the node at <pos> with a “wetter” version of it, if available ]]
function pedology.wetten(pos)
local node = minetest.get_node(pos)
local wet = minetest.get_item_group(node.name, "wet")
local cutbasename = string.sub(node.name,9,#node.name-2)
if pedology.maxwet[cutbasename] == nil then
return
elseif wet > pedology.maxwet[cutbasename] then
return
end
local newbasename = string.sub(node.name,1,#node.name-1) .. tostring(wet+1)
minetest.set_node(pos, {name=newbasename, param1=0, param2=0})
end
--[[ register ABMs ]]
minetest.register_abm({
nodenames = {"group:sun_dry"},
neighbors = {"air"},
interval = 30,
chance = 10,
action = pedology.sun_dry,
})
minetest.register_abm({
nodenames = {"group:sucky"},
neighbors = {"group:water"},
interval = 30,
chance = 1,
action = pedology.suck,
})
minetest.register_abm({
nodenames = {"group:melting_point"},
neighbors = {"group:hot"},
interval = 1,
chance = 1,
action = function(pos,node,...)
minetest.set_node(pos,node)
end,
})