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
|