sorcery  Diff

Differences From Artifact [c21bb1a7ca]:

To Artifact [c1d9a4ce4b]:


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
..
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
116
117
118
119
120
121



122
123
124
125
126
127
128
...
134
135
136
137
138
139
140

141
142
143
144
145
146
147
...
163
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
228
229
230
231
232
...
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
...
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
...
345
346
347
348
349
350
351
352
353
354
355
356
	
	metal_grindvalue = 4;
	-- how many powders an ingot is worth

	default_grindvalue = 1;
	-- number of items produced when not otherwise
	-- specified




	
	default_hardness = 1;
	-- difficulty to grind an item when not otherwise
	-- specified

	metal_grindcost = 1;
	-- number of metal items needed to perform a grind
}
local mill_formspec_update = function(pos,pct,stat1,stat2)
	-- eventually we'll want to display available
	-- energy here, but for now we're just assuming
	-- max energy available

	-- local meta = minetest.get_meta(pos)
	-- local inv = meta:get_inventory()
	-- local torque = 20
	stat1 = stat1 or 'off'
	minetest.get_meta(pos):set_string('formspec', string.format([[
		size[8,7.2]
................................................................................
	if slot == 'grinder' then
		if minetest.get_item_group(item:get_name(), 'sorcery_mill_grindhead')~=0 
			then return 1 end
	elseif slot == 'input' then
		local metal = sorcery.data.metallookup[item:get_name()]
		local mat = sorcery.matreg.lookup[item:get_name()]
		local comp = sorcery.data.compat.grindables[item:get_name()]
		if metal or mat.metal or comp then
			return item:get_count()
		else
			local mat = item:get_definition()._matprop
			if mat and mat.grindvalue then
				return item:get_count() 
			end
		end
	end
	return 0
end
local matprops = function(item)
	local metal = sorcery.data.metallookup[item:get_name()]
	if not metal then
		-- allow grinding of armor and tools back to their
		-- original components
		local mat = sorcery.matreg.lookup[item:get_name()]
		if mat.metal then
			metal = mat
		else
			return nil
		end
	end
	local mp = item:get_definition()._matprop
		or sorcery.data.compat.grindables[item:get_name()]
		or {}

	again = true
	if metal then mp = {
		hardness = metal.data.hardness or mp.hardness or constants.default_hardness;
		grindvalue = metal.value or mp.grindvalue or (metal and constants.metal_grindvalue) or constants.default_grindvalue;
		powder = metal.data.parts.powder or mp.powder;
		grindcost = constants.metal_grindcost or mp.grindcost; -- invariant for metal
	} end

	mp.torque = constants.grind_torque_factor * mp.hardness




	if item:get_wear() ~= 0 then
		-- prevent cheating by recovering metal from items before they
		-- are destroyed
		local wearfac = (item:get_wear() / 65535)
		mp.grindvalue = math.max(1,math.ceil(mp.grindvalue * wearfac))
		mp.hardness = math.max(1,math.ceil(mp.grindcost * wearfac))
................................................................................
minetest.register_node('sorcery:mill',{
	description = 'Mill';
	groups = {
		cracky = 2;
		sorcery_ley_device = 1;
	};
	paramtype2 = 'facedir';

	on_construct = function(pos)
		local meta = minetest.get_meta(pos)
		local inv = meta:get_inventory()
		inv:set_size('input',1)
		inv:set_size('output',4)
		inv:set_size('grinder',2)
		meta:set_float('grindtime',0)
................................................................................
	on_metadata_inventory_move = function(pos,fl,fi,tl,ti)
		if fl == 'input' or tl == 'input' then
			minetest.get_meta(pos):set_float('grindtime',0)
		end
		mill_update(pos)
	end;
	_sorcery = {

		ley = { mode = 'consume'; affinity = {'praxic'}};
		on_leyconnect = mill_update;
		on_leycalc = function(pos,time)
			local meta = minetest.get_meta(pos)
			local active = meta:get_int('active') == 1
			if not active then return { power = 0; } end
			local inv = meta:get_inventory()
			local item = inv:get_stack('input',1)
			if item:is_empty() then
				meta:set_int('active', 0)
				return { power = 0; }
			end
			return {
				power = matprops(item).torque * time;

			}
		end;
	};
	on_timer = function(pos,delta)
		local meta = minetest.get_meta(pos)
		local inv = meta:get_inventory()
		local elapsed = meta:get_float('grindtime') + delta
		local ley = sorcery.ley.netcaps(pos,delta,pos)
		local again = false
		local active = false
		local reqtime -- sigh
		local statcolor = 'off'
		local grinders_on
		if inv:is_empty('input') or inv:is_empty('grinder') then
			print('empty')
			elapsed = 0
			mill_formspec_update(pos, 0)
		else
			local item = inv:get_stack('input',1)
			local mp = matprops(item)
			if mp.grindcost > item:get_count() then
				elapsed = 0
				mill_formspec_update(pos, 0)
				print('bad grindcost')
				goto stop
			end

			-- print('power supply',ley.maxpower)
			-- print('power available',ley.freepower)
			-- print('power needed',mp.torque*delta)
			if ley.maxpower < (mp.torque * delta) then
				-- not enough potential energy in the system to grind
				-- so don't bother
				print('not enough power')
				statcolor = 'red'
				elapsed = 0 goto stop
			elseif ley.freepower < (mp.torque * delta) then
				-- the net has enough potential energy to supply us,
				-- but too much of it is in use right now. give up
				-- on this round, but try again in a bit to see if
				-- more energy is available
				print('currently not enough power')
				statcolor = 'yellow'
				elapsed = 0 again = true goto stop
			end

			local grinders = 0
			local grindpower = 0
			local grind_wear = {}
................................................................................
					if dif == 0 then
						wear = constants.grind_wear
					elseif dif < 0 then
						wear = constants.grind_wear * ((dif * -1)/constants.grind_range)
					elseif dif > 0 then
						if dif > constants.grind_grace_range then
							wear = 0
							print('grinder reject')
							goto reject
						else
							wear = constants.grind_wear * (1 + (dif/constants.grind_range)) * constants.grind_grace_penalty
						end
					end
					::accept:: grinders = grinders + 1
					           grindpower = grindpower + hh
................................................................................
				if grindpower < mp.hardness then
					statcolor = 'yellow'
				else statcolor='green' end
				grindpower = grindpower / grinders
				-- if there is more power available than needed,
				-- and/or if the blades are stronger than needed,
				-- speed up the grind
				local speedboost = math.max(0.05,((grindpower - mp.hardness)/constants.grind_range) * grinders) * ((mp.torque * delta) / ley.freepower)
				reqtime = mp.grindvalue * mp.hardness * constants.grind_factor * (1-speedboost)
				if elapsed >= reqtime then
					item:take_item(mp.grindcost)
					inv:set_stack('input',1,item)
					local pw = ItemStack{
						name=mp.powder;
						count=mp.grindvalue;
................................................................................
			metal = name;
		};
	});
	minetest.register_craft {
		output = id;
		recipe = {
			{f,i,f};
			{i,i,i};
			{f,i,f};
		};
	}
end







>
>
>
>










|
<







 







|


|













|

<
<








|
|
|
|


|
>
>
>







 







>







 







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












<








<



<
<
<



<







<







 







<







 







|







 







|




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
..
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
...
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
...
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
228
229
230
...
240
241
242
243
244
245
246

247
248
249
250
251
252
253
...
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
...
342
343
344
345
346
347
348
349
350
351
352
353
	
	metal_grindvalue = 4;
	-- how many powders an ingot is worth

	default_grindvalue = 1;
	-- number of items produced when not otherwise
	-- specified

	default_grindcost = 1;
	-- number of items needed to perform a grind when
	-- not otherwise specified
	
	default_hardness = 1;
	-- difficulty to grind an item when not otherwise
	-- specified

	metal_grindcost = 1;
	-- number of metal items needed to perform a grind
}
local mill_formspec_update = function(pos,pct,stat1,stat2)
	-- eventually we'll want to display available
	-- energy here


	-- local meta = minetest.get_meta(pos)
	-- local inv = meta:get_inventory()
	-- local torque = 20
	stat1 = stat1 or 'off'
	minetest.get_meta(pos):set_string('formspec', string.format([[
		size[8,7.2]
................................................................................
	if slot == 'grinder' then
		if minetest.get_item_group(item:get_name(), 'sorcery_mill_grindhead')~=0 
			then return 1 end
	elseif slot == 'input' then
		local metal = sorcery.data.metallookup[item:get_name()]
		local mat = sorcery.matreg.lookup[item:get_name()]
		local comp = sorcery.data.compat.grindables[item:get_name()]
		if metal or (mat and mat.metal) or comp then
			return item:get_count()
		else
			mat = item:get_definition()._matprop
			if mat and mat.grindvalue then
				return item:get_count() 
			end
		end
	end
	return 0
end
local matprops = function(item)
	local metal = sorcery.data.metallookup[item:get_name()]
	if not metal then
		-- allow grinding of armor and tools back to their
		-- original components
		local mat = sorcery.matreg.lookup[item:get_name()]
		if mat and mat.metal then
			metal = mat


		end
	end
	local mp = item:get_definition()._matprop
		or sorcery.data.compat.grindables[item:get_name()]
		or {}

	again = true
	if metal then mp = {
		hardness = mp.hardness or metal.data.hardness;
		grindvalue = ((mp.grindvalue or metal.value) or (metal and constants.metal_grindvalue));
		powder = mp.powder or metal.data.parts.powder;
		grindcost = mp.grindcost or constants.metal_grindcost; -- invariant for metal
	} end

	mp.torque     = constants.grind_torque_factor * mp.hardness
	mp.grindvalue = mp.grindvalue or constants.default_grindvalue
	mp.grindcost  = mp.grindcost  or constants.default_grindcost
	mp.hardness   = mp.hardness   or constants.default_hardness;

	if item:get_wear() ~= 0 then
		-- prevent cheating by recovering metal from items before they
		-- are destroyed
		local wearfac = (item:get_wear() / 65535)
		mp.grindvalue = math.max(1,math.ceil(mp.grindvalue * wearfac))
		mp.hardness = math.max(1,math.ceil(mp.grindcost * wearfac))
................................................................................
minetest.register_node('sorcery:mill',{
	description = 'Mill';
	groups = {
		cracky = 2;
		sorcery_ley_device = 1;
	};
	paramtype2 = 'facedir';
	after_dig_node = sorcery.lib.node.purge_container;
	on_construct = function(pos)
		local meta = minetest.get_meta(pos)
		local inv = meta:get_inventory()
		inv:set_size('input',1)
		inv:set_size('output',4)
		inv:set_size('grinder',2)
		meta:set_float('grindtime',0)
................................................................................
	on_metadata_inventory_move = function(pos,fl,fi,tl,ti)
		if fl == 'input' or tl == 'input' then
			minetest.get_meta(pos):set_float('grindtime',0)
		end
		mill_update(pos)
	end;
	_sorcery = {
		ley = {
			mode = 'consume', affinity = {'praxic'};

			power = function(pos,time)
				local meta = minetest.get_meta(pos)
				local active = meta:get_int('active') == 1
				if not active then return 0 end
				local inv = meta:get_inventory()
				local item = inv:get_stack('input',1)
				if item:is_empty() then
					meta:set_int('active', 0)
					return 0
				end

				return matprops(item).torque * time;
			end;
		};
		on_leychange = mill_update;
	};
	on_timer = function(pos,delta)
		local meta = minetest.get_meta(pos)
		local inv = meta:get_inventory()
		local elapsed = meta:get_float('grindtime') + delta
		local ley = sorcery.ley.netcaps(pos,delta,pos)
		local again = false
		local active = false
		local reqtime -- sigh
		local statcolor = 'off'
		local grinders_on
		if inv:is_empty('input') or inv:is_empty('grinder') then

			elapsed = 0
			mill_formspec_update(pos, 0)
		else
			local item = inv:get_stack('input',1)
			local mp = matprops(item)
			if mp.grindcost > item:get_count() then
				elapsed = 0
				mill_formspec_update(pos, 0)

				goto stop
			end




			if ley.maxpower < (mp.torque * delta) then
				-- not enough potential energy in the system to grind
				-- so don't bother

				statcolor = 'red'
				elapsed = 0 goto stop
			elseif ley.freepower < (mp.torque * delta) then
				-- the net has enough potential energy to supply us,
				-- but too much of it is in use right now. give up
				-- on this round, but try again in a bit to see if
				-- more energy is available

				statcolor = 'yellow'
				elapsed = 0 again = true goto stop
			end

			local grinders = 0
			local grindpower = 0
			local grind_wear = {}
................................................................................
					if dif == 0 then
						wear = constants.grind_wear
					elseif dif < 0 then
						wear = constants.grind_wear * ((dif * -1)/constants.grind_range)
					elseif dif > 0 then
						if dif > constants.grind_grace_range then
							wear = 0

							goto reject
						else
							wear = constants.grind_wear * (1 + (dif/constants.grind_range)) * constants.grind_grace_penalty
						end
					end
					::accept:: grinders = grinders + 1
					           grindpower = grindpower + hh
................................................................................
				if grindpower < mp.hardness then
					statcolor = 'yellow'
				else statcolor='green' end
				grindpower = grindpower / grinders
				-- if there is more power available than needed,
				-- and/or if the blades are stronger than needed,
				-- speed up the grind
				local speedboost = math.max(0.05,((grindpower - mp.hardness)/constants.grind_range) * grinders)
				reqtime = mp.grindvalue * mp.hardness * constants.grind_factor * (1-speedboost)
				if elapsed >= reqtime then
					item:take_item(mp.grindcost)
					inv:set_stack('input',1,item)
					local pw = ItemStack{
						name=mp.powder;
						count=mp.grindvalue;
................................................................................
			metal = name;
		};
	});
	minetest.register_craft {
		output = id;
		recipe = {
			{f,i,f};
			{i,'',i};
			{f,i,f};
		};
	}
end