9607bcc6a6
- Clean up registered_* usage patterns. - Reduce tendancy of leaves to create stack nodes. Now they tend to stack up properly in-world more often. - Tweak damage system to create "headroom" where minor damage doesn't cost inv slots immediately. - Make player hand skin color match model skin. - Cleanup/unify grass abm logic. - Start installing new sounds by MagikEh Sound source: https://github.com/MagikEh/SoundsOfWarr
110 lines
3.2 KiB
Lua
110 lines
3.2 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local math, minetest, nodecore, pairs, type
|
|
= math, minetest, nodecore, pairs, type
|
|
local math_random
|
|
= math.random
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
--[[
|
|
Nodes with the "falling_repose" group will not only fall if unsupported
|
|
from below, but if there is a sufficient drop off the sides, so simulate
|
|
an "angle of repose."
|
|
--]]
|
|
|
|
function nodecore.falling_repose_drop(posfrom, posto, node)
|
|
minetest.spawn_falling_node(posto, node, minetest.get_meta(posfrom))
|
|
minetest.remove_node(posfrom)
|
|
posfrom.y = posfrom.y + 1
|
|
return minetest.check_for_falling(posfrom)
|
|
end
|
|
|
|
nodecore.register_on_register_item(function(name, def)
|
|
if def.type ~= "node" then return end
|
|
|
|
def.groups = def.groups or {}
|
|
|
|
if def.groups.falling_repose then def.groups.falling_node = 1 end
|
|
|
|
def.repose_drop = def.repose_drop or nodecore.falling_repose_drop
|
|
end)
|
|
|
|
function minetest.spawn_falling_node(pos, node, meta)
|
|
node = node or minetest.get_node(pos)
|
|
if node.name == "air" or node.name == "ignore" then
|
|
return false
|
|
end
|
|
local obj = minetest.add_entity(pos, "__builtin:falling_node")
|
|
if obj then
|
|
obj:get_luaentity():set_node(node, meta or minetest.get_meta(pos):to_table())
|
|
minetest.remove_node(pos)
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function check_empty(pos, dx, dy, dz)
|
|
for ndy = dy, 1 do
|
|
local p = {x = pos.x + dx, y = pos.y + ndy, z = pos.z + dz}
|
|
if not nodecore.buildable_to(p) then return end
|
|
end
|
|
return {x = pos.x + dx, y = pos.y, z = pos.z + dz}
|
|
end
|
|
function nodecore.falling_repose_check(pos)
|
|
if minetest.check_single_for_falling(pos) then return end
|
|
local node = minetest.get_node(pos)
|
|
local def = minetest.registered_items[node.name] or {}
|
|
local repose = def.groups and def.groups.falling_repose
|
|
if not repose then return end
|
|
|
|
-- Reposing nodes can always sit comfortably atop
|
|
-- a non-moving node; it's only when stacked on other
|
|
-- falling nodes that they can slip off.
|
|
local sitdef = minetest.registered_items[minetest.get_node(
|
|
{x = pos.x, y = pos.y - 1, z = pos.z}).name]
|
|
if not (sitdef and sitdef.groups and sitdef.groups.falling_node)
|
|
then return end
|
|
|
|
local open = {}
|
|
local ok = check_empty(pos, 1, -repose, 0)
|
|
if ok then open[1] = ok end
|
|
ok = check_empty(pos, -1, -repose, 0)
|
|
if ok then open[#open + 1] = ok end
|
|
ok = check_empty(pos, 0, -repose, 1)
|
|
if ok then open[#open + 1] = ok end
|
|
ok = check_empty(pos, 0, -repose, -1)
|
|
if ok then open[#open + 1] = ok end
|
|
if #open < 1 then return end
|
|
return def.repose_drop(pos, open[math_random(1, #open)], node)
|
|
end
|
|
|
|
local reposeq
|
|
local qqty
|
|
local qmax = 100
|
|
local function reposeall()
|
|
for _, v in pairs(reposeq) do v() end
|
|
reposeq = nil
|
|
qqty = nil
|
|
end
|
|
nodecore.register_limited_abm({
|
|
label = "Falling Repose",
|
|
nodenames = {"group:falling_repose"},
|
|
neighbors = {"air"},
|
|
interval = 2,
|
|
chance = 5,
|
|
action = function(pos, node)
|
|
if not reposeq then
|
|
reposeq = {}
|
|
qqty = 0
|
|
minetest.after(0, reposeall)
|
|
end
|
|
local f = function() nodecore.falling_repose_check(pos) end
|
|
if #reposeq > qmax then
|
|
local i = math_random(1, qqty)
|
|
if i < qmax then reposeq[i] = f end
|
|
else
|
|
reposeq[#reposeq + 1] = f
|
|
end
|
|
qqty = qqty + 1
|
|
end
|
|
})
|