9674a3cbe8
Presumably this had to do with tote survival
179 lines
4.7 KiB
Lua
179 lines
4.7 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local ipairs, math, minetest, nodecore, pairs, vector
|
|
= ipairs, math, minetest, nodecore, pairs, vector
|
|
local math_random, math_sqrt
|
|
= math.random, math.sqrt
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local modname = minetest.get_current_modname()
|
|
|
|
local alldirs = nodecore.dirs()
|
|
|
|
local living = modname .. ":sponge_living"
|
|
local wet = modname .. ":sponge_wet"
|
|
|
|
local water = {}
|
|
local sand = {}
|
|
|
|
local dryitems = {}
|
|
local drydrawtypes = {
|
|
nodebox = true,
|
|
signlike = true,
|
|
mesh = true,
|
|
allfaces_optional = true
|
|
}
|
|
minetest.after(0, function()
|
|
for k, v in pairs(minetest.registered_items) do
|
|
if v["type"] == "node" and v.groups.water then
|
|
water[k] = true
|
|
end
|
|
if v["type"] == "node" and v.groups.sand then
|
|
sand[k] = true
|
|
end
|
|
if v["type"] ~= "node" or (v.groups.damage_radiant or 0) > 0
|
|
or v.liquidtype == "none" and not v.groups.moist
|
|
and not v.groups.silica and (drydrawtypes[v.drawtype]
|
|
or v.climbable or not v.walkable) then
|
|
dryitems[k] = true
|
|
end
|
|
end
|
|
end)
|
|
|
|
local function notdry(pos)
|
|
local node = minetest.get_node_or_nil(pos)
|
|
if not node then return true end
|
|
if not dryitems[node.name] then return true end
|
|
local def = minetest.registered_items[node.name]
|
|
if def and def.groups.is_stack_only then
|
|
local stack = nodecore.stack_get(pos)
|
|
return minetest.get_item_group(stack:get_name(), "moist") > 0
|
|
end
|
|
end
|
|
|
|
local accessdirs = nodecore.dirs()
|
|
local function sealed_or_notdry(nodename, pos)
|
|
local def = minetest.registered_nodes[nodename]
|
|
if def and def.groups and def.groups.storebox_sealed and def.groups.storebox_sealed > 0 then
|
|
if not pos then return true end
|
|
for i = 1, #accessdirs do
|
|
local pt = {
|
|
type = "node",
|
|
above = vector.add(accessdirs[i], pos),
|
|
under = pos
|
|
}
|
|
if (not def.storebox_access) or def.storebox_access(pt, pos,
|
|
{name = nodename, param = 0, param2 = 0}) then
|
|
if not notdry(pt.above) then return end
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
if not pos then return end
|
|
for _, d in pairs(alldirs) do
|
|
if not notdry(vector.add(pos, d)) then return end
|
|
end
|
|
return true
|
|
end
|
|
|
|
local function spongesurvive(data)
|
|
if data.toteslot then
|
|
return sealed_or_notdry(data.toteslot.n.name)
|
|
elseif data.node then
|
|
return sealed_or_notdry(data.node.name, data.pos)
|
|
elseif data.inv then
|
|
return notdry(data.pos)
|
|
end
|
|
end
|
|
nodecore.spongesurvive = spongesurvive
|
|
|
|
nodecore.register_dnt({
|
|
name = modname .. ":spongedie",
|
|
nodenames = {living},
|
|
time = 2,
|
|
action = function(pos, node)
|
|
if not spongesurvive({pos = pos, node = node}) then
|
|
nodecore.set_loud(pos, {name = wet})
|
|
return nodecore.fallcheck(pos)
|
|
end
|
|
end
|
|
})
|
|
minetest.register_abm({
|
|
label = "sponge death",
|
|
interval = 2,
|
|
chance = 5,
|
|
nodenames = {living},
|
|
arealoaded = 1,
|
|
action = function(pos, node)
|
|
if not spongesurvive({pos = pos, node = node}) then
|
|
nodecore.dnt_set(pos, modname .. ":spongedie")
|
|
end
|
|
end
|
|
})
|
|
|
|
nodecore.register_aism({
|
|
label = "sponge stack death",
|
|
interval = 2,
|
|
chance = 1,
|
|
arealoaded = 1,
|
|
itemnames = {living},
|
|
action = function(stack, data)
|
|
if spongesurvive(data) then return end
|
|
nodecore.sound_play("nc_terrain_swishy", {gain = 1, pos = data.pos})
|
|
stack:set_name(wet)
|
|
return stack
|
|
end
|
|
})
|
|
|
|
local growdirs = {}
|
|
for _, p in pairs(nodecore.dirs()) do
|
|
if p.y >= 0 then growdirs[#growdirs + 1] = p end
|
|
end
|
|
|
|
local basecost = 2000
|
|
nodecore.register_soaking_abm({
|
|
label = "sponge grow",
|
|
fieldname = "spongegrow",
|
|
nodenames = {living},
|
|
interval = 5,
|
|
chance = 2,
|
|
arealoaded = 6,
|
|
soakrate = function() return 2 end,
|
|
soakcheck = function(data, pos)
|
|
if data.total < basecost then return end
|
|
|
|
local count = 0
|
|
if nodecore.scan_flood(pos, 6,
|
|
function(p, d)
|
|
if d >= 6 then return true end
|
|
if minetest.get_node(p).name ~= living then return false end
|
|
count = count + 1
|
|
if count >= 20 then return true end
|
|
end
|
|
) then return false end
|
|
local realcost = basecost * math_sqrt(count)
|
|
if data.total < realcost then return end
|
|
|
|
for i = #growdirs, 2, -1 do
|
|
local j = math_random(1, i)
|
|
growdirs[i], growdirs[j] = growdirs[j], growdirs[i]
|
|
end
|
|
for _, rel in ipairs(growdirs) do
|
|
local dest = vector.add(pos, rel)
|
|
local node = minetest.get_node(dest)
|
|
if water[node.name] then
|
|
local below = {x = dest.x, y = dest.y - 1, z = dest.z}
|
|
node = minetest.get_node(below)
|
|
if node.name == living or sand[node.name] then
|
|
nodecore.set_loud(dest, {name = living})
|
|
if dest.y <= pos.y and math_random(1, 2) == 1 then
|
|
nodecore.soaking_abm_push(dest,
|
|
"spongegrow", data.total - realcost)
|
|
end
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
})
|