pedology/init.lua
2014-06-13 02:58:55 +02:00

573 lines
20 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, lumpdescription, wetness, oozing, sucky, melting_point, drop, 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
local name = "pedology:"..wetname
local itemname
-- 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 = drop,
groups = groups,
sounds = sounds,
}
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.
lumpdescription. The description component of the “lump” of the node. If nil, no lump is used
maxwet: The maximum wetness level of this node group (minimum: 0, maximum: 5)
maxlump: The maximum wetness level of lumps of this node group (minimum: 0, recommended maximum: 3)
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
dropcount: How many lumps nodes of this group drop. If 0, the nodes simply drop themselves (not recommended!)
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, lumpbasedescription, maxwet, maxlump, oozeinterval, oozechance, melttable, dropcount, sounds, additional_groups)
local oozing, dripinterval
local m -- melting_point
local lumpdescription
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
if( lumpbasedescription ~= nil) then
lumpdescription = (pedology.wetnames[w]).." "..lumpbasedescription
else
lumpdescription = nil
end
local itemname, drop, itemdef
if( maxlump == -1) then
drop = nil
elseif( w > maxlump) then
itemname = "pedology:"..basename.."_lump_"..tostring(maxlump)
drop = itemname .. " " .. tostring(dropcount)
else
itemname = "pedology:"..basename.."_lump_"..tostring(w)
drop = itemname .. " " .. tostring(dropcount)
itemdef = {
description = lumpdescription,
inventory_image = "pedology_lump_inv_"..basename.."_"..tostring(w)..".png",
wield_image = "pedology_lump_"..basename.."_"..tostring(w)..".png"
}
minetest.register_craftitem("pedology:"..basename.."_lump_"..tostring(w), itemdef)
end
pedology.register_sucky(basename, (pedology.wetnames[w]).." "..basedescription, lumpdescription, w, oozing, sucky, m, drop, 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", "clay lump",
5, 3, 60, 1.25, {3000, 3100, 3200, 3500, 3550, 3600}, 4, sound_clay, { crumbly = 3, sun_dry = 1})
pedology.register_sucky_group("silt_fine", "fine silt", "fine silt lump",
5, 3, 45, 1.25, {2800, 2900, 3000, 3100, 3200, 3300}, 4, sound_silt_fine, { crumbly = 3, sun_dry = 1 })
pedology.register_sucky_group("silt_medium", "medium silt", "medium silt lump",
4, 3, 30, 1.25, {2600, 2800, 3200, 3800, 4200}, 4, sound_silt_medium, { crumbly = 3, sun_dry = 1 })
pedology.register_sucky_group("silt_coarse", "coarse silt", "coarse silt lump",
3, 3, 20, 1.25, {2000, 2200, 2400, 2800}, 4, sound_silt_coarse, { crumbly = 3, sun_dry = 1 })
pedology.register_sucky_group("sand_fine", "fine sand", nil,
2, -1, 10, 1.111111, {1100, 1200, 1300}, 0, sound_sand_fine, { crumbly = 3, sand = 1, sun_dry = 1 })
pedology.register_sucky_group("sand_medium", "medium sand", nil,
1, -1, 5, 1.111111, {990, 1100}, 0, sound_sand_medium, { crumbly = 3, sand = 1, sun_dry = 1 })
pedology.register_sucky_group("sand_coarse", "coarse sand", nil,
0, -1, nil, nil, {900}, 0, sound_sand_coarse, { crumbly = 3, sand = 1, sun_dry = 1 })
pedology.register_sucky_group("gravel_fine", "fine gravel", "pebble",
1, 0, 2, 1, {670, 770}, 9, sound_gravel_fine, { crumbly = 2, sun_dry = 1 })
pedology.register_sucky_group("gravel_medium", "medium gravel", "medium stone",
2, 0, 1.5, 1, {600, 800, 1250}, 3, sound_gravel_medium, { crumbly = 2, sun_dry = 1})
pedology.register_sucky_group("gravel_coarse", "coarse gravel", "big stone",
2, 0, 1, 1, {500, 750, 1000}, 1, 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 } )]]
--[[ TODO (v5.0): Write registration function for turf to condense redundant code. Its a mess! ]]
pedology.register_sucky("turf_fibric", "dry fibric turf", "dry fibric turf cutting", 0, 0, 1, 1000, 4, sound_silt_coarse, { crumbly = 3, flammable = 1 } )
pedology.register_sucky("turf_fibric", "wet fibric turf", "wet fibric turf cutting", 1, 1, 1, 1100, 4, sound_silt_coarse, { crumbly = 3 } )
pedology.register_sucky("turf_fibric", "watery fibric turf", "watery fibric turf cutting", 2, 1, 0, 1200, 4, sound_silt_coarse, { crumbly = 3 } )
pedology.register_sucky("turf_hemic", "dry hemic turf", "dry hemic turf cutting", 0, 0, 1, 1100, 3, sound_silt_coarse, { crumbly = 3, flammable = 1 } )
pedology.register_sucky("turf_hemic", "wet hemic turf", "wet hemic turf cutting", 1, 1, 1, 1200, 3, sound_silt_coarse, { crumbly = 3 } )
pedology.register_sucky("turf_hemic", "watery hemic turf", "watery hemic turf cutting", 2, 1, 0, 1300, 3, sound_silt_coarse, { crumbly = 3 } )
pedology.register_sucky("turf_sapric", "dry sapric turf", "dry sapric turf cutting", 0, 0, 1, 1200, 2, sound_silt_coarse, { crumbly = 3, flammable = 1 } )
pedology.register_sucky("turf_sapric", "wet sapric turf", "wet sapric turf cutting", 1, 1, 1, 1300, 2, sound_silt_coarse, { crumbly = 3 } )
pedology.register_sucky("turf_sapric", "watery sapric turf", "watery sapric turf cutting", 2, 1, 0, 1400, 2, 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
})
minetest.register_craft({
type = "fuel",
recipe = "pedology:turf_fibric_0",
burntime = 100,
})
minetest.register_craft({
type = "fuel",
recipe = "pedology:turf_hemic_0",
burntime = 200,
})
minetest.register_craft({
type = "fuel",
recipe = "pedology:turf_sapric_0",
burntime = 300,
})
minetest.register_craft({
type = "fuel",
recipe = "pedology:lump_turf_fibric_0",
burntime = 10,
})
minetest.register_craft({
type = "fuel",
recipe = "pedology:lump_turf_hemic_0",
burntime = 20,
})
minetest.register_craft({
type = "fuel",
recipe = "pedology:lump_turf_sapric_0",
burntime = 30,
})
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,
})