starlit  Check-in [cade6683f7]

Overview
Comment:add sprint, improve bio job, rebalance stamina regen, various fixes
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: cade6683f70db136391f34c5e60f9f814155147ceabd8900b026116fa94b97e4
User & Date: lexi on 2024-05-03 00:10:09
Other Links: manifest | tags
Context
2024-05-03
13:40
ui latency/performance improvements, bugfixes check-in: f1e68eb97e user: lexi tags: trunk
00:10
add sprint, improve bio job, rebalance stamina regen, various fixes check-in: cade6683f7 user: lexi tags: trunk
2024-05-02
20:27
check in missing mod, add forest biome, racial powers, overlays (untested) check-in: 6deb9bedbc user: lexi tags: trunk
Changes

Modified mods/starlit-eco/init.lua from [ffe9d8ff5f] to [0a9075eccb].

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
..
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65











































66
67
68
69
70
71
72
	seasonalTemp = {-50, -10, 5, 5, -20, -50};
	def = {
		node_top      = 'starlit:greengraze', depth_top = 1;
		node_filler   = 'starlit:soil',    depth_filler = 4;
		node_riverbed = 'starlit:sand',  depth_riverbed = 4;
		y_min = 0;
		y_max = 512;
		heat_point = 10;
		humidity_point = 30;
	};
})

world.ecology.biomes.link('starlit:forest', {
	nightTempDelta = -20;
	waterTempDelta = 0;
	--               W    Sp   Su    Au   W
	seasonalTemp = {-40, -8, 10, 10, -14, -40};
	def = {
		node_top      = 'starlit:greengraze', depth_top = 1;
		node_filler   = 'starlit:soil',    depth_filler = 4;
		node_riverbed = 'starlit:sand',  depth_riverbed = 4;
		y_min = -100;
		y_max = 256;
		heat_point = 13;
		humidity_point = 40;
	};
})

world.ecology.biomes.link('starlit:desert', {
	nightTempDelta = -40;
	waterTempDelta = 0;
................................................................................
	seasonalTemp = {-10, -5, 15, 15, -5, -10};
	def = {
		node_top      = 'starlit:sand',  depth_top = 1;
		node_filler   = 'starlit:sand',  depth_filler = 4;
		node_riverbed = 'starlit:sand',  depth_riverbed = 4;
		y_min = 0;
		y_max = 512;
		heat_point = 20;
		humidity_point = 10;
	};
})

world.ecology.biomes.link('starlit:ocean', {
	nightTempDelta = -35;
	waterTempDelta = 5;
	seasonalTemp = {0}; -- no seasonal variance
	def = {
		y_max = 3;
		y_min = -512;
		heat_point = 15;
		humidity_point = 50;
		node_top    = 'starlit:sand', depth_top    = 1;
		node_filler = 'starlit:sand', depth_filler = 3;
	};
})












































