starlit  Artifact [3b2a0cfbed]

Artifact 3b2a0cfbedff3d691bbe935f49b65625e4d499cae90d7df7910578a8c2242ab0:


-- [ʞ] sw.lua
--  ~ lexi hale <lexi@hale.su>
--  🄯 EUPL v1.2
--  ? 

-------------------------------
-- basic suit nano abilities --
-------------------------------
local function shredder(prop)
	local function getItemsForFab(fab)
		local elt
		if fab then
			elt = fab:elementalize()
		else
			elt = {}
		end
		local items = {}
		if elt.element then
			for k,v in pairs(elt.element) do
				local st = ItemStack {
					name = starsoul.world.material.element.db[k].form.element;
					count = v;
				}
				table.insert(items, st)
			end
		end
		return items
	end

	return function(user, ctx)
		local function cleanup()
			user.action.prog.shred = nil
			if user.action.sfx.shred then
				minetest.sound_fade(user.action.sfx.shred, 1, 0)
				user.action.sfx.shred = nil
			end
			if user.action.fx.shred then
				user.action.fx.shred.abort()
			end
		end

		if user.action.tgt.type ~= 'node' then return end
		local what = user.action.tgt.under
		if what == nil or user.entity:get_pos():distance(what) > prop.range then
			cleanup()
			return false
		end
		local shredTime = 1.0
		local soundPitch = 1.0 -- TODO
		local pdraw = prop.powerDraw or 0

		local node = minetest.get_node(what)
		local nd = minetest.registered_nodes[node.name]
		local elt, fab, vary
		if nd._starsoul then
			fab = nd._starsoul.recover or nd._starsoul.fab
			vary = nd._starsoul.recover_vary
		end
		if fab then
			if fab.flag then
				if fab.flag.unshreddable then
					cleanup()
					return false
					-- TODO error beep
				end
			end
			shredTime = fab.time and fab.time.shred or shredTime -- FIXME
			if fab.cost and fab.cost.shredPower then
				pdraw = pdraw * fab.cost.shredPower
			end
		end
		local maxW = user:getSuit():maxPowerUse()
		if maxW < pdraw then
			shredTime = shredTime * (pdraw/maxW)
			pdraw = maxW
		end
		if ctx.how.state == 'prog' then
			local pdx = pdraw * ctx.how.delta
			local p = user:suitDrawCurrent(pdx, ctx.how.delta, {kind='nano',label='Shredder'}, pdx)
			if p < pdx then
				cleanup()
				return false
			elseif not user.action.prog.shred then
				cleanup() -- kill danglers
				-- begin
				user.action.prog.shred = 0
				user.action.sfx.shred = minetest.sound_play('starsoul-nano-shred', {
					object = user.entity;
					max_hear_distance = prop.range*2;
					loop = true;
					pitch = soundPitch;
				})
				user.action.fx.shred = starsoul.fx.nano.shred(user, what, prop, shredTime, node)
			else
				user.action.prog.shred = user.action.prog.shred + ctx.how.delta or 0
			end
			--print('shred progress: ', user.action.prog.shred)
			if user.action.prog.shred >= shredTime then
				if minetest.dig_node(what) then
					--print('shred complete')
					user:suitSound 'starsoul-success'
					if fab then
						local vf = fab
						if vary then
							local rng = (starsoul.world.seedbank+0xa891f62)[minetest.hash_node_position(what)]
							vf = vf + vary(rng, {})
						end
						local items = getItemsForFab(vf)
						for i, it in ipairs(items) do user:give(it) end
					end
				else
					user:suitSound 'starsoul-error'
				end
				cleanup()
			end
		elseif ctx.how.state == 'halt' then
			cleanup()
		end
		return true
	end
end

starsoul.item.sw.link('starsoul_electronics:shred', {
	name = 'NanoShred';
	kind = 'suitPower', powerKind = 'active';
	desc = 'An open-source program used in its various forks and iterations all across human-inhabited space and beyond. Rumored to contain fragments of code stolen from the nanoware of the Greater Races by an elusive infoterrorist.';
	size = 500e3;
	cost = {
		cycles = 100e6;
		ram = 500e6;
	};
	run = shredder{range=2, powerDraw=200};
})

starsoul.item.sw.link('starsoul_electronics:compile_commune', {
	name = 'Compile Matter';
	kind = 'suitPower', powerKind = 'direct';
	desc = "A basic suit matter compiler program, rather slow but ruthlessly optimized for power- and memory-efficiency by some of the Commune's most fanatic coders.";
	size = 700e3;
	cost = {
		cycles = 300e6;
		ram = 2e9;
	};
	ui = 'starsoul:compile-matter-component';
	run = function(user, ctx)
	end;
})

