sorcery  Artifact [64c5633477]

Artifact 64c56334778af3bbf228accce6c4c7f40e830624e9b3c522215b7adcf393a88a:

  • File gravitator.lua — part of check-in [147592b8e9] at 2020-10-26 03:58:08 on branch trunk — add over-time spellcasting abstraction to enable metamagic and in particular disjunction, add more animations and sound effects, add excavation spell, possibly some others, forget when the last commit was, edit a bunch of magitech to make it subject to the disjunction mechanism (throw up a disjunction aura and waltz right through those force fields bby, wheee), also illumination spells, tweak runeforge and rune frequence to better the balance and also limit player frustration, move some math functions into their own library category, various tweaks and bugfixes, probably other shit i don't remember (user: lexi, size: 3753) [annotate] [blame] [check-ins using]

local modes = {
	off   = {next = 'stop';  power = 0};
	stop  = {next = 'slow';  power = 0.4; factor =  0;    color = {255,126,113}};
	slow  = {next = 'lift';  power = 0.2; factor =  0.5;  color = {255,255,100}};
	lift  = {next = 'crush'; power = 0.6; factor = -0.25; color = {113,255,126}};
	crush = {next = 'off';   power = 1;   factor =  2;    color = {113,126,255}};
}
for kind, p in pairs(modes) do
	local radius = 4
	local enoughpower = function(pos,mode)
		if mode and modes[mode] == nil then return false end
		local n = modes[mode or kind]
		local l = sorcery.ley.netcaps(pos,1,nil,n.power)
		local maxfree = l.self.powerdraw + l.freepower
		return maxfree >= n.power
	end
	local setmeta = function(pos,nextmode)
		local label = 'Gravitator'
		if nextmode ~= 'off' then
			label = label .. ' (' .. nextmode .. ')'
			minetest.get_node_timer(pos):start(4)
		end
		local meta = minetest.get_meta(pos)
		meta:set_string('infotext',label)
	end
	minetest.register_node('sorcery:gravitator_' .. kind, {
		description = 'Gravitator';
		drop = 'sorcery:gravitator_off';
		paramtype2 = 'facedir';
		groups = {
			cracky = 2;
			sorcery_magitech = 1;
			sorcery_ley_device = 1;
			not_in_creative_inventory = kind == 'off' and nil or 1;
			effect_trigger = (kind == 'off') and nil or 1;
		};
		tiles = {
			'sorcery_gravitator_side.png';
			'sorcery_gravitator_side.png';
			'sorcery_gravitator_side.png';
			'sorcery_gravitator_side.png';
			'sorcery_gravitator_side.png';
			'sorcery_gravitator_panel_'..kind..'.png';
		};
		effect_near = p.factor and {
			impacts = {
				gravity = p.factor;
			};
			distance = radius;
			spread = 1.5;
		} or nil;
		_sorcery = {
			ley = {
				mode = 'consume', affinity = {'counterpraxic'};
				power = p.power;
			};
			on_leychange = function(pos)
				local meta = minetest.get_meta(pos)
				if kind ~= 'off' then
					if not enoughpower(pos) then
						local old = minetest.get_node(pos)
						old.name = 'sorcery:gravitator_off'
						minetest.swap_node(pos,old)
						meta:set_string('lastmode',kind)
						setmeta(pos,'off')
					end
				elseif meta:contains('lastmode') then
					local nm = meta:get_string('lastmode')
					if enoughpower(pos,nm) then
						local old = minetest.get_node(pos)
						old.name = 'sorcery:gravitator_' .. nm
						minetest.set_node(pos,old)
						setmeta(pos,nm)
					end
				end
			end;
		};
		on_construct = function(pos)
			setmeta(pos,'off')
		end;
		on_timer = function(pos)
			if p.color == nil then return false end

			local probe = sorcery.spell.probe(pos)
			if probe.disjunction then return true end

			local vee = {x=0,y=-1,z=0}
			minetest.add_particlespawner {
				amount = 128;
				time = 4;
				minpos = vector.subtract(pos,radius);
				maxpos = vector.add(pos,radius);
				minvel = vector.multiply(vee, p.factor*0.5);
				maxvel = vector.multiply(vee, p.factor);
				minexptime = 1;
				maxexptime = 1.3;
				minsize = 0.2, maxsize = 1.4;
				glow = 12;
				texture = sorcery.lib.image('sorcery_spark.png'):multiply(sorcery.lib.color(p.color)):render();
				animation = {
					type = 'vertical_frames';
					aspect_w = 16, aspect_h = 16;
					length = 1.4;
				}
			}
			return true;
		end;
		on_rightclick = function(pos)
			minetest.sound_play('doors_steel_door_open', {
				gain = 0.6;
				pos = pos;
			}, true)
			
			local nextmode = p.next
			while true do
				local nm = modes[nextmode]
				if nm.power == 0 then break end
				if nm.power <= p.power then break end
				if enoughpower(pos,nextmode) then break end
				nextmode = nm.next
			end

			local old = minetest.get_node(pos)
			minetest.set_node(pos, {
				name = 'sorcery:gravitator_' .. nextmode;
				param1 = old.param1;
				param2 = old.param2;
			})

			setmeta(pos,nextmode)
		end;
	})
end