minetest.register_craftitem('starlit_eco:fiber', {
	description = "Plant Fiber";
	groups = {fiber = 1};
	inventory_image = lib.image('starlit-eco-plant-fiber.png'):shift(lib.color(0,1,0)):render();
	_starlit = {
		recover_vary = function(rng, ctx)
			return starlit.type.fab {







|
|












|

|







 







|











|
|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
..
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
	seasonalTemp = {-50, -10, 5, 5, -20, -50};
	def = {
		node_top      = 'starlit:greengraze', depth_top = 1;
		node_filler   = 'starlit:soil',    depth_filler = 4;
		node_riverbed = 'starlit:sand',  depth_riverbed = 4;
		y_min = 0;
		y_max = 512;
		heat_point = 20;
		humidity_point = 35;
	};
})

world.ecology.biomes.link('starlit:forest', {
	nightTempDelta = -20;
	waterTempDelta = 0;
	--               W    Sp   Su    Au   W
	seasonalTemp = {-40, -8, 10, 10, -14, -40};
	def = {
		node_top      = 'starlit:greengraze', depth_top = 1;
		node_filler   = 'starlit:soil',    depth_filler = 4;
		node_riverbed = 'starlit:sand',  depth_riverbed = 4;
		y_min = 0;
		y_max = 256;
		heat_point = 50;
		humidity_point = 40;
	};
})

world.ecology.biomes.link('starlit:desert', {
	nightTempDelta = -40;
	waterTempDelta = 0;
................................................................................
	seasonalTemp = {-10, -5, 15, 15, -5, -10};
	def = {
		node_top      = 'starlit:sand',  depth_top = 1;
		node_filler   = 'starlit:sand',  depth_filler = 4;
		node_riverbed = 'starlit:sand',  depth_riverbed = 4;
		y_min = 0;
		y_max = 512;
		heat_point = 70;
		humidity_point = 10;
	};
})

world.ecology.biomes.link('starlit:ocean', {
	nightTempDelta = -35;
	waterTempDelta = 5;
	seasonalTemp = {0}; -- no seasonal variance
	def = {
		y_max = 3;
		y_min = -512;
		heat_point = 50;
		humidity_point = 70;
		node_top    = 'starlit:sand', depth_top    = 1;
		node_filler = 'starlit:sand', depth_filler = 3;
	};
})

world.ecology.biomes.link('starlit:shiverdeep', {
	nightTempDelta = -25;
	waterTempDelta = 5;
	--               W    Sp  Su   Au   W
	seasonalTemp = {-70, -30, 0,  -60, -70};
	def = {
		y_max = 70;
		y_min = 1;
		heat_point = 0;
		humidity_point = 5;
		node_water_top = 'starlit:ice', depth_water_top = 1;
		node_top    = 'starlit:undergloam', depth_top    = 1;
		node_filler = 'starlit:soil',       depth_filler = 2;
	};
})

world.ecology.biomes.link('starlit:silthaven', {
	nightTempDelta = -5;
	waterTempDelta = 5;
	--               W  Sp  Su   Au   W
	seasonalTemp = {-15, 5, 15,  7, -15};
	def = {
		y_max = 30;
		y_min = 0;
		heat_point = 15;
		humidity_point = 35;
-- 		node_top    = 'starlit:undergloam', depth_top    = 1;
		node_filler = 'starlit:lifesilt',       depth_filler = 5;
	};
})

world.ecology.biomes.link('starlit:barrens', {
	nightTempDelta = -20;
	waterTempDelta = 5;
	--                 W  Sp  Su   Au   W
	seasonalTemp = {-30, -20, 0,  -20, -30};
	def = {
		y_max = 512;
		y_min = 0;
		heat_point = 0;
		humidity_point = 0;
	};
})
minetest.register_craftitem('starlit_eco:fiber', {
	description = "Plant Fiber";
	groups = {fiber = 1};
	inventory_image = lib.image('starlit-eco-plant-fiber.png'):shift(lib.color(0,1,0)):render();
	_starlit = {
		recover_vary = function(rng, ctx)
			return starlit.type.fab {

Modified mods/starlit-eco/plants.lua from [e9756bfa75] to [f0b6b474f2].

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
	color = lib.color(.5, .7, 1);
	biolum = 5;
	leaf = {
		color = lib.color(.6, .8, .8);
		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 Thousand Petal's great delicacies";
		color = lib.color(1,0,.4);
		nourish = 10;
		hydrate = 0.05;
		taste = 1 * 60;
		mass = 1;
	};
	decoration = {
................................................................................
		color = lib.color(.7, .4, .8);
		drop = simpleDrop(2, 'starlit_eco:dustrose_petal');
	};
	decoration = {
		place_on = 'starlit:greengraze';
		fill_ratio = 0.03;
		biomes = {'starlit:forest'};
		y_min = -50;
		y_max = 50;
	};
}

stalkPlantAuto {
	id = 'starlit_eco:harrowstalk';
	name = "Harrowstalk";
	fiber = simpleDrop(2, 'starlit_eco:fiber');
	seed = {};
	color = lib.color(.3, .2, .1);
	decoration = {
		place_on = 'starlit:sand';
		fill_ratio = 0.03;
		biomes = {'starlit:ocean', 'starlit:desert'};
		y_min = -30;
		y_max = 400;
	};
}







|







 







|













|
|



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
	color = lib.color(.5, .7, 1);
	biolum = 5;
	leaf = {
		color = lib.color(.6, .8, .8);
		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;
	};
	decoration = {
................................................................................
		color = lib.color(.7, .4, .8);
		drop = simpleDrop(2, 'starlit_eco:dustrose_petal');
	};
	decoration = {
		place_on = 'starlit:greengraze';
		fill_ratio = 0.03;
		biomes = {'starlit:forest'};
		y_min = 0;
		y_max = 50;
	};
}

stalkPlantAuto {
	id = 'starlit_eco:harrowstalk';
	name = "Harrowstalk";
	fiber = simpleDrop(2, 'starlit_eco:fiber');
	seed = {};
	color = lib.color(.3, .2, .1);
	decoration = {
		place_on = 'starlit:sand';
		fill_ratio = 0.03;
		biomes = {'starlit:desert'};
		y_min = 0;
		y_max = 400;
	};
}

Modified mods/starlit-eco/trees.lua from [49c5f4ea72] to [9fe2b3bf5d].

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
			thin_branches = true;

			fruit = 'starlit_eco:lambent_pine_bulb';
			fruit_chance = 0;
		};
		decorate = {
			{ biomes = {'starlit:forest'};
				place_on = 'starlit:greengraze';
				fill_ratio = 0.004;
				y_min = -30, y_max = 500;
				seed = 0xe8190e;
			};
			{ biomes = {'starlit:steppe'};
				place_on = 'starlit:greengraze';
				fill_ratio = 0.002;
				y_min = -30, y_max = 500;
				seed = 0xe8190e;
			};
		};
	};

	['starlit_eco:starblossom'] = {
		def = {
................................................................................
			iterations = 13;
			random_level = 5;
		};
		decorate = {
			{ biomes = {'starlit:forest'};
				place_on = 'starlit:greengraze';
				fill_ratio = 0.001;
				y_min = -20, y_max = 512;
			};
		};
	};
}

minetest.register_abm {
	label = "lambent pine fruiting";







|

|



|

|







 







|







171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
			thin_branches = true;

			fruit = 'starlit_eco:lambent_pine_bulb';
			fruit_chance = 0;
		};
		decorate = {
			{ biomes = {'starlit:forest'};
				place_on = {'starlit:greengraze'};
				fill_ratio = 0.004;
				y_min = 0, y_max = 500;
				seed = 0xe8190e;
			};
			{ biomes = {'starlit:steppe'};
				place_on = {'starlit:greengraze'};
				fill_ratio = 0.002;
				y_min = 0, y_max = 500;
				seed = 0xe8190e;
			};
		};
	};

	['starlit_eco:starblossom'] = {
		def = {
................................................................................
			iterations = 13;
			random_level = 5;
		};
		decorate = {
			{ biomes = {'starlit:forest'};
				place_on = 'starlit:greengraze';
				fill_ratio = 0.001;
				y_min = 0, y_max = 512;
			};
		};
	};
}

