sorcery  Artifact [f6fe98aba0]

Artifact f6fe98aba0655c6f8b59d047d7257c19d82a3fa9d890f2cbf3bd9a4adb2d753f:


local u = sorcery.lib
local flamebolt_pack, flamebolt_unpack = u.marshal.transcoder {
	age = u.marshal.t.u32;
	lastemit = u.marshal.t.u32;
}

minetest.register_entity('sorcery:spell_projectile_flamebolt',{
	initial_properties = {
		visual = "sprite";
        -- use_texture_alpha = true;
		textures = {'sorcery_fireball.png'};
		groups = {immortal = 1};
		visual_size = { x = 2, y = 2, z = 2 };
		physical = false;
		collide_with_objects = false;
		pointable = false;
		glow = 14;
		static_save = false;
	};
	on_step = function(self,dtime,collision)
		local pos = self.object:get_pos()
		if not self._meta then
			self._meta = { age = 0; lastemit = 0; emitters = {} }
			goto emit
		end

		self._meta.age = self._meta.age + dtime
		if self._meta.age >= 6 then
			goto destroy
		elseif (self._meta.age - self._meta.lastemit) < 3 then
			goto collcheck
		end
		
		::emit:: do
			self._meta.lastemit = self._meta.age
			local spawn = function(num, life_min, life_max, size_min, size_max, gl, speed, img)
				table.insert(self._meta.emitters, minetest.add_particlespawner {
					amount = num;
					minexptime = life_min;
					maxexptime = life_max;
					minvel = vector.multiply({ x = -1; y = -1; z = -1; }, speed);
					maxvel = vector.multiply({ x =  1; y =  1; z =  1; }, speed);
					minacc = vector.multiply({ x =  0; y = -1; z =  0; }, speed);
					maxacc = vector.multiply({ x =  0; y =  1; z =  0; }, speed);
					texture = img or u.image('sorcery_spark.png'):multiply(u.color(255,74,25):brighten(gl)):render();
					time = 3;
					glow = 14;
					minsize = size_min;
					maxsize = size_max;
					attached = self.object;
					animation = ((not img) and {
						type = "vertical_frames";
						aspect_w = 16;
						aspect_h = 16;
						length = life_max;
					}) or nil;
				})
			end
			--    #    life       size    glow speed
			spawn(50,   0.5,1,  10.0,15.0,  1.0,  1.0)
			spawn(80,   3.0,6,   5.0, 7.0,  1.7,  2.0)
			spawn(140,  1.0,7,   1.0, 6.0,  2.4,  3.0)
			spawn(250,  4.0,9,   0.3, 0.8,  3.0,  7.0)
			spawn(500,  10,20,   1.0, 1.8,  2.0,  0.2)
			spawn(500,  10,20,   0.5, 1.0,  3.0,  0.5)
		end

		::collcheck:: do
			-- if no collision then return end
			local nname = minetest.get_node(pos).name 
			if nname == 'air' then return
			elseif nname == 'ignore' then goto destroy end
			-- else fall through to explode
		end

		::explode:: do
			minetest.add_particle({
				pos = pos,
				velocity     = { x = 0, y = 0, z = 0 };
				acceleration = { x = 0, y = 0, z = 0 };
				expirationtime = 0.4,
				size = 50,
				collisiondetection = false,
				vertical = false,
				texture = "tnt_boom.png",
				glow = 14,
			})

			local boom = function(len,num,speed)
				minetest.add_particlespawner {
					amount = num;
					time = len;
					minpos = vector.subtract(pos, 1.2);
					maxpos = vector.add(pos, 1,2);
					minvel = vector.multiply({ x = -10; y = -10; z = -10; }, speed);
					maxvel = vector.multiply({ x =  10; y =  10; z =  10; }, speed);
					minacc = vector.multiply({ x =  -1; y =  -1; z =  -1; }, speed);
					maxacc = vector.multiply({ x =   1; y =   1; z =   1; }, speed);
					minexptime = 0.1;
					maxexptime = 0.3;
					minsize = 6;
					maxsize = 25;
					texture = 'tnt_smoke.png';
				}
			end
			boom(0.7, 140, 0.8)
			minetest.sound_play("tnt_explode", {pos = pos, gain = 1.5, max_hear_distance = 40}, true)
		end

		::destroy:: do
			if self._meta then for _,v in pairs(self._meta.emitters) do
				minetest.delete_particlespawner(v)
			end end
			self.object:remove()
		end
	end;
})