-- [ʞ] sw.lua
-- ~ lexi hale <lexi@hale.su>
-- 🄯 EUPL v1.2
-- ?
-------------------------------
-- basic suit nano abilities --
-------------------------------
local function shredder(prop)
local function fabToItemsAndCharges(fab)
local elt
if fab then
elt = fab:elementalize()
else
elt = {}
end
local items,charges = {},{}
if elt.element then
for k,v in pairs(elt.element) do
local forms = starlit.world.material.element.db[k].form
if forms.brick then
local st = ItemStack {
name = forms.brick;
count = math.floor(v);
}
table.insert(items, st)
else -- gas, liquid
table.insert(charges, {id = k, mass = v})
end
end
end
return items, charges
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
if minetest.is_protected(what, user.entity:get_player_name()) then return end
local node = minetest.get_node(what)
local nd = minetest.registered_nodes[node.name]
local elt, fab, vary
if nd._starlit then
fab = nd._starlit.recover or nd._starlit.fab
vary = nd._starlit.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('starlit-nano-shred', {
object = user.entity;
max_hear_distance = prop.range*2;
loop = true;
pitch = soundPitch;
})
user.action.fx.shred = starlit.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
minetest.remove_node(what)
minetest.check_for_falling(what)
--print('shred complete')
user:suitSound 'starlit-success'
if fab then
local vf = fab
if vary then
local rng = (starlit.world.seedbank+0xa891f62)[minetest.hash_node_position(what)]
vf = vf + vary(rng, {})
end
local items, charges = fabToItemsAndCharges(vf)
for i, it in ipairs(items) do user:give(it) end
-- TODO give gasses, liquids
end
cleanup()
end
elseif ctx.how.state == 'halt' then
cleanup()
end
return true
end
end
starlit.item.sw.link('starlit_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=3, powerDraw=200};
})
starlit.item.sw.link('starlit_electronics:compile_commune', {
name = 'Compile Matter';
kind = 'suitPower', powerKind = 'direct';
desc = "A basic suit matter compiler program. It's rather slow, but it's been ruthlessly optimized for size- and memory-efficiency by some of the Commune's most fanatic coders, to the point where every Commune nanosuit can come with the program preinstalled.";
size = 700e3;
cost = {
cycles = 4e9;
ram = .3e9;
};
ui = 'starlit:compile-matter-component';
run = function(user, ctx)
end;
})
starlit.item.sw.link('starlit_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 = 8e9;
ram = 1e9;
};
ui = 'starlit:compile-matter-block';
run = function(user, ctx)
end;
})
starlit.item.sw.link('starlit_electronics:compile_imperial', {
name = 'Genesis Deluxe';
kind = 'suitPower', powerKind = 'direct';
desc = "House Bascundir has long dominated the matter compiler market in the Crystal Sea. Their firmware is excessively complex due to mountains of specialized edge-case handling, but the end result is certainly speedier than the competitors'.";
size = 2e4;
cost = {
cycles = 100e6;
ram = 1.5e9;
};
ui = 'starlit:compile-matter-component';
run = function(user, ctx)
end;
})
do local J = starlit.store.compilerJob
starlit.item.sw.link('starlit_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 = 'starlit: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 = starlit.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 = starlit.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))
starlit.fx.nano.heal(user, {{player=user.entity}}, heal, 1)
return true
end
end
return false -- program did not run
end;
end
starlit.item.sw.link('starlit_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);
})
starlit.item.sw.link('starlit_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);
})