sorcery  entities.lua at [9ef6cbcf31]

File entities.lua artifact f6fe98aba0 part of check-in 9ef6cbcf31


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;
})