36
37
38
39
40
41
42
43
44
45
46
47
48
49
..
56
57
58
59
60
61
62
63
64
65
66
67
68
69
...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
...
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
...
394
395
396
397
398
399
400
401
402
403
404
405
406
407
...
424
425
426
427
428
429
430
431
432
433
434
435
436
437
...
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
...
906
907
908
909
910
911
912
913
914
915
916
917
918
919
...
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
...
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
|
name = luser:get_player_name()
end
return {
entity = luser;
name = name;
hud = {
elt = {};
};
tree = {};
action = {
bits = 0; -- for control deltas
prog = {}; -- for recording action progress on a node; reset on refocus
tgt = {type='nothing'};
sfx = {};
................................................................................
psi = {primary = nil, secondary = nil};
maneuver = nil;
};
pref = {
calendar = 'commune';
};
overlays = {};
}
end;
__index = {
--------------
-- overlays --
--------------
updateOverlays = function(self)
................................................................................
if dt[stat]+base > max then dt[stat] = max-base
elseif dt[stat]+base < min then dt[stat] = min-base end
self:pushPersona()
end
self:updateHUD()
-- TODO trigger relevant animations?
end;
statRange = function(self, stat) --> min, max, base
return starlit.world.species.statRange(
self.persona.species, self.persona.speciesVariant, stat)
end;
effectiveStat = function(self, stat)
................................................................................
return bar, {x=3 * def.size, y=16} -- x*2??? what
end;
createHUD = function(self)
local function basicStat(statName)
return function(user, bar)
return self:effectiveStat(statName)
end
end
local function batteryLookup(user)
local max = user:suitPowerCapacity()
if max == 0 then return 0, 0 end
local ch = user:suitCharge()
return (ch/max)*100, ch/max
end
local function C(h,s,l) return {hue=h,sat=s,lum=l} end
local hbofs = (1+self.entity:hud_get_hotbar_itemcount()) * 25
local bpad = 8
self.hud.elt.health = self:attachStatBar {
name = 'health', stat = basicStat 'health';
color = C(340,0,.3), size = 100;
pos = {x=0.5, y=1}, ofs = {x = -hbofs, y=-48 - bpad};
dir = 1;
align = {x=-1, y=-1};
}
self.hud.elt.stamina = self:attachStatBar {
name = 'stamina', stat = basicStat 'stamina';
color = C(60,0,.2), size = 100;
pos = {x=0.5, y=1}, ofs = {x = -hbofs, y=-24 - bpad};
dir = 1;
align = {x=-1, y=-1};
}
self.hud.elt.bat = self:attachStatBar {
name = 'battery', stat = batteryLookup;
color = C(190,0,.2), size = 100;
pos = {x=0.5, y=1}, ofs = {x = hbofs - 4, y=-48 - bpad};
dir = 0;
align = {x=1, y=-1};
}
self.hud.elt.psi = self:attachStatBar {
name = 'psi', stat = basicStat 'psi';
color = C(320,0,.2), size = 100;
pos = {x=0.5, y=1}, ofs = {x = hbofs - 4, y=-24 - bpad};
dir = 0;
align = {x=1, y=-1};
}
self.hud.elt.time = self:attachTextBox {
name = 'time';
................................................................................
measure = function(user)
local hot = self:effectiveStat 'irradiation'
local color = self:uiColor():lerp(lib.color(0.3, 1, 0), math.min(1, hot/5))
local txt = string.format("%sGy", math.floor(hot))
return (hot/5), txt, color
end;
}
self.hud.elt.crosshair = self:attachImage {
name = 'crosshair';
tex = '';
pos = {x=.5, y=.5};
scale = {x=1,y=1};
ofs = {x=0, y=0};
align = {x=0, y=0};
................................................................................
ofs = {x=0, y=0};
align = {x=0, y=-1};
z = -1;
update = function(user, set)
set('text', hudAdjustBacklight(hudCenterBG):render())
end;
};
end;
deleteHUD = function(self)
for name, e in pairs(self.hud.elt) do
self:hud_delete(e.id)
end
end;
updateHUD = function(self)
................................................................................
local suit = self:getSuit()
suit:establishInventories(self.entity)
if self:suitCharge() <= 0 then
self:suitPowerStateSet 'off'
end
end
self:updateHUD()
end;
reconfigureSuit = function(self)
-- and here's where things get ugly
-- you can't have an inventory inside another item. to hack around this,
-- we use the player as the location of the suit inventories, and whenever
-- there's a change in the content of these inventories, this function is
-- called to serialize those inventories out to the suit stack
................................................................................
local fd = stack:take_item(n)
local stats = starlit.world.food.effectiveStats(fd)
return stack
end;
};
}
local biointerval = 1.0
starlit.startJob('starlit:bio', biointerval, function(delta)
for id, u in pairs(starlit.activeUsers) do
if u:effectiveStat 'health' ~= 0 then
local bmr = u:phenoTrait 'metabolism' * biointerval
-- TODO apply modifiers
................................................................................
local tempPenalty = tempDiff/3
moralePenalty = moralePenalty + tempPenalty
heatPenalty = heatPenalty + tempPenalty
end
-- penalize heavy phys. activity
local stamina, sp = u:effectiveStat 'stamina'
fatiguePenalty = fatiguePenalty * (1 + 9*(1-sp))
local food = u:effectiveStat 'nutrition'
local water = u:effectiveStat 'hydration'
local rads = u:effectiveStat 'irradiation'
if food < 1000 then moralePenalty = moralePenalty + (1 - (food/1000)) * 5 end
if water < 1 then moralePenalty = moralePenalty + (1 - (water/1)) * 10 end
................................................................................
u:statDelta('health', -5*biointerval)
end
if water == 0 then -- dying of thirst
u:statDelta('health', -20*biointerval)
end
if sp < 1.0 then
u:statDelta('stamina', u:phenoTrait('staminaRegen',1) / heatPenalty)
-- print('stam', u:effectiveStat 'stamina', u:phenoTrait('staminaRegen',1) / heatPenalty, heatPenalty)
end
end
end
end)
local cbit = {
up = 0x001;
down = 0x002;
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
|
|
|
|
|
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
|
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
..
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
...
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
...
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
...
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
...
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
...
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
...
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
...
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
...
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
|
name = luser:get_player_name()
end
return {
entity = luser;
name = name;
hud = {
elt = {};
bar = {};
};
tree = {};
action = {
bits = 0; -- for control deltas
prog = {}; -- for recording action progress on a node; reset on refocus
tgt = {type='nothing'};
sfx = {};
................................................................................
psi = {primary = nil, secondary = nil};
maneuver = nil;
};
pref = {
calendar = 'commune';
};
overlays = {};
cooldownTimes = {
stamina = 0;
};
}
end;
__index = {
--------------
-- overlays --
--------------
updateOverlays = function(self)
................................................................................
if dt[stat]+base > max then dt[stat] = max-base
elseif dt[stat]+base < min then dt[stat] = min-base end
self:pushPersona()
end
local sb = self.hud.bar[stat]
if sb then sb:update() end
-- self:updateHUD()
-- TODO trigger relevant animations?
end;
statRange = function(self, stat) --> min, max, base
return starlit.world.species.statRange(
self.persona.species, self.persona.speciesVariant, stat)
end;
effectiveStat = function(self, stat)
................................................................................
return bar, {x=3 * def.size, y=16} -- x*2??? what
end;
createHUD = function(self)
local function basicStat(statName)
return function(user, bar)
return self:effectiveStat(statName)
end
end
local function attachBasicStat(def)
local statName = def.stat
def.stat = basicStat(def.stat)
local b = self:attachStatBar(def)
self.hud.bar[statName] = b
return b
end
local function batteryLookup(user)
local max = user:suitPowerCapacity()
if max == 0 then return 0, 0 end
local ch = user:suitCharge()
return (ch/max)*100, ch/max
end
local function C(h,s,l) return {hue=h,sat=s,lum=l} end
local hbofs = (1+self.entity:hud_get_hotbar_itemcount()) * 25
local bpad = 8
self.hud.elt.health = attachBasicStat {
name = 'health', stat = 'health';
color = C(10,0,.3), size = 100;
pos = {x=0.5, y=1}, ofs = {x = -hbofs, y=-48 - bpad};
dir = 1;
align = {x=-1, y=-1};
}
self.hud.elt.stamina = attachBasicStat {
name = 'stamina', stat = 'stamina';
color = C(60,0,.2), size = 100;
pos = {x=0.5, y=1}, ofs = {x = -hbofs, y=-24 - bpad};
dir = 1;
align = {x=-1, y=-1};
}
self.hud.elt.bat = self:attachStatBar {
name = 'battery', stat = batteryLookup;
color = C(190,0,.2), size = 100;
pos = {x=0.5, y=1}, ofs = {x = hbofs - 4, y=-48 - bpad};
dir = 0;
align = {x=1, y=-1};
}
self.hud.elt.psi = attachBasicStat {
name = 'psi', stat = 'psi';
color = C(320,0,.2), size = 100;
pos = {x=0.5, y=1}, ofs = {x = hbofs - 4, y=-24 - bpad};
dir = 0;
align = {x=1, y=-1};
}
self.hud.elt.time = self:attachTextBox {
name = 'time';
................................................................................
measure = function(user)
local hot = self:effectiveStat 'irradiation'
local color = self:uiColor():lerp(lib.color(0.3, 1, 0), math.min(1, hot/5))
local txt = string.format("%sGy", math.floor(hot))
return (hot/5), txt, color
end;
}
-- special-case the meters
self.hud.bar.irradiation = self.hud.elt.geiger
self.hud.bar.warmth = self.hud.elt.temp
self.hud.elt.crosshair = self:attachImage {
name = 'crosshair';
tex = '';
pos = {x=.5, y=.5};
scale = {x=1,y=1};
ofs = {x=0, y=0};
align = {x=0, y=0};
................................................................................
ofs = {x=0, y=0};
align = {x=0, y=-1};
z = -1;
update = function(user, set)
set('text', hudAdjustBacklight(hudCenterBG):render())
end;
};
self:updateHUD()
end;
deleteHUD = function(self)
for name, e in pairs(self.hud.elt) do
self:hud_delete(e.id)
end
end;
updateHUD = function(self)
................................................................................
local suit = self:getSuit()
suit:establishInventories(self.entity)
if self:suitCharge() <= 0 then
self:suitPowerStateSet 'off'
end
end
-- self:updateHUD()
self.hud.elt.bat:update()
end;
reconfigureSuit = function(self)
-- and here's where things get ugly
-- you can't have an inventory inside another item. to hack around this,
-- we use the player as the location of the suit inventories, and whenever
-- there's a change in the content of these inventories, this function is
-- called to serialize those inventories out to the suit stack
................................................................................
local fd = stack:take_item(n)
local stats = starlit.world.food.effectiveStats(fd)
return stack
end;
};
}
local clockInterval = 1.0
starlit.startJob('starlit:clock', clockInterval, function(delta)
for id, u in pairs(starlit.activeUsers) do
u.hud.elt.time:update()
end
end)
local biointerval = 1.0
starlit.startJob('starlit:bio', biointerval, function(delta)
for id, u in pairs(starlit.activeUsers) do
if u:effectiveStat 'health' ~= 0 then
local bmr = u:phenoTrait 'metabolism' * biointerval
-- TODO apply modifiers
................................................................................
local tempPenalty = tempDiff/3
moralePenalty = moralePenalty + tempPenalty
heatPenalty = heatPenalty + tempPenalty
end
-- penalize heavy phys. activity
local stamina, sp = u:effectiveStat 'stamina'
local fatigue, fp = u:effectiveStat 'fatigue'
fatiguePenalty = fatiguePenalty * (1 + 9*(1-sp))
local penaltyFromFatigue = 1 - fp
local food = u:effectiveStat 'nutrition'
local water = u:effectiveStat 'hydration'
local rads = u:effectiveStat 'irradiation'
if food < 1000 then moralePenalty = moralePenalty + (1 - (food/1000)) * 5 end
if water < 1 then moralePenalty = moralePenalty + (1 - (water/1)) * 10 end
................................................................................
u:statDelta('health', -5*biointerval)
end
if water == 0 then -- dying of thirst
u:statDelta('health', -20*biointerval)
end
if sp < 1.0 and minetest.get_gametime() - u.cooldownTimes.stamina > 5.0 then
u:statDelta('stamina', (u:phenoTrait('staminaRegen',1) * penaltyFromFatigue) / heatPenalty)
-- print('stam', u:effectiveStat 'stamina', u:phenoTrait('staminaRegen',1) / heatPenalty, heatPenalty)
end
local morale, mp = u:effectiveStat 'morale'
local pr = u:phenoTrait 'psiRegen'
u:statDelta('psi', pr * penaltyFromFatigue * mp)
end
end
end)
local cbit = {
up = 0x001;
down = 0x002;
|