sorcery.vfx = {}
local L = sorcery.lib
sorcery.vfx.glowspark = function(color)
local spark = L.image('sorcery_spark.png')
return spark:blit(spark:multiply(color))
end
sorcery.vfx.cast_sparkle = function(caster,color,strength,duration,pos)
local ofs = pos
and function(x) return vector.add(pos,x) end
or function(x) return x end
local height = caster:get_properties().eye_height
minetest.add_particlespawner {
amount = 70 * strength;
time = duration or 1.5;
attached = caster;
-- texture = L.image('sorcery_spark.png'):multiply(color):render();
texture = sorcery.vfx.glowspark(color):render();
minpos = ofs({ x = 0.0, z = 0.6, y = height*0.7});
maxpos = ofs({ x = 0.4, z = 0.2, y = height*1.1});
minvel = { x = -0.5, z = -0.5, y = -0.5};
maxvel = { x = 0.5, z = 0.5, y = 0.5};
minacc = { x = 0.0, z = 0.0, y = 0.5};
maxacc = { x = 0.0, z = 0.0, y = 0.5};
minsize = 0.4, maxsize = 0.8;
minexptime = 1, maxexptime = 1;
glow = 14;
animation = {
type = 'vertical_frames';
aspect_w = 16;
aspect_h = 16;
length = 1.1;
};
}
end
sorcery.vfx.body_sparkle = function(body,color,str,pos)
local tex = L.image('sorcery_spark.png')
local pi = tex:blit(tex:multiply(color)):render()
local ofs = pos
and function(x) return vector.add(pos,x) end
or function(x) return x end
return minetest.add_particlespawner {
amount = 25 * str;
time = 0.5;
attached = body;
minpos = ofs{x = -0.5, y = -0.5, z = -0.5};
maxpos = ofs{x = 0.5, y = 1.5, z = 0.5};
minacc = {x = -0.3, y = 0.0, z = 0.3};
maxacc = {x = -0.3, y = 0.0, z = 0.3};
minvel = {x = -0.6, y = -0.2, z = 0.6};
maxvel = {x = -0.6, y = 0.2, z = 0.6};
minexptime = 1.0;
maxexptime = 1.5;
texture = pi;
glow = 14;
animation = {
type = 'vertical_frames';
aspect_w = 16, aspect_h = 16;
length = 1.6;
};
}
end
sorcery.vfx.enchantment_sparkle = function(tgt,color)
local minvel, maxvel
if minetest.get_node(vector.add(tgt.under,{y=1,z=0,x=0})).name == 'air' then
minvel = {x=0,z=0,y= 0.3} maxvel = {x=0,z=0,y= 1.5};
else
local dir = vector.subtract(tgt.above,tgt.under)
minvel = vector.multiply(dir, 0.3)
maxvel = vector.multiply(dir, 1.2)
end
return minetest.add_particlespawner {
amount = 50;
time = 0.5;
minpos = vector.subtract(tgt.under, 0.5);
maxpos = vector.add(tgt.under, 0.5);
minvel = minvel, maxvel = maxvel;
minexptime = 1, maxexptime = 2;
minsize = 0.5, maxsize = 2;
texture = L.image('sorcery_spark.png'):multiply(color):render();
animation = {
type = 'vertical_frames';
aspect_w = 16, aspect_h = 16;
length = 2;
};
glow = 14;
}
end
sorcery.vfx.bloodburst = function(pos,size)
for i=0, size or 48 do
minetest.add_particle{
texture = 'sorcery_blood_' .. math.random(5) .. '.png',
size = 7,
expirationtime = 2 + math.random(),
glow = 1,
pos = pos,
velocity = {
x = (math.random() * 3.0) - 1.5,
y = math.random(),
z = (math.random() * 3.0) - 1.5
},
acceleration = {
x = 0,
y = -1,
z = 0
}
}
end
end
-- target can be an entity or a pos vector
sorcery.vfx.imbue = function(color, target, strength, height)
local tpos if target.get_pos then
tpos = target:get_pos()
if target.get_properties then
height = height or ((target:get_properties().eye_height or 1)*1.3)
end
else
tpos = vector.offset(target, 0,0.5,0)
end
height = height or 1
local scenter = vector.add(tpos, {x=0,y=height/2,z=0})
for i=1,math.random(24*(strength or 1),32*(strength or 1)) do
local high = (height+0.8)*math.random() - 0.8
local far = (high >= -0.5 and high <= height) and
(math.random() * 0.3 + 0.4) or
(math.random() * 0.5)
local yaw = {x=0, y = math.random()*(2*math.pi), z=0}
local po = vector.rotate({x=far,y=high,z=0}, yaw)
local ppos = vector.add(po,tpos)
local dir = vector.direction(ppos,scenter)
local vel = math.random() * 0.8 + 0.4
local col if type(color) == 'function'
then col = color(i, {high = high, far = far, dir = dir, vel = vel, pos = po})
else col = color
end
local et = math.floor((far/vel)*10)*.1
minetest.add_particle {
pos = ppos;
velocity = vector.multiply(dir,vel);
expirationtime = 0.4;
size = math.random()*2.4 + 0.6;
texture = L.image('sorcery_sputter.png'):glow(col):render();
glow = 14;
animation = {
type = 'vertical_frames', length = 0.4;
aspect_w = 16, aspect_h = 16
};
}
end
end
function sorcery.vfx.drip(liquid, noz, amt, time, exp)
if type(liquid) == 'string' then liquid = sorcery.register.liquid.db[liquid] end
local minnoz = vector.offset(noz, -0.03, 0.0, -0.03);
local maxnoz = vector.offset(noz, 0.03, 0.0, 0.03);
local drop = L.image('sorcery_drop.png'):multiply(L.color(liquid.color))
return minetest.add_particlespawner {
amount = amt, time = time;
texture = drop:render();
minpos = minnoz, maxpos = maxnoz;
minvel = vector.new(0,0,0);
maxvel = vector.new(0,-0.2,0);
minacc = vector.new(0,-0.2,0);
maxacc = vector.new(0,-0.23,0);
minsize = 0.4, maxsize = 1;
glow = liquid.glow or 2;
minexptime = exp, maxexptime = exp;
animation = {
type = 'sheet_2d';
frames_w = 10;
frames_h = 1;
frame_length = (exp/10) + 0.01;
};
vertical = true;
}
end