local hitbox = {
type = 'fixed';
fixed = {
-0.4, -0.5, -0.5;
0.4, 0.2, 0.5;
};
}
local kegcaption = function(m)
local liqid = m:get_string('liquid')
if liqid ~= '' then
local liq = sorcery.register.liquid.db[liqid]
if not liq then log.err('missing entry for liquid',liqid) return end
local measure = liq.measure or function(u)
return string.format('%s drams', u*63.9)
end
return {
title = string.format('Keg of %s', liq.name);
color = sorcery.lib.color(liq.color);
props = {
{title = 'Contains', desc = measure(m:get_int('charge'))};
}
};
else return { title = 'Empty Keg', props = {} } end
end
local log = sorcery.logger('keg')
minetest.register_node('sorcery:keg', {
description = 'Keg';
drawtype = 'mesh';
mesh = 'sorcery-keg.obj';
sunlight_propagates = true;
paramtype = 'light';
paramtype2 = 'facedir';
groups = { choppy = 2; sorcery_container = 2 }; -- 2=liquid
tiles = {
'default_bronze_block.png';
'default_wood.png';
'default_steel_block.png';
};
selection_box = hitbox;
collision_box = hitbox;
drop = {
-- preserve_metadata will not work without this!
max_items = 1;
items = {
{ items = { 'sorcery:keg' } };
};
};
preserve_metadata = function(pos,node,meta,drops)
if meta.liquid and meta.liquid ~= '' then
local m = drops[1]:get_meta()
m:from_table({fields = meta})
local cap = kegcaption(m)
m:set_string('description', sorcery.lib.ui.tooltip(cap))
m:set_string('short_description', cap.title)
end
end;
after_place_node = function(pos, placer, stack, tgt)
local meta = minetest.get_meta(pos)
local stackmeta = stack:get_meta()
meta:from_table(stackmeta:to_table())
end;
on_construct = function(pos)
local m = minetest.get_meta(pos)
m:set_string('infotext', 'Empty Keg')
end;
on_rightclick = function(pos, node, user, stack)
local m = minetest.get_meta(pos)
local update = function()
local c = kegcaption(m)
local str = c.title
for _,p in pairs(c.props) do
str = str .. string.format('\n(%s: %s)', p.title, p.desc)
end
m:set_string('infotext', str)
end
local noise = function(amt)
minetest.sound_play('default_water_footstep', {
gain = 0.5 + amt / 9.0;
pitch = 1.3 - amt / 12.0;
pos = pos;
}, true)
end
if stack:is_empty() then return end
local ctr = sorcery.itemclass.get(stack, 'container')
if (not ctr) or not ctr.hold == 'liquid' then return end
if ctr.has and
(m:get_string('liquid') == ctr.has or not m:contains('liquid')) then
if not ctr.empty then log.err(stack:get_name(), 'does not specify its empty counterpart container') return end
local add = ctr.charge * stack:get_count()
local chg = m:get_int('charge')
m:set_int('charge', chg + add)
m:set_string('liquid', ctr.has)
noise(chg + add)
local liq = sorcery.register.liquid.db[ctr.has]
if liq then
update()
log.act(string.format('%s added %u units of %s to a keg', user:get_player_name(), add, ctr.has))
else log.err('no liquid entry for',ctr.has) end
return ItemStack {
name = ctr.empty;
count = stack:get_count();
}
elseif not ctr.has and m:get_string('liquid') ~= '' then
local reg = sorcery.register.liquid.db[m:get_string('liquid')]
if not reg then log.err('missing definition for liquid', m:get_string('liquid')) return end
local filled = reg.containers[stack:get_name()]
if filled then
local fs = sorcery.itemclass.get(filled, 'container')
if not fs then log.err(filled,'is named as filled container but does not have the required itemclass definition') return end
local chg = fs.charge * stack:get_count()
local avail = m:get_int('charge')
if avail >= chg then
local liqid = m:get_string('liquid')
local liq = sorcery.register.liquid.db[liqid]
log.act(string.format('%s removed %u units of %s from a keg', user:get_player_name(), chg, liqid))
if avail == chg then
m:set_string('liquid','')
m:set_int('charge',0)
else m:set_int('charge', avail - chg) end
noise(chg)
update()
-- fancy visuals
local color = sorcery.lib.color(liq.color or {255,255,255})
local spritz = sorcery.lib.image('sorcery_droplet.png')
local drop = sorcery.lib.image('sorcery_drop.png')
spritz = spritz:blit(spritz:multiply(color))
drop = drop:blit (drop:multiply (color))
local facing = minetest.facedir_to_dir(minetest.get_node(pos).param2)
local noz = vector.add(pos, vector.rotate(
vector.new(0.0,0,-0.48),
vector.dir_to_rotation(facing)
))
local minnoz = vector.offset(noz, -0.03, -0.32, -0.03);
local maxnoz = vector.offset(noz, 0.03, -0.32, 0.03);
minetest.add_particlespawner {
amount = 15 * chg, time = 0.4*chg;
texture = spritz:render();
minpos = minnoz, maxpos = maxnoz;
minvel = vector.new(0,0,0);
maxvel = vector.new(0,-0.1,0);
minacc = vector.new(0,-0.1,0);
maxacc = vector.new(0,-0.13,0);
minsize = 0.4, maxsize = 1;
glow = 14; -- FIXME liquid glow prop
minexptime = 0.5, maxexptime = 0.5;
animation = {
type = 'sheet_2d';
frames_w = 14;
frames_h = 1;
frame_length = 0.5/14;
}
}
minetest.after(0.2, function()
minetest.add_particlespawner {
amount = math.random(5,11) * chg, time = 0.45 * chg;
texture = drop:render();
minpos = vector.offset(minnoz, 0,-0.05,0);
maxpos = vector.offset(maxnoz, 0,-0.05,0);
minvel = vector.new(0,-0.1,0);
maxvel = vector.new(0,-0.4,0);
minacc = vector.new(0,-0.15,0);
maxacc = vector.new(0,-0.18,0);
minsize = 0.3, maxsize = 0.5;
glow = 14; -- FIXME liquid glow prop
minexptime = 1, maxexptime = 1.5;
animation = {
type = 'sheet_2d';
frames_w = 10;
frames_h = 1;
frame_length = 1.5/10;
}
}
end)
return ItemStack {
name = filled;
count = stack:get_count();
}
end
end
end
end;
})