Index: mods/starlit-eco/plants.lua ================================================================== --- mods/starlit-eco/plants.lua +++ mods/starlit-eco/plants.lua @@ -124,14 +124,16 @@ drop = simpleDrop(2, 'starlit_eco:moondrop_petal'); }; berries = { desc = "The fruits of the moondrop are not very nutritious, but their peculiar sweet-sour flavor profile makes them one of Farthest Shadow's great delicacies"; color = lib.color(1,0,.4); - nourish = 10; - hydrate = 0.05; - taste = 1 * 60; mass = 1; + impact = starlit.type.impact { + nutrition = 10; + hydration = 0.05; + taste = 1*60; + }; }; decoration = { place_on = 'starlit:greengraze'; fill_ratio = 0.03; biomes = {'starlit:steppe', 'starlit:forest'}; Index: mods/starlit-eco/trees.lua ================================================================== --- mods/starlit-eco/trees.lua +++ mods/starlit-eco/trees.lua @@ -60,12 +60,14 @@ starlit.item.food.link('starlit_eco:lambent_pine_berry', { name = 'Lambent Pine Berry'; desc = 'Though packed with human-compatible nutrients, these berries are almost painfully sour when eaten raw.'; tex = lib.image('starlit-eco-plant-berry-bunch.png'):shift{hue=180,sat=-30,lum=30}:render(); - nourish = 150; - taste = -2 * 60; + impact = starlit.type.impact { + nutrition = 150; + taste = -2 * 60; + }; mass = 2; }) starlit.item.seed.link('starlit_eco:lambent_pine_seed', { name = 'Lambent Pine Seed'; Index: mods/starlit/interfaces.lua ================================================================== --- mods/starlit/interfaces.lua +++ mods/starlit/interfaces.lua @@ -88,25 +88,25 @@ for _, i in ipairs(l) do local bw = w/max if i.cfg then w = w - rh end table.insert(bar, { - kind = 'button', close = i.close; + kind = i.img and 'contact' or 'button', close = i.close; color = i.color; fg = i.fg; label = i.label; - icon = i.img; + img = i.img; id = i.id; w = bw, h = rh; }) if i.cfg then table.insert(bar, { kind = 'button'; color = i.color; fg = i.fg; label = "CFG"; - icon = i.img; + img = i.img; id = i.id .. '_cfg'; w = rh, h = rh; }) end @@ -355,11 +355,11 @@ local s = starlit.world.stats[id] local amt, sv = user:effectiveStat(id) local min, max = starlit.world.species.statRange(user.persona.species, user.persona.speciesVariant, id) local st = string.format('%s / %s', s.desc(amt, true), s.desc(max)) table.insert(tb, {kind = 'hztl', padding = 0.25; - {kind = 'label', w=2, h=barh, text = s.name}; + {kind = 'label', w=2, h=barh, text = lib.str.capitalize(s.name)}; {kind = 'hbar', w=4, h=barh, fac = sv, text = st, color=s.color}; }) end local abilities = { maneuver = {}; @@ -372,11 +372,11 @@ state.abilityMap[id] = a; table.insert(abilities[a.powerKind], { id = id; label = a.name; desc = a.desc; - img = a.img; +-- img = a.img; -- HACK color = pptrMatch(user.power.maneuver, {ref=a}) and {hue = 150, sat = 0, lum = .3} or nil; }); Index: mods/starlit/stats.lua ================================================================== --- mods/starlit/stats.lua +++ mods/starlit/stats.lua @@ -20,34 +20,157 @@ 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'}; + psi = {min = 0, max = 500, base = 0, desc = U('ψ', 10), color = C(320), name = 'numina'}; -- numina is measured in daψ - warmth = {min = -1000, max = 1000, base = 0, desc = U('°C', 10, true), color = C(5), name = 'Warmth'}; + 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', srzType = T.decimal}; + 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'}; + stamina = {min = 0, max = 10 * 20, base = true, desc = U('m', 100), color = C(88), name = 'stamina'}; -- stamina is measured in how many 10th-nodes (== cm) one can sprint - nutrition = {min = 0, max = 8000, base = 0, desc = U('kCal', 1, true), color = C(43,.5,.4), name = 'Nutrition', srzType = T.decimal}; + nutrition = {min = 0, max = 8000, base = 0, desc = U('kCal', 1, true), color = C(43,.5,.4), name = 'nutrition', srzType = T.decimal}; -- hunger is measured in kcalories one must consume to cure it. at 0, you start dying - hydration = {min = 0, max = 4, base = 0, desc = U('L', 1), color = C(217, .25,.4), name = 'Hydration', srzType = T.decimal}; + hydration = {min = 0, max = 4, base = 0, desc = U('L', 1), color = C(217, .25,.4), name = 'hydration', srzType = T.decimal}; -- thirst is measured in L of H²O required to cure it - morale = {min = 0, max = 10 * 24 * 60, base = true, desc = U('hr', 60, true), color = C(0,0,.8), name = 'Morale', srzType = T.decimal}; + morale = {min = 0, max = 10 * 24 * 60, base = true, color = C(0,0,.8), name = 'morale', srzType = T.decimal; + desc = function(amt, excU) return lib.math.timespec(amt) end}; -- morale is measured in minutes. e.g. at base rate morale degrades by -- 60 points every hour. morale can last up to 10 earthdays - irradiation = {min = 0, max = 10, base = 0, desc = U('Gy', 1), color = C(141,1,.5), name = 'Irradiation', srzType = T.decimal}; + irradiation = {min = 0, max = 10, base = 0, desc = U('Gy', 1), color = C(141,1,.5), name = 'irradiation', harm=true, srzType = T.decimal}; -- irrad is measured is milligreys -- 1Gy counters natural healing -- ~3Gy counters basic nanomedicine -- 5Gy causes death within two weeks without nanomedicine -- radiation speeds up psi regen -- morale drain doubles with each 2Gy - illness = {min = 0, max = 1, base = 0, desc = U('%', .01, true), color = C(71,.4,.25), name = 'Illness', srzType = T.factor}; + illness = {min = 0, max = 1, base = 0, desc = U('%', .01, true), color = C(71,.4,.25), name = 'illness', harm=true, srzType = T.factor}; -- as illness increases, maximum stamina and health gain a corresponding limit -- illness is increased by certain conditions, and decreases on its own as your -- body heals when those conditions wear off. some drugs can lower accumulated illness -- but illness-causing conditions require specific cures -- illness also causes thirst and fatigue to increase proportionately } + +starlit.world.statOrder = { + 'health', 'stamina', 'psi', 'warmth'; + + 'nutrition', 'hydration', 'irradiation'; + 'illness', 'morale', 'fatigue'; +} + +local impactStruct = G.struct { + base = G.array(8, G.struct {id = T.str, val = T.decimal}); +-- alt = G.array(8, ) +} + +starlit.type.impact = lib.class { + __name = 'starlit.type.impact'; + construct = function(p) + -- deltaPack { + -- nutrition = 5.0; + -- hydration = -1; + -- {"Taste", 'good'; {'morale', 1}}; + -- {"Narcotic", 'mixed'; {'morale', 10}; + -- {'addiction', function(user) ... end}}; + -- {"Magic", 'info'; 'casts an magic spell', function(user) ... end}; + -- } + return p + end; +-- __tostring = function(me) +-- end; + __index = { + pushProps = function(me, p) + for i,k in pairs(starlit.world.statOrder) do + if me[k] then + local s = starlit.world.stats[k] + + local v = me[k] + local good = v > 0 + if s.harm then good = not good end + local d = s.desc(v) + if v > 0 then d = '+' .. d end + + table.insert(p, { + title = lib.str.capitalize(s.name); + affinity = good and 'good' or 'bad'; + desc = d; + }) + end + end + for i,v in ipairs(me) do + local label, aff = v[1], v[2] + local effectStrs = {} + for i = 3, #v do + local t = v[i] + local str + if type(t) == 'table' then + local id, amt = t[1], t[2] + local s = starlit.world.stats[id] + local desc = s.desc(amt) + if amt > 0 then desc = '+' .. desc end + str = string.format('%s to %s', desc, s.name) + -- elseif type(v[i]) == 'function' then + elseif type(t) == 'string' then + str = t + end + if str then table.insert(effectStrs, str) end + end + + table.insert(p, { + title = lib.str.capitalize(label); + affinity = aff; + desc = next(effectStrs) and table.concat(effectStrs, ', ') or nil; + }) + end + end; + propTable = function(me) + local t = {} + me:pushProps(t) + return t + end; + addToItem = function(me, stack, key) + key = key or 'starlit:impact' + local m = stack:get_meta() + local tbl = {base={}} + for k,v in pairs(me) do + if type(k) == 'string' then + tbl.base[k] = v + end + end + local armored = lib.str.meta_armor(impactStruct.enc(tbl)) + m:set_string(key, armored) + return stack + end; + effective = function(me, stack, key) + key = key or 'starlit:impact' + local c = starlit.type.impact.clone(me) + + local m = stack:get_meta() + if m:contains(key) then + local tbl = impactStruct.dec(lib.str.meta_dearmor(m:get_string(key))) + for k,v in pairs(tbl.base) do c[k] = v end + end + + return c + end; + apply = function(me, user) + for k,v in pairs(me) do + if starlit.world.stats[k] then + user:statDelta(k, v) + elseif type(k) == 'number' then + for i = 3, #v do + local t = v[i] + if type(t) == 'table' then + local id, amt = t[1], t[2] + user:statDelta(id, amt) + elseif type(t) == 'function' then + t(user) + end + end + end + end + end; + }; +} Index: mods/vtlib/math.lua ================================================================== --- mods/vtlib/math.lua +++ mods/vtlib/math.lua @@ -136,14 +136,14 @@ function fn.timespec(n) if n == 0 then return '0s' end if n < 0 then return '-' .. fn.timespec(n*-1) end - local sec = n % 60 + local sec = math.floor(n % 60) local hr = math.floor(n / 60) local spec = {} - if sec ~= 0 then table.insert(spec, string.format("%ss", sec)) end if hr ~= 0 then table.insert(spec, string.format("%shr", hr)) end + if sec ~= 0 then table.insert(spec, string.format("%ss", sec)) end return table.concat(spec, ' ') end return fn