minetest.register_abm {
	label = "lambent pine fruiting";

Modified mods/starlit/species.lua from [1469667980] to [7816834c67].

19
20
21
22
23
24
25


































26
27
28
29
30
31
32
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
	sprint = {
		id = 'sprint';
		name = 'Sprint';
		desc = 'Put on a short burst of speed at the cost of some stamina';
		img = 'starlit-ui-icon-ability-sprint.png';
		powerKind = 'maneuver';
		run = function(user, ctx)


































		end;
	};
}

local species = {
	human = {
		name = 'Human';
................................................................................
				end;
				stats = {
					psiRegen = 1.3;
					psiPower = 1.2;
					psi = 1.2;
					nutrition = .8; -- women have smaller stomachs
					hydration = .8;
					staminaRegen = 1.0;
					morale = 0.8; -- you are not She-Bear Grylls
				};
				traits = {
					health = 400;
					lungCapacity = .6;
					irradiation = 0.8; -- you are smaller, so it takes less rads to kill ya
					sturdiness = 0; -- women are more fragile and thus susceptible to blunt force trauma
					metabolism = .150; -- kCal/s
					painTolerance = 0.4;
					dehydration = 10e-4; -- L/s
					speed = 1.1;

				};
			};
			male = {
				name = 'Human Male';
				eyeHeight = 1.6;
				stats = {
					psiRegen = 1.0;
					psiPower = 1.0;
					psi = 1.0;
					nutrition = 1.0;
					hydration = 1.0;
					staminaRegen = .7; -- men are strong but have inferior endurance
				};
				traits = {
					health = 500;
					painTolerance = 1.0;
					lungCapacity = 1.0;
					sturdiness = 0.3;
					metabolism = .150; -- kCal/s







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<











>











|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
..
93
94
95
96
97
98
99

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
	sprint = {
		id = 'sprint';
		name = 'Sprint';
		desc = 'Put on a short burst of speed at the cost of some stamina';
		img = 'starlit-ui-icon-ability-sprint.png';
		powerKind = 'maneuver';
		run = function(user, ctx)
			local cost = 10
			-- unfortunately stat writes are very expensive, so can't draw from stamina
			-- every single frame
			local function halt()
				if user.action.prog.sprint then
					user:statDelta('stamina', -user.action.prog.sprint.cb)
					user:deleteOverlay(user.action.prog.sprint.id)
					user.action.prog.sprint = nil
				end
			end

			if ctx.how.state == 'init' then
				halt()
				if user:effectiveStat 'stamina' > 0 then
					user.action.prog.sprint = {
						cb = 0;
						id = user:overlay(function(phys) phys.speed = phys.speed * 2 end)
					}
				end
			elseif ctx.how.state == 'prog' then
				local d = ctx.how.delta
				local p = user.action.prog.sprint
				-- is the player currently holding any of WASD
				local isMoving = bit.band(0x0f, user.entity:get_player_control_bits()) ~= 0
				if p and isMoving then
					p.cb = p.cb + cost*d
					if p.cb >= 10 then
						user:statDelta('stamina', -10)
						if user:effectiveStat 'stamina' < 10 then halt() end
					end
				end
			elseif ctx.how.state == 'halt' then
				halt()
			end
		end;
	};
}

local species = {
	human = {
		name = 'Human';
................................................................................
				end;
				stats = {
					psiRegen = 1.3;
					psiPower = 1.2;
					psi = 1.2;
					nutrition = .8; -- women have smaller stomachs
					hydration = .8;

					morale = 0.8; -- you are not She-Bear Grylls
				};
				traits = {
					health = 400;
					lungCapacity = .6;
					irradiation = 0.8; -- you are smaller, so it takes less rads to kill ya
					sturdiness = 0; -- women are more fragile and thus susceptible to blunt force trauma
					metabolism = .150; -- kCal/s
					painTolerance = 0.4;
					dehydration = 10e-4; -- L/s
					speed = 1.1;
					staminaRegen = 30.0;
				};
			};
			male = {
				name = 'Human Male';
				eyeHeight = 1.6;
				stats = {
					psiRegen = 1.0;
					psiPower = 1.0;
					psi = 1.0;
					nutrition = 1.0;
					hydration = 1.0;
					staminaRegen = 20; -- men are strong but have inferior endurance
				};
				traits = {
					health = 500;
					painTolerance = 1.0;
					lungCapacity = 1.0;
					sturdiness = 0.3;
					metabolism = .150; -- kCal/s

Modified mods/starlit/stats.lua from [93739694fe] to [0892085f88].

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
starlit.world.stats = {
	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 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 is measured in minutes one needs to sleep to cure it
	stamina    = {min = 0, max = 20 * 100, 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};
	-- 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};
	-- 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 is measured in minutes. e.g. at base rate morale degrades by







|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
starlit.world.stats = {
	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 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 is measured in minutes one needs to sleep to cure it
	stamina    = {min = 0, max = 40 * 100, 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};
	-- 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};
	-- 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 is measured in minutes. e.g. at base rate morale degrades by

Modified mods/starlit/terrain.lua from [43f9137bd9] to [4e1556f916].

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53













54
55
56
57
58
59
60
...
105
106
107
108
109
110
111











112
113
114
115
116
117
118
119
120
121
122
123
124
...
164
165
166
167
168
169
170
171





172
173
174
175
176


177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199


200
201
202
203
204
205
206
207
208
209
210
211
212

213
214
215
216

217















218
219




220



221
222
223
224
225
226
227
	};
})


minetest.register_node('starlit:sand', {
	description = T 'Sand';
	tiles = {'starlit-terrain-sand.png'};
	groups = {looseClump = 1, sand  = 1};
	drop = '';
	sounds = sandSounds;
	_starlit = {
		kind = 'block';
		fab = starlit.type.fab { element = { silicon = 25 } };
	};
})













minetest.register_craftitem('starlit:soil_clump', {
	short_description = T 'Soil';
	description = starlit.ui.tooltip {
		title = T 'Soil';
		desc = 'A handful of nutrient-packed soil, suitable for growing plants';
		color = lib.color(0.3,0.2,0.1);
	};
................................................................................


starlit.terrain.createGrass {
	name = 'starlit:greengraze';
	desc = T 'Greengraze';
	img = 'starlit-terrain-greengraze';
	fab = starlit.type.fab {











		element = {
			carbon = 12;
		};
		time = {
			shred = 2.5;
		};
	};
}

for _, w in pairs {false,true} do
	minetest.register_node('starlit:liquid_water' .. (w and '_flowing' or ''), {
		description = T 'Water';
		drawtype = 'liquid';
................................................................................
end


starlit.world.mineral.foreach('starlit:mineral_generate', {}, function(name,m)
	local node = string.format('starlit:mineral_%s', name)
	local grp = {mineral = 1}
	minetest.register_node(node, {
		description = m.desc;





		tiles = m.tiles or 
				(m.tone and {
					string.format('default_stone.png^[colorizehsl:%s:%s:%s',
						m.tone.hue, m.tone.sat, m.tone.lum)
				}) or {'default_stone.png'};


		groups = grp;
		drop = m.rocks or '';
		sounds = hardSounds;
		_starlit = {
			kind = 'block';
			elements = m.elements;
			fab = m.fab;
			recover = m.recover;
			recover_vary = m.recover_vary;
		};
	})
	if not m.excludeOre then
		local seed = 0
		grp.ore = 1
		for i = 1, #m.name do
			seed = seed*50 + string.byte(name, i)
		end
		minetest.register_ore {
			ore = node;
			ore_type = m.dist.kind;
			wherein = {m.dist.among};
			clust_scarcity = m.dist.rare;
			y_max = m.dist.height[1], y_min = m.dist.height[2];


			noise_params = m.dist.noise or {
				offset = 28;
				scale = 16;
				spread = vector.new(128,128,128);
				seed = seed;
				octaves = 1;
			};
		}
	end
end)

starlit.world.mineral.link('feldspar', {
	desc = T 'Feldspar';

	excludeOre = true;
	recover = starlit.type.fab {
		time = {
			shred = 3;

		};















		cost = {
			shredPower = 3;




		};



	};
	recover_vary = function(rng, ctx)
		-- print('vary!', rng:int(), rng:int(0,10))
		return starlit.type.fab {
			element = {
				aluminum  = rng:int(0,4);
				potassium = rng:int(0,2);







|







>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>



<
|
<







 







|
>
>
>
>
>


<
<
<
>
>













|

|




|


>
>

<
|


|






|
>


<
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
>
>
>
>
|
>
>
>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

139

140
141
142
143
144
145
146
...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228

229
230
231
232
233
234
235
236
237
238
239
240
241
242

243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261

262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
	};
})


minetest.register_node('starlit:sand', {
	description = T 'Sand';
	tiles = {'starlit-terrain-sand.png'};
	groups = {looseClump = 1, sand = 1, falling_node = 1};
	drop = '';
	sounds = sandSounds;
	_starlit = {
		kind = 'block';
		fab = starlit.type.fab { element = { silicon = 25 } };
	};
})

minetest.register_node('starlit:lifesilt', {
	description = T 'Lifesilt';
	tiles = {'starlit-terrain-lifesilt.png'};
	groups = {looseClump = 1, lifesilt = 1, falling_node = 1};
	drop = '';
	sounds = sandSounds;
	_starlit = {
		kind = 'block';
		fab = starlit.type.fab { element = { carbon = 8, silicon = 4 } };
	};
})

minetest.register_craftitem('starlit:soil_clump', {
	short_description = T 'Soil';
	description = starlit.ui.tooltip {
		title = T 'Soil';
		desc = 'A handful of nutrient-packed soil, suitable for growing plants';
		color = lib.color(0.3,0.2,0.1);
	};
................................................................................


starlit.terrain.createGrass {
	name = 'starlit:greengraze';
	desc = T 'Greengraze';
	img = 'starlit-terrain-greengraze';
	fab = starlit.type.fab {
		element = { carbon = 12; };
		time = { shred = 2.5; };
	};
}

starlit.terrain.createGrass {
	name = 'starlit:undergloam';
	desc = T 'Undergloam';
	-- fungal carpet
	img = 'starlit-terrain-undergloam';
	fab = starlit.type.fab {
		element = {
			carbon = 12;
		};

		time = { shred = 2.5; };

	};
}

for _, w in pairs {false,true} do
	minetest.register_node('starlit:liquid_water' .. (w and '_flowing' or ''), {
		description = T 'Water';
		drawtype = 'liquid';
................................................................................
end


starlit.world.mineral.foreach('starlit:mineral_generate', {}, function(name,m)
	local node = string.format('starlit:mineral_%s', name)
	local grp = {mineral = 1}
	minetest.register_node(node, {
		short_description = m.name;
		description = starlit.ui.tooltip {
			title = m.name;
			desc = m.desc;
			color = m.tone;
		};
		tiles = m.tiles or 
				(m.tone and {



					lib.image'starlit-terrain-granite.png':shift(m.tone):render()
				}) or nil;
		groups = grp;
		drop = m.rocks or '';
		sounds = hardSounds;
		_starlit = {
			kind = 'block';
			elements = m.elements;
			fab = m.fab;
			recover = m.recover;
			recover_vary = m.recover_vary;
		};
	})
	if not m.excludeOre then
		local seed = 0
-- 		grp.ore = 1
		for i = 1, #m.name do
			seed = seed*50 + string.byte(m.name, i)
		end
		minetest.register_ore {
			ore = node;
			ore_type = m.dist.kind;
			wherein = m.dist.among;
			clust_scarcity = m.dist.rare;
			y_max = m.dist.height[1], y_min = m.dist.height[2];
			column_height_min = m.dist.sheetCols and m.dist.sheetCols[1] or nil;
			column_height_max = m.dist.sheetCols and m.dist.sheetCols[2] or nil;
			noise_params = m.dist.noise or {

				scale = 1;
				spread = vector.new(128,128,128);
				seed = seed;
				octaves = 2;
			};
		}
	end
end)

starlit.world.mineral.link('feldspar', {
	name = T 'Feldspar';
	tiles = {'starlit-terrain-feldspar.png'};
	excludeOre = true;
	recover = starlit.type.fab {

		time = { shred = 3; };
		cost = { shredPower = 3; };
	};
	recover_vary = function(rng, ctx)
		-- print('vary!', rng:int(), rng:int(0,10))
		return starlit.type.fab {
			element = {
				aluminum  = rng:int(0,4);
				potassium = rng:int(0,2);
				calcium   = rng:int(0,2);
			}
		};
	end;
})

starlit.world.mineral.link('granite', {
	name = T 'Granite';
	tiles = {'starlit-terrain-granite.png'};
	dist = {

		kind = 'sheet';
		among = 'starlit:feldspar';
		height = {-200,30};
		sheetCols = {1, 16};
	};
	recover = starlit.type.fab {
		time = { shred = 4; };
		cost = { shredPower = 8; };
	};
	recover_vary = function(rng, ctx)
		-- print('vary!', rng:int(), rng:int(0,10))
		return starlit.type.fab {
			element = {
				aluminum  = rng:int(0,4);
				potassium = rng:int(0,2);

Modified mods/starlit/user.lua from [910641ec39] to [e60d6be4a9].

907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940


941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973


974
975
976
977
978
979
980
			local stats = starlit.world.food.effectiveStats(fd)

			return stack
		end;
	};
}

local biointerval = 3.0
starlit.startJob('starlit:bio', biointerval, function(delta)
	for id, u in pairs(starlit.activeUsers) do
		local p = u.pheno
		local bmr = p:trait 'metabolism' * biointerval
		-- TODO apply modifiers

		local dehydration = p:trait 'dehydration' * biointerval
		-- you dehydrate faster in higher temp
		dehydration = dehydration * math.max(1, starlit.world.climate.temp(u.entity:get_pos()) / 10)

		u:statDelta('nutrition', -bmr)
		u:statDelta('hydration', -dehydration)

		local moralePenalty = -1 -- 1min/min
		local fatiguePenalty = 1 -- 1min/min
		local heatPenalty = 1 -- stamina regen is divided by this

		do local warmth = u:effectiveStat 'warmth'
			local tempRange = u:species().tempRange
			local tComfMin, tComfMax = tempRange.comfort[1], tempRange.comfort[2]
			local tempDiff = 0
			if warmth < tComfMin then
				tempDiff = math.abs(warmth-tComfMin)
			elseif warmth > tComfMax then
				tempDiff = math.abs(warmth-tComfMax)
			end


			moralePenalty = moralePenalty + tempDiff
			heatPenalty = heatPenalty + tempDiff
		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

		if rads > 0 then
			u:statDelta('irradiation', -0.0001 * biointerval)
			local moraleDrainFac = 2^(rads / 2)
			moralePenalty = moralePenalty * moraleDrainFac
		end

		u:statDelta('morale', moralePenalty * biointerval)
		u:statDelta('fatigue', fatiguePenalty * biointerval)

		if food == 0 then -- starvation
			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:effectiveStat 'staminaRegen' / heatPenalty)


		end
	end
end)

local cbit = {
	up   = 0x001;
	down = 0x002;







|


|
|
|

|
|
|

|
|

|
|
|

|
|
|
|
|
|
|
|
|
>
>
|
|
|

|
|
|

|
|
|
|
|

|
|
|
|
|

|
|

|
|
|

|
|
|

|
|
>
>







907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
			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 dehydration = u:phenoTrait 'dehydration' * biointerval
			-- you dehydrate faster in higher temp
			dehydration = dehydration * math.max(1, starlit.world.climate.temp(u.entity:get_pos()) / 10)

			u:statDelta('nutrition', -bmr)
			u:statDelta('hydration', -dehydration)

			local moralePenalty = -1 -- 1min/min
			local fatiguePenalty = 1 -- 1min/min
			local heatPenalty = 1 -- stamina regen is divided by this

			do local warmth = u:effectiveStat 'warmth'
				local tempRange = u:species().tempRange
				local tComfMin, tComfMax = tempRange.comfort[1], tempRange.comfort[2]
				local tempDiff = 0
				if warmth < tComfMin then
					tempDiff = tComfMin - warmth
				elseif warmth > tComfMax then
					tempDiff = warmth-tComfMax
				end
-- 				print('tempDiff', tComfMin, tComfMax, tempDiff)
				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

			if rads > 0 then
				u:statDelta('irradiation', -0.0001 * biointerval)
				local moraleDrainFac = 2^(rads / 2)
				moralePenalty = moralePenalty * moraleDrainFac
			end

			u:statDelta('morale', moralePenalty * biointerval)
			u:statDelta('fatigue', fatiguePenalty * biointerval)

			if food == 0 then -- starvation
				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;

Modified mods/starlit/world.lua from [cdaabd4e00] to [d79dc9efc2].

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
..
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33

34
35

36
37
38

39
40
41

42
43
44
45
46
47
48

function world.date()
	local days = minetest.get_day_count()
	local year = math.floor(days / world.planet.orbit);
	local day = days % world.planet.orbit;
	return {
		year = year, day = day;
		season = day / world.planet.orbit;
	}
end
local lerp = lib.math.lerp

local function gradient(grad, pos)
	local n = #grad
	if n == 1 then return grad[1] end
................................................................................
	local op = pos*(n-1)
	local idx = math.floor(op)
	local t = op-idx
	return lerp(t, grad[1 + idx], grad[2 + idx])
end

local altitudeCooling = 10 / 100


-- this function provides the basis for temperature calculation,
-- which is performed by adding this value to the ambient temperature,
-- determined by querying nearby group:heatSource items in accordance
-- with the inverse-square law
function world.climate.eval(pos, tod, season)
	local data = minetest.get_biome_data(pos)
	local biome = world.ecology.biomes.db[minetest.get_biome_name(data.biome)]
	local heat, humid = data.heat, data.humidity

	tod = tod or minetest.get_timeofday()
	heat = lerp(math.abs(tod - 0.5)*2, heat, heat + biome.nightTempDelta)


	local td = world.date()
	heat = heat + gradient(biome.seasonalTemp, season or td.season)

	if pos.y > 0 then
		heat = heat - pos.y*altitudeCooling 
	end


	return {
		surfaceTemp = heat;
		waterTemp = heat + biome.waterTempDelta;
		surfaceHumid = humid;
	}
end







|







 







>









>


>



>



>







3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
..
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

function world.date()
	local days = minetest.get_day_count()
	local year = math.floor(days / world.planet.orbit);
	local day = days % world.planet.orbit;
	return {
		year = year, day = day;
		season = day / world.planet.orbit + 0.5; -- begin summer
	}
end
local lerp = lib.math.lerp

local function gradient(grad, pos)
	local n = #grad
	if n == 1 then return grad[1] end
................................................................................
	local op = pos*(n-1)
	local idx = math.floor(op)
	local t = op-idx
	return lerp(t, grad[1 + idx], grad[2 + idx])
end

local altitudeCooling = 10 / 100
local heatRange = {min = -70, max = 70} -- translate mt temps into real temps

-- this function provides the basis for temperature calculation,
-- which is performed by adding this value to the ambient temperature,
-- determined by querying nearby group:heatSource items in accordance
-- with the inverse-square law
function world.climate.eval(pos, tod, season)
	local data = minetest.get_biome_data(pos)
	local biome = world.ecology.biomes.db[minetest.get_biome_name(data.biome)]
	local heat, humid = data.heat, data.humidity
	heat = lerp(heat/100, heatRange.min, heatRange.max)
	tod = tod or minetest.get_timeofday()
	heat = lerp(math.abs(tod - 0.5)*2, heat, heat + biome.nightTempDelta)
-- 	print('base heat', heat)

	local td = world.date()
	heat = heat + gradient(biome.seasonalTemp, season or td.season)
-- 	print('seasonal heat', heat)
	if pos.y > 0 then
		heat = heat - pos.y*altitudeCooling 
	end
-- 	print('altitude heat', heat)

	return {
		surfaceTemp = heat;
		waterTemp = heat + biome.waterTempDelta;
		surfaceHumid = humid;
	}
end

Modified starlit.ct from [990b095f3f] to [415d01ad10].

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

### shadows
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.

## gameplay
the most important thing to understand about starlit is that is is [*mean], by design.

* 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. Thousand Petal doesn't care about your feelings.
* 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. 

starlit is somewhat unusual in how it uses the minetest engine. it's a voxel game but not of the minecraft variety.

### controls
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.








|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

### shadows
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.

## gameplay
the most important thing to understand about starlit is that is is [*mean], by design.

* 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.
* 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. 

starlit is somewhat unusual in how it uses the minetest engine. it's a voxel game but not of the minecraft variety.

### controls
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.