Commit f894c9e7 authored by Aaron Suen's avatar Aaron Suen
Browse files

Experimental density/buoyancy mechanic.

Like MT's "float" system but on steroids.  Things can fall
through some fluids, but float atop other fluids.  Falling node,
item mechanics are all affected, as well as repose, etc.

Not actually working yet: throw some lode prills onto some lava
and you will get some rapid cycling with ringing sounds.
parent 06d25946
......@@ -5,20 +5,6 @@ local math_floor, math_pi, math_sqrt
= math.floor, math.pi, math.sqrt
-- LUALOCALS > ---------------------------------------------------------
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 obj
end
return false
end
function nodecore.stackentprops(stack, yaw, rotate, ss)
local props = {
hp_max = 1,
......@@ -69,21 +55,49 @@ function nodecore.entity_staticdata_helpers(savedprops)
end
local area_unloaded = {}
nodecore.falling_collides_area_unloaded = area_unloaded
local function collides(pos)
local function density(name, def)
local d = minetest.get_item_group(name, "density")
if d and d ~= 0 then return d end
def = def or minetest.registered_items[name]
if def then
if def.type ~= "node" then return 50 end
if def.liquidtype == "source" then return 30 end
if def.liquidtype == "flowing" then return 20 end
if not def.walkable then return 0 end
end
return 100
end
function nodecore.falling_collides(pos, itemname, settled)
local node = minetest.get_node_or_nil(pos)
if not node then return area_unloaded end
local def = minetest.registered_nodes[node.name]
if not def then return node end
if def.walkable then return node end
if settled then
if not def then return node end
if def.walkable then return node end
end
local md = density(itemname)
local pd = density(node.name)
if md == pd then
local p = vector.round(pos)
p = p.x + p.y + p.z + math_floor(nodecore.gametime / 5)
p = p / 2
return p == math_floor(p) and node or nil
end
if md < pd then return node end
end
function nodecore.entity_settle_check(on_settle, isnode)
function nodecore.entity_settle_check(on_settle, getname, isnode)
return function(self)
local pos = self.object:get_pos()
local yvel = self.object:get_velocity().y
local coll = (isnode or self.not_rising and yvel == 0)
and collides({x = pos.x, y = pos.y - 0.75, z = pos.z})
local itemname = getname(self)
local function collides(p)
return nodecore.falling_collides(p, itemname,
isnode or self.not_rising and yvel == 0)
end
local coll = collides({x = pos.x, y = pos.y - 0.75, z = pos.z})
self.not_rising = yvel <= 0
if not coll then
if self.setvel then
......
......@@ -102,6 +102,7 @@ minetest.register_entity(":__builtin:falling_node", {
return true
end,
function(self) return self.node and self.node.name end,
true),
on_step = function(self, ...)
......
......@@ -9,3 +9,4 @@ include("api")
include("falling_ent")
include("item_ent")
include("item_merge")
include("overrides")
......@@ -80,7 +80,9 @@ minetest.register_entity(":__builtin:item", {
if func(self, ...) == true then return true end
end
nodecore.item_ent_merge(self.object:get_pos())
end),
end,
function(self) return ItemStack(self.itemstring):get_name() end
),
on_step = function(self, dtime, ...)
if not self.itemstring then return self.object:remove() end
......
-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore
= minetest, nodecore
-- LUALOCALS > ---------------------------------------------------------
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 obj
end
return false
end
local oldcheck = minetest.check_single_for_falling
function minetest.check_single_for_falling(pos, ...)
local node = minetest.get_node_or_nil(pos)
if not node then return end
if minetest.get_item_group(node.name, "falling_node") ~= 0 then
local bpos = {x = pos.x, y = pos.y - 1, z = pos.z}
if not nodecore.falling_collides(bpos, node.name, true) then
minetest.spawn_falling_node(pos)
minetest.remove_node(pos)
return true
end
return
end
if minetest.get_item_group(node.name, "attached_node") ~= 0 then
return oldcheck(pos, ...)
end
end
......@@ -47,8 +47,8 @@ function nodecore.falling_repose_check(pos)
-- 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
if not (sitdef and sitdef.groups and (sitdef.liquidtype ~= "none"
or sitdef.groups.falling_node)) then return end
local open = {}
local ok = check_empty(pos, 1, -repose, 0)
......
......@@ -24,7 +24,8 @@ nodecore.register_item_entity_on_settle(function(self, pos)
return true
end
if nodecore.buildable_to(p) and (rel.y <= 0
or nodecore.walkable({x = p.x, y = p.y - 1, z = p.z})) then
or nodecore.falling_collides({x = p.x, y = p.y - 1, z = p.z},
item:get_name(), true)) then
nodecore.place_stack(p, item)
self.itemstring = ""
self.object:remove()
......
......@@ -31,7 +31,8 @@ minetest.register_node(amalgam, {
crumbly = 2,
falling_repose = 3,
igniter = 1,
stack_as_node = 1
stack_as_node = 1,
density = 90
},
crush_damage = 2,
stack_max = 1,
......
......@@ -295,7 +295,7 @@ regliquid({
damage_per_second = 8,
on_punch = nodecore.node_punch_hurt,
drop = "",
groups = {igniter = 1, lava = 2, stack_as_node = 1},
groups = {igniter = 1, lava = 2, stack_as_node = 1, density = 100},
post_effect_color = {a = 191, r = 255, g = 64, b = 0},
sounds = nodecore.sounds("nc_terrain_bubbly")
})
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment