sorcery  vfx.lua at [669078947d]

File vfx.lua artifact e1c11d0a7c part of check-in 669078947d


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