starlit  Diff

Differences From Artifact [9accce5f34]:

To Artifact [1a0e392600]:


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
...
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
...
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
...
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
...
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
...
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
...
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
....
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
....
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
....
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
....
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
....
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
....
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
....
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
--    client. it provides for initial signup and join,
--    managing the HUD, skinning the player model,
--    effecting weather changes, etc.

local lib = starlit.mod.lib

local function hudAdjustBacklight(img)
	local night = math.abs(minetest.get_timeofday() - .5) * 2
	local opacity = night*0.8
	return img:fade(opacity)
end

local userStore = lib.marshal.metaStore {
	persona = {
		key  = 'starlit:persona';
................................................................................
starlit.type.user = lib.class {
	name = 'starlit:user';
	leds = leds;
	construct = function(ident)
		local name, luser
		if type(ident) == 'string' then
			name = ident
			luser = minetest.get_player_by_name(name)
		else
			luser = ident
			name = luser:get_player_name()
		end
		return {
			entity = luser;
			name = name;
................................................................................
		}
	end;
	__index = {
		--------------
		-- overlays --
		--------------
		updateOverlays = function(self)
			-- minetest: because fuck you, that's why
			local engineGravity = starlit.constant.phys.engineGravity
			local targetGravity = starlit.world.planet.gravity
			local phys = {
				speed = self.pheno:trait('speed',1);
				jump = self.pheno:trait('jump',1);
				gravity = targetGravity / engineGravity;
				speed_climb = 1;
................................................................................
			self.hud.elt.time = self:attachTextBox {
				name = 'time';
				align = {x=0, y=1};
				pos = {x=0.5, y=1};
				ofs = {x=0,y=-95};
				text = function(user)
					local cal = starlit.world.time.calendar[user.pref.calendar]
					return cal.time(minetest.get_timeofday())
				end;
			}
			self.hud.elt.temp = self:attachMeter {
				name = 'temp';
				align = {x=1, y=-1};
				pos = {x=0, y=1};
				ofs = {x=20, y=-20};
................................................................................
		updateHUD = function(self)
			for name, e in pairs(self.hud.elt) do
				if e.update then e.update() end
			end
			self:updateLEDs()
		end;
		updateLEDs = function(self)
			local time = minetest.get_gametime()
			local function updateSide(name, ofs, tx)
				local del = {}
				local idx = 0
				for i, l in ipairs(self.hud.led[name]) do
					if time - l.origin > 3 then
						if l.elt then self.entity:hud_remove(l.elt.id) end
						self.hud.led.map[l.kind] = nil
................................................................................
			inv:set_stack('hand', 1, hnd)
		end;

		---------------------
		-- intel-gathering --
		---------------------
		clientInfo = function(self)
			return minetest.get_player_information(self.name)
		end;
		species = function(self)
			return starlit.world.species.index[self.persona.species]
		end;
		-- can the suit heater sustain its current internal temperature in an area of t°C
		tempCanSustain = function(self, t)
			if self:naked() then return false end
................................................................................

			-- i feel like there has to be a better way
			local posrng = starlit.world.seedbank[0x13f19] -- TODO player-specific seed
			local cx = posrng:int(-500,500) --math.random(-500,500)
			local iter, startPoint = 1
			repeat local temp = -100
				local cz = posrng:int(-500,500)
				local cy = minetest.get_spawn_level(cx, cz)
				if cy then
					startPoint = vector.new(cx,cy,cz)
					temp = starlit.world.climate.eval(startPoint,.5,.5).surfaceTemp
				end
				iter = iter + 1
				if iter > 100 then break end -- avoid infiniloop in pathological conditions
			until temp > -2
................................................................................
		onDie = function(self, reason)
			local inv = self.entity:get_inventory()
			local where = self.entity:get_pos()
			local function dropInv(lst)
				local l = inv:get_list(lst)
				for i, o in ipairs(l) do
					if o and not o:is_empty() then
						minetest.item_drop(o, self.entity, where)
					end
				end
				inv:set_list(lst, {})
			end
			dropInv 'main'
			dropInv 'starlit_suit'
			self:updateSuit()
................................................................................
		-- environment suit & body --
		-----------------------------
		suitStack = function(self)
			return self.entity:get_inventory():get_stack('starlit_suit', 1)
		end;
		suitSound = function(self, sfx)
			-- trigger a sound effect from the player's suit computer
			minetest.sound_play(sfx, {object=self.entity, max_hear_distance=4}, true)
		end;
		suitPowerStateSet = function(self, state, silent)
			-- necessary to enable reacting to power state changes
			-- e.g. to play sound effects, display warnings
			local os
			self:forSuit(function(s)
				os=s:powerState()
................................................................................
				return true
			end
			return false
		end;

		alarm = function(self, urgency, kind, minFreq)
			minFreq = minFreq or 1.5
			local time = minetest.get_gametime()
			local led = leds[kind]

			local ul = self.hud.led.map[kind]
			if ul then
				if time - ul.origin > minFreq then
					ul.origin = time
				else return end
................................................................................

		--[[
			freq = freq or 3
			local urgencies = {
				[1] = {sound = 'starlit-alarm'};
				[2] = {sound = 'starlit-alarm-urgent'};
			}
		   local gt = minetest.get_gametime()
		   local urg = urgencies[urgency] or urgencies[#urgencies]

		   if gt - self.cooldownTimes.alarm < freq then return end

		   self.cooldownTimes.alarm = gt
		   self:suitSound(urg.sound)

................................................................................
			   }
			   elt.ofs.x = elt.ofs.x + where.ofs.x
			   elt.ofs.y = elt.ofs.y + where.ofs.y
			   local attached = self:attachImage(elt)
				table.insert(self.hud.alarm, attached)

			   -- HATE. HATE. HAAAAAAAAAAATE
			   minetest.after(freq/2, function()
				   for k,v in pairs(self.hud.alarm) do
					   self.entity:hud_remove(v.id)
				   end
				   self.hud.alarm={}
			   end)
		   end]]
	   end;
................................................................................
		---------------
		-- inventory --
		---------------
		give = function(self, item)
			item = ItemStack(item)
			local inv = self.entity:get_inventory()
			local function is(grp)
				return minetest.get_item_group(item:get_name(), grp) ~= 0
			end
			-- TODO notif popups
			if is 'specialInventory' then
			--[[
				if is 'powder' then
					if self:naked() then return item end
					local cans = inv:get_list 'starlit_suit_canisters'
................................................................................
			else
				return inv:add_item('main', item)
			end
		end;
		thrustUpon = function(self, item)
			local r = self:give(st)
			if not r:is_empty() then
				return minetest.add_item(self.entity:get_pos(), r)
			end
		end;
		consume = function(self, stack, n)
			n = n or 1
			if n == 0 then n = stack:get_count() end
			local fd = stack:take_item(n)
			local stats = starlit.world.food.effectiveStats(fd)
................................................................................
				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 'numinaRegen'
			u:statDelta('numina', pr * penaltyFromFatigue * mp)
................................................................................
	manv = 0x020;
	snk  = 0x040;
	dig  = 0x080;
	put  = 0x100;
	zoom = 0x200;
}
-- this is the painful part
minetest.register_globalstep(function(delta)
	local doNothing,mustInit,mustHalt = 0,1,2
	for id, user in pairs(starlit.activeUsers) do
		local ent = user.entity
		local bits = ent:get_player_control_bits()

		local function what(b)
			if bit.band(bits, b) ~= 0 and bit.band(user.action.bits, b) == 0 then







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
...
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
...
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
...
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
...
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
...
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
...
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
....
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
....
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
....
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
....
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
....
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
....
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
....
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
--    client. it provides for initial signup and join,
--    managing the HUD, skinning the player model,
--    effecting weather changes, etc.

local lib = starlit.mod.lib

local function hudAdjustBacklight(img)
	local night = math.abs(core.get_timeofday() - .5) * 2
	local opacity = night*0.8
	return img:fade(opacity)
end

local userStore = lib.marshal.metaStore {
	persona = {
		key  = 'starlit:persona';
................................................................................
starlit.type.user = lib.class {
	name = 'starlit:user';
	leds = leds;
	construct = function(ident)
		local name, luser
		if type(ident) == 'string' then
			name = ident
			luser = core.get_player_by_name(name)
		else
			luser = ident
			name = luser:get_player_name()
		end
		return {
			entity = luser;
			name = name;
................................................................................
		}
	end;
	__index = {
		--------------
		-- overlays --
		--------------
		updateOverlays = function(self)
			-- luanti: because fuck you, that's why
			local engineGravity = starlit.constant.phys.engineGravity
			local targetGravity = starlit.world.planet.gravity
			local phys = {
				speed = self.pheno:trait('speed',1);
				jump = self.pheno:trait('jump',1);
				gravity = targetGravity / engineGravity;
				speed_climb = 1;
................................................................................
			self.hud.elt.time = self:attachTextBox {
				name = 'time';
				align = {x=0, y=1};
				pos = {x=0.5, y=1};
				ofs = {x=0,y=-95};
				text = function(user)
					local cal = starlit.world.time.calendar[user.pref.calendar]
					return cal.time(core.get_timeofday())
				end;
			}
			self.hud.elt.temp = self:attachMeter {
				name = 'temp';
				align = {x=1, y=-1};
				pos = {x=0, y=1};
				ofs = {x=20, y=-20};
................................................................................
		updateHUD = function(self)
			for name, e in pairs(self.hud.elt) do
				if e.update then e.update() end
			end
			self:updateLEDs()
		end;
		updateLEDs = function(self)
			local time = core.get_gametime()
			local function updateSide(name, ofs, tx)
				local del = {}
				local idx = 0
				for i, l in ipairs(self.hud.led[name]) do
					if time - l.origin > 3 then
						if l.elt then self.entity:hud_remove(l.elt.id) end
						self.hud.led.map[l.kind] = nil
................................................................................
			inv:set_stack('hand', 1, hnd)
		end;

		---------------------
		-- intel-gathering --
		---------------------
		clientInfo = function(self)
			return core.get_player_information(self.name)
		end;
		species = function(self)
			return starlit.world.species.index[self.persona.species]
		end;
		-- can the suit heater sustain its current internal temperature in an area of t°C
		tempCanSustain = function(self, t)
			if self:naked() then return false end
................................................................................

			-- i feel like there has to be a better way
			local posrng = starlit.world.seedbank[0x13f19] -- TODO player-specific seed
			local cx = posrng:int(-500,500) --math.random(-500,500)
			local iter, startPoint = 1
			repeat local temp = -100
				local cz = posrng:int(-500,500)
				local cy = core.get_spawn_level(cx, cz)
				if cy then
					startPoint = vector.new(cx,cy,cz)
					temp = starlit.world.climate.eval(startPoint,.5,.5).surfaceTemp
				end
				iter = iter + 1
				if iter > 100 then break end -- avoid infiniloop in pathological conditions
			until temp > -2
................................................................................
		onDie = function(self, reason)
			local inv = self.entity:get_inventory()
			local where = self.entity:get_pos()
			local function dropInv(lst)
				local l = inv:get_list(lst)
				for i, o in ipairs(l) do
					if o and not o:is_empty() then
						core.item_drop(o, self.entity, where)
					end
				end
				inv:set_list(lst, {})
			end
			dropInv 'main'
			dropInv 'starlit_suit'
			self:updateSuit()
................................................................................
		-- environment suit & body --
		-----------------------------
		suitStack = function(self)
			return self.entity:get_inventory():get_stack('starlit_suit', 1)
		end;
		suitSound = function(self, sfx)
			-- trigger a sound effect from the player's suit computer
			core.sound_play(sfx, {object=self.entity, max_hear_distance=4}, true)
		end;
		suitPowerStateSet = function(self, state, silent)
			-- necessary to enable reacting to power state changes
			-- e.g. to play sound effects, display warnings
			local os
			self:forSuit(function(s)
				os=s:powerState()
................................................................................
				return true
			end
			return false
		end;

		alarm = function(self, urgency, kind, minFreq)
			minFreq = minFreq or 1.5
			local time = core.get_gametime()
			local led = leds[kind]

			local ul = self.hud.led.map[kind]
			if ul then
				if time - ul.origin > minFreq then
					ul.origin = time
				else return end
................................................................................

		--[[
			freq = freq or 3
			local urgencies = {
				[1] = {sound = 'starlit-alarm'};
				[2] = {sound = 'starlit-alarm-urgent'};
			}
		   local gt = core.get_gametime()
		   local urg = urgencies[urgency] or urgencies[#urgencies]

		   if gt - self.cooldownTimes.alarm < freq then return end

		   self.cooldownTimes.alarm = gt
		   self:suitSound(urg.sound)

................................................................................
			   }
			   elt.ofs.x = elt.ofs.x + where.ofs.x
			   elt.ofs.y = elt.ofs.y + where.ofs.y
			   local attached = self:attachImage(elt)
				table.insert(self.hud.alarm, attached)

			   -- HATE. HATE. HAAAAAAAAAAATE
			   core.after(freq/2, function()
				   for k,v in pairs(self.hud.alarm) do
					   self.entity:hud_remove(v.id)
				   end
				   self.hud.alarm={}
			   end)
		   end]]
	   end;
................................................................................
		---------------
		-- inventory --
		---------------
		give = function(self, item)
			item = ItemStack(item)
			local inv = self.entity:get_inventory()
			local function is(grp)
				return core.get_item_group(item:get_name(), grp) ~= 0
			end
			-- TODO notif popups
			if is 'specialInventory' then
			--[[
				if is 'powder' then
					if self:naked() then return item end
					local cans = inv:get_list 'starlit_suit_canisters'
................................................................................
			else
				return inv:add_item('main', item)
			end
		end;
		thrustUpon = function(self, item)
			local r = self:give(st)
			if not r:is_empty() then
				return core.add_item(self.entity:get_pos(), r)
			end
		end;
		consume = function(self, stack, n)
			n = n or 1
			if n == 0 then n = stack:get_count() end
			local fd = stack:take_item(n)
			local stats = starlit.world.food.effectiveStats(fd)
................................................................................
				u:statDelta('health', -5*biointerval)
			end

			if water == 0 then -- dying of thirst
				u:statDelta('health', -20*biointerval)
			end

			if sp < 1.0 and core.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 'numinaRegen'
			u:statDelta('numina', pr * penaltyFromFatigue * mp)
................................................................................
	manv = 0x020;
	snk  = 0x040;
	dig  = 0x080;
	put  = 0x100;
	zoom = 0x200;
}
-- this is the painful part
core.register_globalstep(function(delta)
	local doNothing,mustInit,mustHalt = 0,1,2
	for id, user in pairs(starlit.activeUsers) do
		local ent = user.entity
		local bits = ent:get_player_control_bits()

		local function what(b)
			if bit.band(bits, b) ~= 0 and bit.band(user.action.bits, b) == 0 then