starsoul.item.sw.link('starsoul_electronics:compile_block_commune', {
	name = 'Compile Block';
	kind = 'suitPower', powerKind = 'active';
	desc = "An advanced suit matter compiler program, capable of printing complete devices and structure parts directly into the world.";
	size = 5e6;
	cost = {
		cycles = 700e6;
		ram = 4e9;
	};
	ui = 'starsoul:compile-matter-block';
	run = function(user, ctx)
	end;
})

do local J = starsoul.store.compilerJob
	starsoul.item.sw.link('starsoul_electronics:driver_compiler_commune', {
		name = 'Matter Compiler';
		kind = 'driver';
		desc = "A driver for a standalone matter compiler, suitable for building larger components than your suit alone can handle.";
		size = 850e3;
		cost = {
			cycles = 400e6;
			ram = 2e9;
		};
		ui = 'starsoul:device-compile-matter-component';
		run = function(user, ctx)
		end;
		bgProc = function(user, ctx, interval, runState)
			if runState.flags.compiled == true then return false end
			-- only so many nanides to go around
			runState.flags.compiled = true
			local time = minetest.get_gametime()
			local cyclesLeft = ctx.comp.cycles * interval

			for id, e in ipairs(ctx.file.body.conf) do
				if e.key == 'job' then
					local t = J.dec(e.value)
					local remove = false
					local r = starsoul.item.sw.db[t.schematic]
					if not r then -- bad schematic
						remove = true
					else
						local ccost = ctx.sw.cost.cycles + r.cost.cycles
						local tcost = ccost / cyclesLeft
						t.progress = t.progress + (1/tcost)*interval
						cyclesLeft = cyclesLeft - ccost*interval
						if t.progress >= 1 then
							-- complete
							remove = true
							local i = starsoul.item.mk(r.output, {
								how = 'print';
								user = user; -- for suit
								compiler = {
									node = ctx.compiler; -- for device
									sw = ctx.sw;
									install = ctx.fd;
								};
								schematic = r;
							})
							ctx.giveItem(i)
						end
					end
					if remove then
						table.remove(ctx.file.body.conf, id)
					else
						e.value = J.enc(t)
					end
					if not cyclesLeft > 0 then break end
				end
			end
			ctx.saveConf()
		end;
	})
end

local function pasv_heal(effect, energy, lvl, pgmId)
	return function(user, ctx, interval, runState)
		if runState.flags.healed == true then return false end
		-- competing nanosurgical programs?? VERY bad idea
		runState.flags.healed = true

		local amt, f = user:effectiveStat 'health'
		local st = user:getSuit():powerState()
		if (st == 'on' and f < lvl) or (st == 'powerSave' and f < math.min(lvl,0.25)) then
			local maxPower = energy*interval
			local p = user:suitDrawCurrent(maxPower, interval, {
				id = 'heal';
				src = 'suitPower';
				pgmId = pgmId;
				healAmount = effect;
			})
			if p > 0 then
				local heal = (p/maxPower) * ctx.speed * effect*interval
				--user:statDelta('health', math.max(1, heal))
				starsoul.fx.nano.heal(user, {{player=user.entity}}, heal, 1)
				return true
			end
		end
		return false -- program did not run
	end;
end

starsoul.item.sw.link('starsoul_electronics:nanomed', {
	name = 'NanoMed';
	kind = 'suitPower', powerKind = 'passive';
	desc = 'Repair of the body is a Commune specialty, and their environment suits all come equipped with highly sophisticated nanomedicine suites, able to repair even the most grievous of wounds given sufficient energy input and time.';
	size = 2e9;
	cost = {
		cycles = 400e6;
		ram = 3e9;
	};
	run = pasv_heal(2, 20, 1);
})

starsoul.item.sw.link('starsoul_electronics:autodoc_deluxe', {
	name = 'AutoDoc Deluxe';
	kind = 'suitPower', powerKind = 'passive';
	desc = "A flagship offering of the Excellence Unyielding nanoware division, AutoDoc Deluxe has been the top-rated nanocare package in the Celestial Shores Province for six centuries and counting. Every chip includes our comprehensive database of illnesses, prosyn schematics, and organ repair techniques, with free over-the-ether updates guaranteed for ten solariads from date of purchase! When professional medical care just isn't an option, 9/10 doctors recommend Excellence Unyielding AutoDoc Deluxe! The remaining doctor was bribed by our competitors.";
	size = 1e9;
	cost = {
		cycles = 700e6;
		ram = 1e9;
	};
	run = pasv_heal(4, 50, .7);
})