Index: mods/starlit-electronics/init.lua
==================================================================
--- mods/starlit-electronics/init.lua
+++ mods/starlit-electronics/init.lua
@@ -41,11 +41,11 @@
--
starlit.item.chip = lib.registry.mk 'starlit_electronics:chip'
-- software is of one of the following types:
-- schematic: program for your matter compiler that enables crafting a given item.
--- output: the result
+-- output (convertible to ItemStack): the result
-- driver: inserted into a Core to control attached hardware
-- suitPower: provides suit functionality like nanoshredding or healing
-- passive powers are iterated on suit application/configuration and upon fst-tick
-- cost: what the software needs to run. some fields are fab-specific
-- energy: for fab, total energy cost of process in joules
@@ -216,17 +216,17 @@
title = def.name;
desc = def.desc;
color = lib.color(0,.2,1);
props = {
{ title = 'Optimal Capacity', affinity = 'info';
- desc = lib.math.si('J', def.capacity) };
+ desc = lib.math.siUI('J', def.capacity) };
{ title = 'Discharge Rate', affinity = 'info';
- desc = lib.math.si('W', def.dischargeRate) };
+ desc = lib.math.siUI('W', def.dischargeRate) };
{ title = 'Charge Efficiency', affinity = 'info';
desc = string.format('%s%%', (1-def.leak) * 100) };
{ title = 'Size', affinity = 'info';
- desc = lib.math.si('m', def.fab.size.print) };
+ desc = lib.math.siUI('m', def.fab.size.print) };
};
};
_starlit = {
event = {
create = function(st, how)
@@ -276,20 +276,20 @@
local batteryTiers = {
makeshift = {
name = 'Makeshift'; capacity = .5, decay = 3, leak = 2, dischargeRate = 1,
fab = starlit.type.fab {
- metal = {copper=10};
+ element = {copper=10};
};
desc = "Every attosecond this electrical abomination doesn't explode in your face is but the unearned grace of the Wild Gods.";
complexity = 1;
sw = {rarity = 1};
};
imperial = {
name = 'Imperial'; capacity = 2, decay = 2, leak = 2, dischargeRate = 2;
fab = starlit.type.fab {
- metal = {copper=15, iron = 20};
+ element = {copper=15, iron = 20};
size = { print = 0.1 };
};
desc = "The Empire's native technology is a lumbering titan: bulky, inefficient, unreliable, ugly, and awesomely powerful. Their batteries are no exception, with raw capacity and throughput that exceed even Usukinwya designs.";
drm = 1;
complexity = 2;
@@ -296,21 +296,23 @@
sw = {rarity = 2};
};
commune = {
name = 'Commune'; capacity = 1, decay = .5, leak = .2, dischargeRate = 1;
fab = starlit.type.fab {
- metal = {vanadium=50, steel=10};
+ element = {vanadium = 50};
+ metal = {steel=10};
size = { print = 0.05 };
};
desc = "The Commune's proprietary battery designs prioritize reliability, compactness, and maintenance concerns above raw throughput, with an elegance of engineering and design that would make a Su'ikuri cry.";
complexity = 5;
sw = {rarity = 3};
};
usukwinya = {
name = 'Usukwinya'; capacity = 2, decay = 1, leak = 1, dischargeRate = 1.5,
fab = starlit.type.fab {
- metal = {vanadium=30, argon=10};
+ element = {argon=10};
+ metal = {vanadium=30};
size = { print = 0.07 };
};
desc = "A race of consummate value engineers, the Usukwinya have spent thousands of years refining their tech to be as cheap to build as possible, without compromising much on quality. The Tradebirds drive an infamously hard bargain, but their batteries are more than worth their meagre cost.";
drm = 2;
sw = {rarity = 10};
@@ -317,21 +319,23 @@
complexity = 15;
};
eluthrai = {
name = 'Eluthrai'; capacity = 3, decay = .4, leak = .1, dischargeRate = 1.5,
fab = starlit.type.fab {
- metal = {beryllium=20, platinum=20, technetium = 1, cinderstone = 10 };
+ element = {beryllium=20, platinum=20, technetium = 1};
+ metal = {cinderstone = 10};
size = { print = 0.03 };
};
desc = "The uncompromising Eluthrai are never satisfied until every quantifiable characteristic of their tech is maximally optimised down to the picoscale. Their batteries are some of the best in the Reach, and unquestionably the most expensive -- especially for those lesser races trying to copy the designs without the benefit of the sublime autofabricator ecosystem of the Eluthrai themselves.";
complexity = 200;
sw = {rarity = 0}; -- you think you're gonna buy eluthran schematics on SuperDiscountNanoWare.space??
};
firstborn = {
name = 'Firstborn'; capacity = 5, decay = 0.1, leak = 0, dischargeRate = 3;
fab = starlit.type.fab {
- metal = {neodymium=20, xenon=150, technetium=5, sunsteel = 10 };
+ element = {neodymium=20, xenon=150, technetium=5};
+ metal = {sunsteel = 10};
crystal = {astrite = 1};
size = { print = 0.05 };
};
desc = "Firstborn engineering seamlessly merges psionic effects with a mastery of the physical universe unattained by even the greatest of the living Starsouls. Their batteries reach levels of performance that strongly imply Quantum Gravity Theory -- and several major holy books -- need to be rewritten. From the ground up.";
complexity = 1000;
@@ -369,12 +373,11 @@
};
chemical = {
name = 'Chemical';
desc = '';
fab = starlit.type.fab {
- element = { lithium = 3};
- metal = {iron = 5};
+ element = { lithium = 3 };
size = {print=1.0};
};
sw = {
cost = {
cycles = 1e9; -- 1 bil cycles
@@ -411,14 +414,12 @@
name = 'Hybrid';
desc = '';
capacity = 1;
fab = starlit.type.fab {
element = {
- lithium = 3;
- };
- metal = {
- iron = 5;
+ lithium = 10;
+ carbon = 20;
};
size = {print=1.5};
};
sw = {
cost = {
@@ -502,10 +503,11 @@
end
starlit.item.sw.link(swID, {
kind = 'schematic';
name = name .. ' Schematic';
+ input = fab;
output = id;
size = bType.sw.pgmSize;
cost = bType.sw.cost;
rarity = rare;
})
@@ -688,19 +690,19 @@
end
def = assert(def._starlit.chip)
end
local props = {
{title = 'Clock Rate', affinity = 'info';
- desc = lib.math.si('Hz', def.clockRate)};
+ desc = lib.math.siUI('Hz', def.clockRate)};
{title = 'RAM', affinity = 'info';
- desc = lib.math.si('B', def.ram)};
+ desc = lib.math.siUI('B', def.ram)};
}
if not defOnly then
table.insert(props, {
title = 'Free Storage', affinity = 'info';
- desc = lib.math.si('B', E.chip.freeSpace(ch, data)) .. ' / '
- .. lib.math.si('B', def.flash);
+ desc = lib.math.siUI('B', E.chip.freeSpace(ch, data)) .. ' / '
+ .. lib.math.siUI('B', def.flash);
})
local swAffMap = {
schematic = 'schematic';
suitPower = 'ability';
driver = 'driver';
@@ -732,11 +734,11 @@
})
end
else
table.insert(props, {
title = 'Flash Storage', affinity = 'info';
- desc = lib.math.si('B', def.flash);
+ desc = lib.math.siUI('B', def.flash);
})
end
return starlit.ui.tooltip {
title = data.label and data.label~='' and string.format('<%s>', data.label) or def.name;
color = lib.color(.6,.6,.6);
@@ -784,11 +786,11 @@
name = t.name;
clockRate = t.clockRate;
flash = t.flash;
ram = t.ram;
powerEfficiency = t.powerEfficiency; -- cycles per joule
- fab = {
+ fab = starlit.type.fab {
flag = {
silicompile = true;
};
time = {
silicompile = t.size * 24*60;
@@ -868,11 +870,12 @@
return E.chip.fileOpen(self.chip, self.inode, fn)
end;
};
}
-function E.chip.usableSoftware(chips,pgm)
+function E.chip.usableSoftware(chips,pgm,pred)
+ pred = pred or function() return true end
local comp = E.chip.sumCompute(chips)
local r = {}
local unusable = {}
local sw if pgm then
if type(pgm) == 'string' then
@@ -897,11 +900,11 @@
end
end
end
for _, s in pairs(sw) do
- if s.sw.cost.ram <= comp.ram then
+ if s.sw.cost.ram <= comp.ram and pred(s) then
table.insert(r, {
sw = s.sw;
chip = s.chip, chipSlot = s.chipSlot;
file = s.file;
fd = E.chip.fileHandle(s.chip, s.inode);
Index: mods/starlit-electronics/mod.conf
==================================================================
--- mods/starlit-electronics/mod.conf
+++ mods/starlit-electronics/mod.conf
@@ -1,4 +1,4 @@
name = starlit_electronics
title = starlit electronics
description = basic electronic components and logic
-depends = starlit
+depends = starlit, starlit_material
Index: mods/starlit-electronics/sw.lua
==================================================================
--- mods/starlit-electronics/sw.lua
+++ mods/starlit-electronics/sw.lua
@@ -101,10 +101,11 @@
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
Index: mods/starlit-material/elements.lua
==================================================================
--- mods/starlit-material/elements.lua
+++ mods/starlit-material/elements.lua
@@ -25,10 +25,15 @@
silicon = {
name = 'silicon', sym = 'Si', n = 14, density = 2.329;
metal = true; -- can be forged into an ingot
color = lib.color(.6,.6,.4);
};
+ neodymium = {
+ name = 'neodymium', sym = 'Nd', n= 60, density = 7.01;
+ metal = true;
+ color = lib.color(1,1,1);
+ };
potassium = {
name = 'potassium', sym = 'K', n = 19, density = 0.862;
-- potassium is technically a metal but it's so soft
-- it can be easily nanoworked without high temps, so
-- ingots make no sense
Index: mods/starlit-material/init.lua
==================================================================
--- mods/starlit-material/init.lua
+++ mods/starlit-material/init.lua
@@ -20,6 +20,7 @@
starlit.mod.material = M
starlit.include 'elements'
starlit.include 'liquids'
+starlit.include 'metals'
ADDED mods/starlit-material/liquids.lua
Index: mods/starlit-material/liquids.lua
==================================================================
--- mods/starlit-material/liquids.lua
+++ mods/starlit-material/liquids.lua
@@ -0,0 +1,14 @@
+local lib = starlit.mod.lib
+local M = starlit.mod.material
+
+starlit.world.material.liquid.meld {
+ water = {
+ name = 'water';
+ composition = starlit.type.fab {
+ element = {hydrogen = 2.0, oxygen = 1.0};
+ };
+ density = 1.0;
+ desc = "the sine qua non of biological life";
+ color = lib.color(.1,.2,1);
+ };
+}
ADDED mods/starlit-material/metals.lua
Index: mods/starlit-material/metals.lua
==================================================================
--- mods/starlit-material/metals.lua
+++ mods/starlit-material/metals.lua
@@ -0,0 +1,14 @@
+local lib = starlit.mod.lib
+local M = starlit.mod.material
+
+starlit.world.material.metal.meld {
+ steel = {
+ name = 'steel';
+ composition = starlit.type.fab {
+ element = {iron = 2.0, carbon = 1.0};
+ };
+ density = 1.0;
+ desc = "steel is a widely used alloy of iron and carbon";
+ color = lib.color(.4,.4,.4);
+ };
+}
Index: mods/starlit/element.lua
==================================================================
--- mods/starlit/element.lua
+++ mods/starlit/element.lua
@@ -164,11 +164,11 @@
material = {
kind = 'metal';
metal = id;
};
fab = starlit.type.fab {
- flag = {smelt= true};
+ flag = {smelt=true};
element = comp(1e3);
};
};
});
Index: mods/starlit/fab.lua
==================================================================
--- mods/starlit/fab.lua
+++ mods/starlit/fab.lua
@@ -10,11 +10,11 @@
-- fabspecs.
--
-- * used for determining quantities. that is,
-- f*x = spec to make x instances of f
--
--- new fab fields must be defined in starlit.type.fab.opClass.
+-- new fab fields must be defined in starlit.type.fab.fields.
-- this maps a name to fn(a,b,n) -> quant, where a is the first
-- argument, b is a compounding amount, and n is a quantity of
-- items to produce. fields that are unnamed will be underwritten
local function fQuant(a,b,n) return ((a or 0)+(b or 0))*n end
@@ -28,72 +28,93 @@
return f*n
end
local function fReq (a,b,n) return a or b end
local function fFlag (a,b,n) return a and b end
local function fSize (a,b,n) return math.max(a,b) end
-local opClass = {
+
+local F = string.format
+local lib = starlit.mod.lib
+
+local fields = {
-- fabrication eligibility will be determined by which kinds
-- of input a particular fabricator can introduce. e.g. a
-- printer with a but no cache can only print items whose
-- recipe only names elements as ingredients
-
- -- ingredients
- element = fQuant; -- (g)
- gas = fQuant; -- ()
- liquid = fQuant; -- (l)
- crystal = fQuant; -- (g)
- item = fQuant; -- n
- metal = fQuant; -- (g)
- metalIngot = fQuant; -- (g)
+ element = {
+ name = {"element", "elements"};
+ string = function(x, n, long)
+ local el = starlit.world.material.element.db[x]
+ return lib.math.si('g', n) .. ' ' .. ((not long and el.sym) or el.name)
+ end;
+ image = function(x, n)
+ return string.format('starlit-element-%s.png', x)
+ end;
+ op = fQuant;
+ };
+ metal ={
+ name = {"metal", "metals"};
+ string = function(x, n)
+ local met = starlit.world.material.metal.db[x]
+ return lib.math.si('g', n) .. ' ' .. met.name
+ end;
+ image = function(x, n)
+ local met = starlit.world.material.metal.db[x]
+ return ItemStack(met.form.ingot):get_definition().inventory_image
+ end;
+ op = fQuant;
+ };
+ liquid = {
+ name = {"liquid", "liquids"};
+ string = function(x, n)
+ local liq = starlit.world.material.liquid.db[x]
+ return lib.math.si('L', n) .. ' ' .. liq.name
+ end;
+ op = fQuant;
+ };
+ gas = {
+ name = {"gas", "gasses"};
+ string = function(x, n)
+ local gas = starlit.world.material.gas.db[x]
+ return lib.math.si('g', n) .. ' ' .. gas.name
+ end;
+ op = fQuant;
+ };
+-- crystal = {
+-- op = fQuant;
+-- };
+ item = {
+ name = {"item", "items"};
+ string = function(x, n)
+ local i = minetest.registered_items[x]
+ return tostring(n) .. 'x ' .. i.short_description
+ end;
+ };
+
-- factors
- cost = fFac; -- units vary
- time = fFac; -- (s)
+
+ cost = {op=fFac}; -- units vary
+ time = {op=fFac}; -- (s)
-- print: base printing time
- size = fSize;
+ size = {op=fSize};
-- printBay: size of the printer bay necessary to produce the item
- req = fReq;
- flag = fFlag; -- means that can be used to produce the item & misc flags
+ req = {op=fReq};
+ flag = {op=fFlag}; -- means that can be used to produce the item & misc flags
-- print: allow production with a printer
-- smelt: allow production with a smelter
-- all else defaults to underwrite
}
-local F = string.format
-local strClass = {
- element = function(x, n)
- local el = starlit.world.material.element[x]
- return lib.math.si('g', n) .. ' ' .. (el.sym or el.name)
- end;
- metal = function(x, n)
- local met = starlit.world.material.metal[x]
- return lib.math.si('g', n) .. ' ' .. met.name
- end;
- liquid = function(x, n)
- local liq = starlit.world.material.liquid[x]
- return lib.math.si('L', n) .. ' ' .. liq.name
- end;
- gas = function(x, n)
- local gas = starlit.world.material.gas[x]
- return lib.math.si('g', n) .. ' ' .. gas.name
- end;
- item = function(x, n)
- local i = minetest.registered_items[x]
- return tostring(n) .. 'x ' .. i.short_description
- end;
-}
-
local order = {
'element', 'metal', 'liquid', 'gas', 'item'
}
local lib = starlit.mod.lib
local fab fab = lib.class {
__name = 'starlit:fab';
- opClass = opClass;
- strClass = strClass;
+ fields = fields;
order = order;
construct = function(q) return q end;
__index = {
elementalize = function(self)
local e = fab {element = self.element or {}}
@@ -156,26 +177,54 @@
if f then table.insert(fml, f) end
fml = table.concat(fml, ' + ')
return fml, ts
end;
+
+ visualize = function(self)
+ local all = {}
+ for i,o in ipairs(order) do
+ local t = {}
+ if self[o] then
+ for mat,amt in pairs(self[o]) do
+ local v = {}
+ v.id = mat
+ v.n = amt
+ if fields[o].string then
+ v.label = fields[o].string(mat,amt,true)
+ end
+ if fields[o].image then
+ v.img = fields[o].image(mat,amt)
+ end
+ table.insert(t,v)
+ end
+ end
+ if fields[o].sort then
+ table.sort(t, function(a,b) return fields[o].sort(a.id, b.id) end)
+ end
+ if next(t) then table.insert(all, {
+ id=o, list=t;
+ header=fields[o].name[t[2] and 2 or 1];
+ }) end
+ end
+ return all
+ end;
};
__tostring = function(self)
local t = {}
for i,o in ipairs(order) do
- if self[o] then
+ if self[o] and fields[o].string then
for mat,amt in pairs(self[o]) do
if amt > 0 then
- table.insert(t, strClass[o](mat, amt))
+ table.insert(t, fields[o].string(mat, amt))
end
end
end
end
return table.concat(t, ", ")
end;
-
__add = function(a,b)
local new = fab {}
for cat, vals in pairs(a) do
new[cat] = lib.tbl.copy(vals)
@@ -182,11 +231,11 @@
end
for cat, vals in pairs(b) do
if not new[cat] then
new[cat] = lib.tbl.copy(vals)
else
- local f = opClass[cat]
+ local f = fields[cat].op
for k,v in pairs(vals) do
local n = f(new[cat][k], v, 1)
new[cat][k] = n > 0 and n or nil
end
end
@@ -196,11 +245,11 @@
__mul = function(x,n)
local new = fab {}
for cat, vals in pairs(x) do
new[cat] = {}
- local f = opClass[cat]
+ local f = fields[cat].op
for k,v in pairs(vals) do
local num = f(v,nil,n)
new[cat][k] = num > 0 and num or nil
end
end
ADDED mods/starlit/food.lua
Index: mods/starlit/food.lua
==================================================================
--- mods/starlit/food.lua
+++ mods/starlit/food.lua
@@ -0,0 +1,79 @@
+local F = starlit.item.food
+local lib = starlit.mod.lib
+
+function F.impact(stack,f)
+ if stack and not f then f = stack:get_definition()._starlit.food end
+ local impact = f.impact and starlit.type.impact.clone(f.impact) or starlit.type.impact{}
+
+ if impact.taste then
+ local aff = impact.taste > 0 and 'good' or 'bad'
+ table.insert(impact, {'taste', aff, {'morale', impact.taste}})
+ end
+
+ if stack then
+ impact = impact:effective(stack)
+ end
+
+ return impact
+end
+
+local function foodTip(stack, f)
+ local impact = F.impact(stack,f)
+ local props = impact:propTable()
+
+ if f.mass then
+ table.insert(props, {
+ title='Mass', affinity='info';
+ desc = lib.math.si('g', f.mass, nil, nil, 2);
+ })
+ end
+
+ return starlit.ui.tooltip {
+ title = f.name;
+ desc = f.desc;
+ props = props;
+ color = f.color;
+ };
+end
+
+F.foreach('starlit:gen-food', {}, function(id, f)
+ minetest.register_item(id, {
+ type = f.itemType or 'none';
+ inventory_image = f.tex;
+ short_description = f.name;
+ description = foodTip(nil, f);
+ on_use = function(st, luser)
+ local user = starlit.activeUsers[luser:get_player_name()]
+ st:take_item(1)
+ local imp = F.impact(st,f)
+ imp:apply(user)
+ user:suitSound 'starlit-success' -- FIXME need proper eating sound
+ return st
+ end;
+ _starlit = {
+ food = f;
+ recover = f.recover;
+ mass = f.mass;
+ };
+ })
+end)
+
+starlit.item.seed.foreach('starlit:gen-seed', {}, function(id, s)
+ minetest.register_item(id, {
+ type = 'none';
+ inventory_image = s.tex;
+ short_description = s.name;
+ description = starlit.ui.tooltip {
+ title = s.name;
+ color = s.color;
+ desc = s.desc;
+ };
+ on_place = function()
+ -- FIXME sow
+ end;
+ _starlit = {
+ seed = s;
+ mass = s.mass;
+ };
+ })
+end)
Index: mods/starlit/interfaces.lua
==================================================================
--- mods/starlit/interfaces.lua
+++ mods/starlit/interfaces.lua
@@ -120,11 +120,11 @@
local function abilityMenu(a)
-- select primary/secondary abilities or activate ritual abilities
local p = {kind = 'vert'}
for _, o in ipairs(a.order) do
local m = a.menu[o]
- table.insert(p, {kind='label', text=m.label, w=a.w, h = .5})
+ table.insert(p, {kind='hbar', fac=0.5, text=string.format("%s",m.label), w=a.w, h = .5})
table.insert(p, wrapMenu(a.w, a.h, 1.2, 2, m.opts))
end
return p
end
@@ -461,23 +461,211 @@
end;
};
};
})
+-- TODO destroy suit interfaces when power runs out or suit/chip is otherwise disabled
starlit.interface.install(starlit.type.ui {
id = 'starlit:compile-matter-component';
+ sub = {
+ suit = function(state, user, evt)
+ if evt.kind == 'disrobe' then state:close()
+ elseif evt.kind == 'power' and evt.mode == 'off' then state:close() end
+ end;
+ playerInventory = function(state,user)
+ -- refresh
+ end;
+ };
pages = {
index = {
setupState = function(state, user, ctx)
- if ctx.context == 'suit' then
- end
state.pgm = ctx.program
+ state.select = {}
+ local E = starlit.mod.electronics
+ if ctx.context == 'suit' then
+ state.fetch = function()
+ local cst = user.entity:get_inventory():get_list 'starlit_suit_chips'
+ local cl = {order={}, map={}}
+ for i, c in ipairs(cst) do
+ if not c:is_empty() then
+ local d = E.chip.read(c)
+ local co = {
+ stack = c;
+ data = d;
+ }
+ table.insert(cl.order, co)
+ cl.map[d.uuid] = co
+ end
+ end
+ if state.select.chip and not cl.map[state.select.chip.data.uuid] then
+ -- chip no longer available
+ user:suitSound 'starlit-error'
+ state.select = {}
+ end
+ state.select.chips = cl
+
+ state.select.scms = {}
+ if state.select.chip then
+ state.select.scms = E.chip.usableSoftware({state.select.chip.stack},nil,
+ function(s) return s.sw.kind == 'schematic' end)
+ end
+ end
+ end
+ end;
+
+ onClose = function(state, user)
+ user:suitSound 'starlit-quit'
+ end;
+ handle = function(state, user, q)
+ local sel = state.select
+ state.fetch()
+ local chips = state.select.chips
+ local function chirp()
+ user:suitSound 'starlit-nav'
+ end
+ local function onPickChip(chip)
+ chirp()
+ sel.chip = chip
+ return true
+ end
+ local function onPickScm(scm)
+ chirp()
+ sel.scm = scm
+ return true
+ end
+
+ if sel.chip == nil then
+ for k in next, q do
+ local id = k:match "^chip_(%d+)$"
+ if id then
+ local cm = chips.map[tonumber(id)]
+ if cm then return onPickChip(cm) end
+ end
+ end
+ elseif sel.scm == nil then
+ if q.back then chirp() sel.chip = nil return true end
+ for k in next, q do
+ local id = k:match "^scm_(%d+)$"
+ if id then
+ local cm = state.select.scms[tonumber(id)]
+ if cm then return onPickScm(cm) end
+ end
+ end
+ else
+ if q.back then chirp() sel.scm = nil return true end
+ end
end;
+
render = function(state, user)
+ local sel, pgmSelector = state.select, {}
+ state.fetch()
+
+ local function pushSelector(id, item, label, desc, req)
+ local rh = .5
+ local label = {kind = 'text', w = 10-1.5, h=1.5;
+ text = ''..label }
+ if req then
+ label.h = label.h - rh - .2
+
+ local imgs = {}
+ for ci,c in ipairs(req) do
+ for ei, e in ipairs(c.list) do
+ table.insert(imgs, {kind = 'img', w=rh, h=rh, img=e.img})
+ end
+ end
+ label = {kind = 'vert', w = 10-1.5, h=1.5;
+ label;
+ {kind ='hztl', w=10-1.5, h=rh; unpack(imgs); }
+ }
+ end
+ table.insert(pgmSelector, {kind = 'hztl', w=10,h=1.5;
+ {kind = 'contact', id=id, w=1.5, h=1.5;
+ item = item;
+ color = {hue=220, sat=0, lum=0};
+ desc = desc;
+ };
+ label;
+ })
+ end
+
+ local back = {kind = 'button', id='back', label = '<- Back', w=10,h=1.2}
+ if sel.chips == nil then
+ table.insert(pgmSelector, {kind = 'img', img = 'starlit-ui-alert.png', w=2, h=2})
+ elseif sel.chip == nil then
+ for i, c in ipairs(sel.chips.order) do
+ -- TODO filter out chips without schematics?
+ pushSelector('chip_' .. c.data.uuid, c.stack, c.data.label)
+ end
+ else
+ if sel.scm == nil then
+ for idx, ent in ipairs(sel.scms) do
+ local fab = ItemStack(ent.sw.output):get_definition()._starlit.fab
+ if fab.flag.print then
+ local req = fab:visualize()
+ pushSelector('scm_' .. idx, ent.sw.output, ent.sw.name, nil, req)
+ end
+ end
+ table.insert(pgmSelector, back)
+ else
+ local output = ItemStack(sel.scm.sw.output):get_definition()
+ local fab = output._starlit.fab
+ local sw = sel.scm.sw
+ table.insert(pgmSelector, {kind = 'hztl', w=10, h=1.2;
+ {kind = 'img', item = sw.output, w=1.2, h=1.2, desc=output.description};
+ {kind = 'text', text = string.format('%s', sw.name), w=10-1.2,h=1.2};
+ })
+ local inputTbl = {kind = 'vert', w=5,h=0;
+ {kind = 'hbar', w=5, h=.5, text='Input'}};
+ local costTbl = {kind = 'vert', w=5,h=0; spacing=.25;
+ {kind = 'hbar', w=5, h=.5, text='Process'}};
+ local reqPane = {kind = 'pane', id='reqPane', w=10, h=7;
+ {kind = 'hztl', w=10,h=0; inputTbl, costTbl}
+ }
+ local req = fab:visualize()
+ for ci,c in ipairs(req) do
+ table.insert(inputTbl, {kind = 'label', w=4.5, h=1, x=.5;
+ text=lib.str.capitalize(c.header)});
+ for ei,e in ipairs(c.list) do
+ table.insert(inputTbl, {kind = 'hztl', w=4, h=.5, x=1;
+ {kind='img', w=.5,h=.5, img=e.img};
+ {kind='label', w=3.3,h=.5,x=.2, text=e.label};
+ });
+ end
+ end
+ if sw.cost then
+ local function pushCost(t, val)
+ table.insert(costTbl, {kind='text', w=4.5,h=.5,x=.5;
+ text=string.format('%s: %s',t,val);
+ })
+ end
+ if sw.cost.cycles then
+ pushCost('Energy', lib.math.siUI('J', sel.scm.powerCost))
+ pushCost('Compute', lib.math.siUI({'cycle','cycles'}, sw.cost.cycles, true))
+ end
+ end
+ table.insert(pgmSelector, reqPane)
+ table.insert(pgmSelector, {kind = 'hztl', w=10,h=1.2;
+ {kind = 'button', id='back', label = '<- Back', w=5,h=1.2};
+ {kind = 'button', id='print', label = 'Print ->', w=5,h=1.2, color={hue=120,sat=0,lum=0}};
+ })
+ end
+ end
+
return starlit.ui.build {
- kind = 'vert', padding = 0.5; w = 5, h = 5, mode = 'sw';
- {kind = 'label', w = 4, h = 1, text = 'hello'};
+ kind = 'hztl', padding = 0.5; w = 20, h = 10, mode = 'sw';
+ {kind = 'vert', w = 5, h = 5;
+ {kind = 'hbar', fac=0, w = 5, h = .5, text = 'Recent Prints'};
+ };
+ {kind = 'vert', w = 10, h = 10;
+ {kind = 'hbar', fac=0, w = 10, h = .5, text = 'Program Select'};
+ {kind = 'pane', w = 10, h = 9.5, id='pgmSelect';
+ unpack(pgmSelector)
+ };
+ };
+ {kind = 'vert', w = 5, h = 10;
+ {kind = 'hbar', fac=0, w = 5, h = .5, text = 'Print Queue'};
+ };
}
end;
};
};
})
Index: mods/starlit/species.lua
==================================================================
--- mods/starlit/species.lua
+++ mods/starlit/species.lua
@@ -107,11 +107,11 @@
metabolism = .150; -- kCal/s
painTolerance = 0.4;
dehydration = 10e-4; -- L/s
speed = 1.1;
staminaRegen = 10.0;
- psiRegen = 1.3;
+ psiRegen = 0.05; -- ψ/s
psiPower = 1.2;
};
};
male = {
name = 'Human Male';
@@ -128,11 +128,11 @@
lungCapacity = 1.0;
sturdiness = 0.3;
metabolism = .150; -- kCal/s
dehydration = 15e-4; -- L/s
speed = 1.0;
- psiRegen = 1.0;
+ psiRegen = 0.025;
psiPower = 1.0;
};
};
};
traits = {};
Index: mods/starlit/stats.lua
==================================================================
--- mods/starlit/stats.lua
+++ mods/starlit/stats.lua
@@ -20,12 +20,12 @@
local function C(h, s, l)
return lib.color {hue = h, sat = s or 1, lum = l or .7}
end
starlit.world.stats = {
- psi = {min = 0, max = 500, base = 0, desc = U('ψ', 10), color = C(320), name = 'numina'};
- -- numina is measured in daψ
+ psi = {min = 0, max = 500, base = 0, desc = U('ψ', 1), color = C(320), name = 'numina', srzType = T.decimal};
+ -- numina is measured in ψ
warmth = {min = -1000, max = 1000, base = 0, desc = U('°C', 10, true), color = C(5), name = 'warmth'};
-- warmth in measured in d°C
fatigue = {min = 0, max = 76 * 60, base = 0, desc = U('hr', 60, true), color = C(288,.3,.5), name = 'fatigue', harm=true, srzType = T.decimal};
-- fatigue is measured in minutes one needs to sleep to cure it
stamina = {min = 0, max = 10 * 20, base = true, desc = U('m', 100), color = C(88), name = 'stamina'};
Index: mods/starlit/ui.lua
==================================================================
--- mods/starlit/ui.lua
+++ mods/starlit/ui.lua
@@ -31,10 +31,12 @@
if not state then
state = {
page = page or 'index';
form = self.id;
+ self = self;
+ close = function() self:close(user) end;
}
starlit.activeUI[user.name] = state
self:cb('setupState', user, ...)
elseif page ~= nil and state.page ~= page then
state.page = page
@@ -150,10 +152,29 @@
state.x=state.x + state.spacing + st.w
state.h = math.max(state.h, st.h)
end
state.h = state.h + state.padding
state.w = state.x + state.padding/2
+ elseif def.kind == 'pane' then
+ widget('scroll_container[%s,%s;%s,%s;%s;vertical]',
+ state.x, state.y, state.w, state.h,
+ def.id)
+ local y = 0
+ for _, w in ipairs(def) do
+ local src, st = starlit.ui.build(w, state)
+ widget('container[%s,%s]%scontainer_end[]', 0, y, src)
+ y=y + state.spacing + st.h
+ state.w = math.max(state.w, st.w)
+ end
+ widget('scroll_container_end[]')
+ if y > state.h then
+ widget('scrollbar[%s,%s;%s,%s;vertical;%s;]',
+ state.x, state.y, .5, state.h,
+ def.id)
+ end
+ state.w = state.w + state.padding
+ state.h = state.h + state.padding/2
elseif def.kind == 'list' then
local slotTypes = {
plain = {hue = 200, sat = -.1, lum = 0};
element = {hue = 20, sat = -.3, lum = 0};
chip = {hue = 0, sat = -1, lum = 0};
@@ -183,14 +204,24 @@
local sm = 1
state.w = def.w * sm + (spac * (def.w - 1))
state.h = def.h * sm + (spac * (def.h - 1))
elseif def.kind == 'contact' then
if def.color then table.insert(lines, btnColorDef(def.id)) end
- widget('image_button%s[%s,%s;%s,%s;%s;%s;%s]',
+ local img = def.img
+ local desc
+ if def.item then
+ img = ItemStack(def.item):get_name()
+ desc = ItemStack(def.item):get_description()
+ end
+ widget('%simage_button%s[%s,%s;%s,%s;%s;%s;%s]',
+ def.item and 'item_' or '',
def.close and '_exit' or '',
state.x, state.y, def.w, def.h,
- E(def.img), E(def.id), E(def.label or ''))
+ E(img), E(def.id), E(def.label or ''))
+ if desc and not def.desc then
+ widget('tooltip[%s;%s]', E(def.id), E(desc))
+ end
elseif def.kind == 'button' then
if def.color then table.insert(lines, btnColorDef(def.id)) end
local label = E(def.label or '')
if state.fg then label = lib.color(state.fg):fmt(label) end
widget('button%s[%s,%s;%s,%s;%s;%s]',
@@ -212,11 +243,11 @@
state.x, state.y, def.w, def.h, E(def.id), E(def.text))
elseif def.kind == 'hbar' or def.kind == 'vbar' then -- TODO fancy image bars
local cl = lib.color(state.color)
local fg = state.fg or cl:readable(.8,1)
local wfac, hfac = 1,1
- local clamp = math.min(math.max(def.fac, 0), 1)
+ local clamp = math.min(math.max(def.fac or 0, 0), 1)
if def.kind == 'hbar'
then wfac = wfac * clamp
else hfac = hfac * clamp
end
local x,y, w,h = state.x, state.y, def.w, def.h
@@ -230,12 +261,17 @@
string.format('%s', fg:hex(), E(def.text)))
end
end
if def.desc then
- widget('tooltip[%s,%s;%s,%s;%s]',
- state.x, state.y, def.w, def.h, E(def.desc))
+ local coord
+ if def.id then
+ coord = E(def.id)
+ else
+ coord = string.format("%s,%s;%s,%s", state.x, state.y, def.w, def.h)
+ end
+ widget('tooltip[%s;%s;#000000;#ffffff]', coord, E(def.desc))
end
local originX = (parent and parent.x or 0)
local originY = (parent and parent.y or 0)
local l = table.concat(lines)
Index: mods/vtlib/math.lua
==================================================================
--- mods/vtlib/math.lua
+++ mods/vtlib/math.lua
@@ -40,39 +40,52 @@
{6, 'M', 'mega', true, 'μ', 'micro', true};
{3, 'k', 'kilo', true, 'm', 'milli', true};
{2, 'h', 'hecto', false, 'c', 'centi', true};
{1, 'da','deca', false, 'd', 'deci', false};
}
+
+ local function unitForAmt(n)
+ if type(unit)=='table' then
+ if n == 1
+ then return unit[1]
+ else return unit[2]
+ end
+ end
+ return unit
+ end
+
for i, s in ipairs(scales) do
local amt, smaj, pmaj, cmaj,
smin, pmin, cmin = lib.tbl.unpack(s)
+
if math.abs(val) > 1 then
if uncommonScales or cmaj then
local denom = 10^amt
local vd = val/denom
if prec then vd = lib.math.trim(vd, prec) end
if math.abs(val) >= (10^(amt)) then
return string.format("%s%s%s",
- vd, (full and (' ' .. pmaj) or smaj), unit)
+ vd, (full and (' ' .. pmaj) or smaj), unitForAmt(vd))
end
end
elseif math.abs(val) < 1 then
if uncommonScales or cmin then
local denom = 10^-amt
local vd = val/denom
if prec then vd = lib.math.trim(vd, prec) end
if math.abs(val) <= (10^-(amt-1)) then
return string.format("%s%s%s",
- vd, (full and (' ' .. pmin) or smin), unit)
+ vd, (full and (' ' .. pmin) or smin), unitForAmt(vd))
end
end
end
end
- return string.format("%s%s", val, unit)
+ return string.format("%s%s", val, unitForAmt(val))
end
+function fn.siUI(u,v,f,us,...) return fn.si(u,v,f,us,2,...) end
function fn.lerp(t, a, b) return (1-t)*a + t*b end
function fn.gradient(grad, pos)
local n = #grad
if n == 1 then return grad[1] end
ADDED src/sfx/alarm-urgent.csd
Index: src/sfx/alarm-urgent.csd
==================================================================
--- src/sfx/alarm-urgent.csd
+++ src/sfx/alarm-urgent.csd
@@ -0,0 +1,21 @@
+; [ʞ] alarm-urgent.csd
+; ~ lexi hale
+; 🄯 CC-NC-BY-SA 3.0
+; ? VERY angry blarp fer when the bad is done to ya
+
+
+
+
+#include "dqual.inc"
+#include "digital.orc"
+
+
+
+i"chirp" 0.00 0.20 0.20 30 1700
+i"chirp" 0.20 0.40 0.20 5 1000
+i"blare" 0.10 0.40 0.8
+i"blarp" 0.40 0.70 0.6
+e 0.9
+
+
+
ADDED src/sfx/alarm.csd
Index: src/sfx/alarm.csd
==================================================================
--- src/sfx/alarm.csd
+++ src/sfx/alarm.csd
@@ -0,0 +1,19 @@
+; [ʞ] alarm.csd
+; ~ lexi hale
+; 🄯 CC-NC-BY-SA 3.0
+; ? angry blarp fer when the bad is done to ya
+
+
+
+
+#include "dqual.inc"
+#include "digital.orc"
+
+
+
+i"chirp" 0.00 0.40 0.20 5 1000
+i"blarp" 0.20 0.70 0.6
+e 0.9
+
+
+
ADDED src/sfx/quit.csd
Index: src/sfx/quit.csd
==================================================================
--- src/sfx/quit.csd
+++ src/sfx/quit.csd
@@ -0,0 +1,19 @@
+; [ʞ] quit.csd
+; ~ lexi hale
+; 🄯 CC-NC-BY-SA 3.0
+; ? choopy chorp for when ya log the off
+
+
+
+
+#include "dqual.inc"
+#include "digital.orc"
+
+
+
+i"chirp" 0.00 0.10 0.10 20 4000
+i"chirp" 0.15 0.20 0.10 20 2000
+e 0.3
+
+
+