Overview
Comment: | add primitive thermal hazard LEDs; further documentation |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
511814aace3b6e9dd57ec362b2f17c70 |
User & Date: | lexi on 2024-05-03 21:00:04 |
Other Links: | manifest | tags |
Context
2024-05-04
| ||
02:18 | fix colors, add grass check-in: 9d4ddb7701 user: lexi tags: trunk | |
2024-05-03
| ||
21:00 | add primitive thermal hazard LEDs; further documentation check-in: 511814aace user: lexi tags: trunk | |
15:31 | genericize impacts check-in: 467a75e0dc user: lexi tags: trunk | |
Changes
Modified mods/starlit/init.lua from [435c654ad9] to [d6e7e6c59c].
28 28 brightest = 14; -- only sun and growlights 29 29 }; 30 30 heat = { -- celsius 31 31 freezing = 0; 32 32 safe = 4; 33 33 overheat = 32; 34 34 boiling = 100; 35 + thermalConductivity = 0.05; -- κ 35 36 }; 36 37 rad = { 37 38 }; 38 39 }; 39 40 40 41 activeUsers = { 41 42 -- map of username -> user object
Modified mods/starlit/user.lua from [788077fd8e] to [7074af2318].
37 37 end 38 38 return { 39 39 entity = luser; 40 40 name = name; 41 41 hud = { 42 42 elt = {}; 43 43 bar = {}; 44 + alarm = {}; 44 45 }; 45 46 tree = {}; 46 47 action = { 47 48 bits = 0; -- for control deltas 48 49 prog = {}; -- for recording action progress on a node; reset on refocus 49 50 tgt = {type='nothing'}; 50 51 sfx = {}; ................................................................................ 59 60 }; 60 61 pref = { 61 62 calendar = 'commune'; 62 63 }; 63 64 overlays = {}; 64 65 cooldownTimes = { 65 66 stamina = 0; 67 + alarm = 0; 66 68 }; 67 69 } 68 70 end; 69 71 __index = { 70 72 -------------- 71 73 -- overlays -- 72 74 -------------- ................................................................................ 188 190 end; 189 191 190 192 --------- 191 193 -- HUD -- 192 194 --------- 193 195 attachImage = function(self, def) 194 196 local user = self.entity 195 - local img = {} 197 + local img = {def = def} 196 198 img.id = user:hud_add { 197 199 type = 'image'; 198 200 text = def.tex; 199 201 scale = def.scale; 200 202 alignment = def.align; 201 203 position = def.pos; 202 204 offset = def.ofs; ................................................................................ 209 211 end, def) 210 212 end 211 213 end 212 214 return img 213 215 end; 214 216 attachMeter = function(self, def) 215 217 local luser = self.entity 216 - local m = {} 218 + local m = {def = def} 217 219 local w = def.size or 80 218 220 local szf = w / 80 219 221 local h = szf * 260 220 222 m.meter = luser:hud_add { 221 223 type = 'image'; 222 224 scale = {x = szf, y = szf}; 223 225 alignment = def.align; ................................................................................ 263 265 luser:hud_change(m.readout, 'number', txtcolor:hex()) 264 266 end 265 267 end 266 268 return m 267 269 end; 268 270 attachTextBox = function(self, def) 269 271 local luser = self.entity 270 - local box = {} 272 + local box = {def = def} 271 273 box.id = luser:hud_add { 272 274 type = 'text'; 273 275 text = ''; 274 276 alignment = def.align; 275 277 number = def.color and def.color:int24() or 0xFFffFF; 276 278 scale = def.bound; 277 279 size = {x = def.size, y=0}; ................................................................................ 286 288 luser:hud_change(box.id, 'number', color:int24()) 287 289 end 288 290 end 289 291 return box 290 292 end; 291 293 attachStatBar = function(self, def) 292 294 local luser = self.entity 293 - local bar = {} 295 + local bar = {def = def} 294 296 local img = lib.image 'starlit-ui-bar.png' 295 297 local colorized = img 296 298 if type(def.color) ~= 'function' then 297 299 colorized = colorized:shift(def.color) 298 300 end 299 301 300 302 bar.id = luser:hud_add { ................................................................................ 446 448 set('text', hudAdjustBacklight(hudCenterBG):render()) 447 449 end; 448 450 }; 449 451 self:updateHUD() 450 452 end; 451 453 deleteHUD = function(self) 452 454 for name, e in pairs(self.hud.elt) do 453 - self:hud_delete(e.id) 455 + self.entity:hud_remove(e.id) 454 456 end 455 457 end; 456 458 updateHUD = function(self) 457 459 for name, e in pairs(self.hud.elt) do 458 460 if e.update then e.update() end 459 461 end 460 462 end; ................................................................................ 499 501 -- intel-gathering -- 500 502 --------------------- 501 503 clientInfo = function(self) 502 504 return minetest.get_player_information(self.name) 503 505 end; 504 506 species = function(self) 505 507 return starlit.world.species.index[self.persona.species] 508 + end; 509 + -- can the suit heater sustain its current internal temperature in an area of t°C 510 + tempCanSustain = function(self, t) 511 + if self:naked() then return false end 512 + local s = self:getSuit() 513 + if s:powerState() == 'off' then return false end 514 + local sd = s:def() 515 + local w = self:effectiveStat 'warmth' 516 + local kappa = starlit.constant.heat.thermalConductivity 517 + local insul = sd.temp.insulation 518 + local dt = (kappa * (1-insul)) * (t - w) 519 + print('dt', dt, dump(sd.temp)) 520 + if (dt > 0 and dt > sd.temp.maxCool) 521 + or (dt < 0 and math.abs(dt) > sd.temp.maxHeat) then return false end 522 + return true 523 + end; 524 + -- will exposure to temperature t cause the player eventual harm 525 + tempHazard = function(self, t) 526 + local tr = self:species().tempRange.survivable 527 + if t >= tr[1] and t <= tr[2] then return nil end 528 + if self:tempCanSustain(t) then return nil end 529 + 530 + if t < tr[1] then return 'cold' end 531 + return 'hot' 506 532 end; 507 533 508 534 -------------------- 509 535 -- event handlers -- 510 536 -------------------- 511 537 onSignup = function(self) 512 538 local meta = self.entity:get_meta() ................................................................................ 872 898 end 873 899 if run then 874 900 run(self, ctx) 875 901 return true 876 902 end 877 903 return false 878 904 end; 905 + 906 + alarm = function(self, urgency, kind, freq, where) 907 + freq = freq or 3 908 + local urgencies = { 909 + [1] = {sound = 'starlit-alarm'}; 910 + [2] = {sound = 'starlit-alarm-urgent'}; 911 + } 912 + local gt = minetest.get_gametime() 913 + local urg = urgencies[urgency] or urgencies[#urgencies] 914 + 915 + if gt - self.cooldownTimes.alarm < freq then return end 916 + 917 + self.cooldownTimes.alarm = gt 918 + self:suitSound(urg.sound) 919 + 920 + if where then 921 + local elt = { 922 + tex = where.tex or 'starlit-ui-alert.png'; 923 + scale = {x=1, y=1}; 924 + align = table.copy(where.elt.def.align); 925 + pos = table.copy(where.elt.def.pos); 926 + ofs = table.copy(where.elt.def.ofs); 927 + } 928 + elt.ofs.x = elt.ofs.x + where.ofs.x 929 + elt.ofs.y = elt.ofs.y + where.ofs.y 930 + local attached = self:attachImage(elt) 931 + table.insert(self.hud.alarm, attached) 932 + 933 + -- HATE. HATE. HAAAAAAAAAAATE 934 + minetest.after(freq/2, function() 935 + for k,v in pairs(self.hud.alarm) do 936 + self.entity:hud_remove(v.id) 937 + end 938 + self.hud.alarm={} 939 + end) 940 + end 941 + end; 879 942 880 943 ------------- 881 944 -- weather -- 882 945 ------------- 883 946 updateWeather = function(self) 884 947 end; 885 948 ................................................................................ 933 996 934 997 local clockInterval = 1.0 935 998 starlit.startJob('starlit:clock', clockInterval, function(delta) 936 999 for id, u in pairs(starlit.activeUsers) do 937 1000 u.hud.elt.time:update() 938 1001 end 939 1002 end) 1003 + 1004 +-- performs a general HUD refresh, mainly to update the HUD backlight brightness 1005 +local hudInterval = 10 1006 +starlit.startJob('starlit:hud-refresh', hudInterval, function(delta) 1007 + for id, u in pairs(starlit.activeUsers) do u:updateHUD() end 1008 +end) 940 1009 941 1010 local biointerval = 1.0 942 1011 starlit.startJob('starlit:bio', biointerval, function(delta) 943 1012 for id, u in pairs(starlit.activeUsers) do 944 1013 if u:effectiveStat 'health' ~= 0 then 945 1014 local bmr = u:phenoTrait 'metabolism' * biointerval 946 1015 -- TODO apply modifiers
Modified mods/starlit/world.lua from [d79dc9efc2] to [a2ac450e1c].
176 176 -- player is in -30°C weather, and has an internal temperature of 177 177 -- 10°C. then: 178 178 -- κ = .1°C/C/s (which is apparently 100mHz) 179 179 -- Tₚ = 10°C 180 180 -- Tₑ = -30°C 181 181 -- d = Tₑ − Tₚ = -40°C 182 182 -- ΔT = κ×d = -.4°C/s 183 + -- too cold: 184 + -- x = beginning of danger zone 185 + -- κ × (x - Tₚ) = y where y < Tₚ 183 186 -- our final change in temperature is computed as tΔC where t is time 184 - local kappa = .05 187 + local kappa = starlit.constant.heat.thermalConductivity 185 188 for name,user in pairs(starlit.activeUsers) do 186 189 local tr = user:species().tempRange 187 190 local t = starlit.world.climate.temp(user.entity:get_pos()) 191 + 192 + do -- this bit probably belongs in starlit:bio but we do it here in order 193 + -- to spare ourselves another call into the dark swamp of climate.temp 194 + local urg = 1 195 + local function alarm(kind) 196 + user:alarm(urg, kind, nil, { 197 + elt = user.hud.elt.temp, ofs = {x=100,y=0}; 198 + tex = 'starlit-ui-alert-'..kind..'.png'; 199 + }) 200 + end 201 + local hz = user:tempHazard(t) 202 + local tr = user:species().tempRange.survivable 203 + if hz == 'cold' then 204 + if tr[1] - t > 7 then urg = 2 end 205 + alarm 'temp-cold' 206 + elseif hz == 'hot' then 207 + if t - tr[2] > 7 then urg = 2 end 208 + alarm 'temp-hot' 209 + end 210 + end 211 + 188 212 local insul = 0 189 213 local naked = user:naked() 190 214 local suitDef 191 215 if not naked then 192 216 suitDef = user:suitStack():get_definition() 193 217 insul = suitDef._starlit.suit.temp.insulation 194 218 end ................................................................................ 223 247 end 224 248 end 225 249 226 250 user:statDelta('warmth', tgt - warm) -- dopey but w/e 227 251 228 252 warm = tgt -- for the sake of readable code 229 253 254 + -- does this belong in starlit:bio? unsure tbh 230 255 if warm < tSafeMin or warm > tSafeMax then 231 256 local dv 232 257 if warm < tSafeMin then 233 258 dv = math.abs(warm - tSafeMin) 234 259 else 235 260 dv = math.abs(warm - tSafeMax) 236 261 end
Modified starlit.ct from [415d01ad10] to [8d6b5074b6].
1 1 # starlit 2 2 [*starlit] is a sci-fi survival game. you play the survivor of a disaster in space, stranded on a just-barely-habitable world with nothing but your escape pod, your survival suit, and some handy new psionic powers that the accident seems to have unlocked in you. scavenge resources, search alien ruins, and build a base where you can survive indefinitely, but be careful: winter approaches, and your starting suit heater is already struggling to keep you alive in the comparatively warm days of "summer". 3 3 4 -## story 5 -### "Imperial Expat" background 4 +##story story 6 5 about a month ago, you woke up to unexpected good news. your application to join the new Commune colony at Thousand Petal, submitted in a moment of utter existential weariness and almost in jest, was actually accepted. your skillset was a "perfect match" for the budding colony's needs, claimed the Population Control Authority, and you'd earned yourself a free trip to your new home -- on a swanky state transport, no less. 7 6 8 7 it took a few discreet threats and bribes from Commune diplomats, but after a week of wrangling with the surly Crown Service for Comings & Goings -- whose bureaucrats seemed outright [!offended] that you actually managed to find a way off that hateful rock -- you secured grudging clearance to depart. you celebrated by telling your slackjawed boss exactly what you thought of him in a meeting room packed with his fellow parasites -- and left House Taladran with a new appreciation for the value of your labor, as the nobs found themselves desperately scrabbling for a replacement on short notice. 9 8 10 9 you almost couldn't believe it when the Commune ship -- a sleek, solid piece of engineering whose graceful descent onto the landing pad seemed to sneer at the lurching rattletraps arrayed all around it -- actually showed up. in a daze you handed over your worldly possessions -- all three of them -- to a valet with impeccable manners, and climbed up out of the wagie nightmare into high orbit around your homeworld. the mercenary psion aboard, a preening Usukwinti with her very own luxury suite, tore a bleeding hole in the spacetime metric, and five hundred hopeful souls dove through towards fancied salvation. "sure," you thought to yourself as you slipped into your sleek new nanotech environment suit, itself worth more than the sum total of your earnings on Flame of Unyielding Purification, "life won't be easy -- but damn it, it'll [!mean] something out there." 11 10 12 11 a free life on the wild frontier with a nation of comrades to have your back, with the best tech humans can make, fresh, clean water that isn't laced with compliance serum, and -- best of all -- never having to worry about paying rent again. it was too good to be true, you mused. ................................................................................ 38 37 39 38 p11143: https://github.com/minetest/minetest/pull/11143.diff 40 39 41 40 ### shadows 42 41 i was delighted to see dynamic shadows land in minetest, and i hope the implementation will eventually mature. however, as it stands, there are severe issues with shadows that make them essentially incompatible with complex meshes like the Starlit player character meshes. for the sake of those who don't mind these glitches, Starlit does enable shadows, but i unfortunately have to recommend that you disable them until the minetest devs get their act together on this feature. 43 42 44 43 ## gameplay 44 +starlit is somewhat unusual in how it uses the minetest engine. it's a voxel game but not of the minecraft variety. 45 + 45 46 the most important thing to understand about starlit is that is is [*mean], by design. 46 47 47 48 * chance plays an important role. your escape pod might land in the midst of a lush, temperate forest with plenty of nearby shipwrecks to scavenge. or it might land in the exact geographic center of a vast, harsh desert that your suit's cooling systems can't protect you from, ten klicks from anything of value. "unfair", you say? tough. Farthest Shadow doesn't care about your feelings. 48 49 * death is much worse than a slap on the wrist. when you die, you drop your possessions and your suit, and respawn naked at your spawn point. this is a serious danger, as you might be kilometers away from your spawn point -- and there's no guarantee someone else won't take your suit before you can find your way back to it. good luck crossing long distances without climate control! if you haven't carefully prepared for this eventuality by keeping a spare suit by your spawn point, death can be devastating, to the point of making the game unsurvivable without another player's help. 49 50 50 -starlit is somewhat unusual in how it uses the minetest engine. it's a voxel game but not of the minecraft variety. 51 +### scenarios 52 +your starting character configuration depends on the scenario you select. (right now this is configured in minetest settings, which is intensely awkward, but i don't have a better solution). the scenario controls your species, sex, and starting inventory. [*neither species nor sex is cosmetic]; e.g. human females are physically weaker but psionically stronged than males. the current playable scenarios are: 53 + 54 +#### Imperial Expat 55 +[*phenotype]: human female 56 +[*starting gear]: Commune survival kit 57 +> Hoping to escape a miserable life deep in the grinding gears of the capitalist machine for the bracing freedom of the frontier, you sought entry as a colonist to the new Commune world of Thousand Petal. Fate -- which is to say, terrorists -- intervened, and you wound up stranded on Farthest Shadow with little more than the nanosuit on your back, ship blown to tatters and your soul thoroughly mauled by the explosion of a twisted alien artifact -- which SOMEONE neglected to inform you your ride would be carrying. 58 +> At least you got some handy psionic powers out of this whole clusterfuck. Hopefully they're safe to use. 59 + 60 +#### Gentleman Adventurer [!(unimplemented)] 61 +[*phenotype]: human male 62 +[*starting gear]: Imperial survival kit 63 +> Tired of the same-old-same-old, sick of your idiot contemporaries, exasperated with the shallow soul-rotting luxury of life as landless lordling, and earnestly eager to enrage your father, you resolved to see the Reach in all her splendor. Deftly evading the usual tourist traps, you finagled your way into the confidence of the Commune ambassador with a few modest infusions of Father's money -- now [!that] should pop his monocle -- and secured yourself a seat on a ride to their brand-new colony at Thousand Petal. How exciting -- a genuine frontier outing! 64 + 65 +#### Terrorist Tagalong 66 +[*phenotype]: human female 67 +[*starting gear]: star merc combat kit 68 +> It turns out there's a *reason* Crown jobs pay so well. 69 + 70 +#### Tradebird Bodyguard [!(unimplemented)] 71 +[*phenotype]: male Usukwinti 72 +[*starting gear]: Usuk survival kit 73 +> You've never understood why astropaths of all people [!insist] on bodyguards. This one could probably make hash of a good-sized human batallion, if her feathers were sufficiently ruffled. Perhaps it's a status thing. Whatever the case, it's easy money. 74 +> At least, it was supposed to be. 51 75 52 76 ### controls 53 77 summon your Suit Interface by pressing the [*E] / [*Inventory] key. this will allow you to move items around in your inventory, but more importantly, it also allows you select or configure your Interaction Mode. 54 78 55 79 the top three buttons can be used to select (or deactivate) an Interaction Mode. an Interaction Mode can be configured by pressing the button immediately below. the active Interaction Mode controls the behavior of the mouse buttons when no item is selected in the hotbar. 56 80 57 81 the modes are: ................................................................................ 67 91 68 92 to use a tool, select it in the hotbar. even if an Interaction Mode is active, the tool will take priority. press [*Left Button] / [*Punch] to use the tool on a block; for instance, to break a stone with a jackhammer. to configure a tool or use its secondary functions, if any, press [*Right Button] / [*Place]. 69 93 70 94 hold [*Aux1] to activate your selected Maneuver. by default this is Sprint, which will consume stamina to allow you to run much faster. certain suits offer the Flight ability, which allows slow, mid-range flight. you can also unlock the psionic ability Lift, which allows very rapid flight but consumes psi at a prodigious rate. 71 95 72 96 you can only have one Maneuver active at a time, whether this is a Psi Maneuver (consuming psi), a Suit Maneuver (consuming battery), or a Body Maneuver (consuming stamina). Maneuvers are activated in their respective panel. 73 97 98 +### stats 99 +to survive and thrive on Farthest Shadow, you need to manage your stats carefully. stats impact gameplay and other stats in various ways. 100 +* [*health]: self-explanatory. it hits zero, you die. measured in hit points (hp) 101 + ** regenerates very slowly, though nanomedical suites improve this considerably 102 +* [*stamina]: how long you can sustain intense physical activity. measured in sprinting meters (m) 103 +** regenerates quickly, depending on [*fatigue] 104 +** consumed by biological abilities such as sprinting or Usuk flight. 105 +** affects [*fatigue]: the lower your stamina bar, the faster your fatigue builds 106 +* [*energy]: the amount of electrical power available to your environment suit. measured in joules (J) 107 +** does not regenerate, but empty batteries can be swapped out to replenish energy in the field 108 +** consumed by all suit abilities, including nanotech and weapons systems 109 +* [*numina]: a measure of your available psionic power. measured in psi (ψ) 110 +** accumulates slowly, depending on [*morale] 111 +* [*nutrition]: how much energy your body has stored. measured in kCal. basal metabolic rate depends on species and sex 112 +** affects [*morale]: if you're starving, you bleed morale more quickly 113 +** affects [*health]: you will die if you do not eat enough 114 +* [*hydration]: stay hydrated uwu. measured in liters (L) 115 +** affects [*morale]: if you're parched, you bleed morale much more quickly 116 +** affects [*health]: you will die very quickly if you do not drink enough 117 +* [*warmth]: maintaining a healthy body temperature is crucially important on Farthest Shadow, which does not have many places a human can be comfortable without a powered environment suit. if you're outside your species' comfort range, your stamina regen and morale expenditure will be impacted. if you're outside your species' [*survival] range, you will start dying of hypo/hyperthermia. most environment suits have built-in thermoelectrics that will try to keep you at a comfortable (or merely survivable, in power save mode) temperature, but this can drain your suit batteries very quickly at extreme temperatures. 118 +** affects [*morale], [*stamina], [*health] 119 +* [*fatigue]: how long you've gone without sleep. 120 +** affects [*stamina] regen: the higher your [*fatigue], the more slowly you regnerate stamina. if you are fully fatigued (exhausted), you do not regenerate stamina 121 +* [*morale]: how happy you are. measured in the number of hours you can continue functioning emotionally 122 +** diminishes over time. can be replenished by various activities, such as eating tasty food 123 +** affects [*numina] regen: the lower your morale, the more slowly you accumulate numina. if you are completely out of morale (depressed), you do not accumulate any numina 124 +* [*irradation]: how much ionizing radiation you've soaked up. measured in grays (Gy) 125 +** your environment suit provides some protection against environmental radiation. how much depends on your model of suit. 126 +** affects [*health]: slows natural healing. at values over 2Gy, you will start to hemorrhage health, though a capable nanomedical system can compensate up to a point 127 +** affects [*numina]: you accumulate numina more quickly in high-rad areas 128 +** naturally diminishes, but very slowly 129 +* [*illness]: not everything on Farthest Shadow's ecosystem is, shall we say, biocompatible. measured in percent 130 +** affects [*morale]: the higher your illness, the more quickly you bleed morale 131 + 132 +your primary stats are shown on your HUD. ancillary stats can be viewed in the "body" panel. 133 + 74 134 ### psionics 75 135 there are four types of psionic abilities: Manual, Maneuver, Ritual, and Contextual. 76 136 77 137 you can assign two Manual abilities at any given time and access them with the mouse buttons in Psionics mode. 78 138 79 139 you can select a Psi Maneuver in the Psionics panel and activate it by holding [*Aux1]. 80 140