Differences From
Artifact [c4c14b0c08]:
- File
infuser.lua
— part of check-in
[147592b8e9]
at
2020-10-26 03:58:08
on branch trunk
— add over-time spellcasting abstraction to enable metamagic and in particular disjunction, add more animations and sound effects, add excavation spell, possibly some others, forget when the last commit was, edit a bunch of magitech to make it subject to the disjunction mechanism (throw up a disjunction aura and waltz right through those force fields bby, wheee), also illumination spells, tweak runeforge and rune frequence to better the balance and also limit player frustration, move some math functions into their own library category, various tweaks and bugfixes, probably other shit i don't remember
(user:
lexi,
size: 7825)
[annotate]
[blame]
[check-ins using]
1 -local infuser_formspec = function(percent)
1 +local log = sorcery.logger('infuser')
2 +
3 +local infuser_formspec = function(percent,active)
2 4 return string.format([[
3 5 size[8,7]
4 6 list[context;infusion;3.5,0;1,1;]
5 7 list[context;potions;2.5,1.7;1,1;0]
6 8 list[context;potions;3.5,2;1,1;1]
7 9 list[context;potions;4.5,1.7;1,1;2]
8 10 image[2.5,1.7;1,1;vessels_shelf_slot.png]
9 11 image[3.5,2;1,1;vessels_shelf_slot.png]
10 12 image[4.5,1.7;1,1;vessels_shelf_slot.png]
11 13 image[3.5,1;1,1;gui_furnace_arrow_bg.png^[lowpart:%d:gui_furnace_arrow_fg.png^[transformR180]
12 14 list[current_player;main;0,3.3;8,4;]
15 + animated_image[2.5,0;1,2;tube_l;sorcery_ui_infuse_tube.png;28;%s;28]
16 + animated_image[4.5,0;1,2;tube_l;sorcery_ui_infuse_tube.png^[transformFX;28;%s;28]
13 17 listring[context;infusion]
14 18 listring[current_player;main]
15 19 listring[context;potions]
16 20 listring[current_player;main]
17 21 listring[context;infusion]
18 - ]], percent)
22 + ]], percent,
23 + active and '71' or '0',
24 + active and '71' or '0')
19 25 end
20 26
21 27 local infuser_stop = function(pos)
22 28 local meta = minetest.get_meta(pos)
23 29 meta:set_float('runtime', 0)
24 30 meta:set_string('formspec', infuser_formspec(0))
25 31 meta:set_string('infotext', 'Infuser')
26 32 minetest.get_node_timer(pos):stop()
27 33 end
34 +sorcery.alchemy = {}
35 +
36 +sorcery.alchemy.is_module = function(name)
37 + local def = minetest.registered_nodes[name]
38 + if def and def._sorcery and def._sorcery.alchemy and def._sorcery.alchemy.module then
39 + return def._sorcery.alchemy.module
40 + else return nil end
41 +end
42 +
43 +local infuser_mods = function(pos)
44 + local getmod = function(pos)
45 + local st = sorcery.lib.node.force(pos)
46 + return sorcery.alchemy.is_module(st.name)
47 + end
48 +
49 + local st = sorcery.lib.node.force(pos)
50 + if st.name ~= 'sorcery:infuser' then return false end
51 + local devs = {}
52 +
53 + repeat
54 + pos = vector.offset(pos, 0, -1, 0)
55 + local mod = getmod(pos)
56 + if mod then
57 + if mod.attach == 'stack' then
58 + devs[#devs+1] = { pos = pos, mod = mod }
59 + if mod.stmod_connect then
60 + for _,ofs in pairs(mod.stmod_connect) do
61 + local wh = vector.add(pos,ofs)
62 + local stm = getmod(wh)
63 + if stm and stm.attach == 'stand' then
64 + -- TODO check facing correct direction
65 + devs[#devs+1] = {pos = wh, mod = stm}
66 + end
67 + end
68 + end
69 + if mod.endstack then break end
70 + else break end -- invalid attachment
71 + else break end
72 + until false
73 +
74 + local props = {}
75 +
76 + local comp = function(a,b) return function(...) return a(b(...)) end end
77 + local mult = function(a,b) return a * b end;
78 + local sum = function(a,b) return a + b end;
79 + local combine = {
80 + brewtime = mult;
81 + onbrew = function(a, b)
82 + return function(ctx)
83 + ctx.stack = b(ctx)
84 + return a(ctx)
85 + end
86 + end;
87 + }
88 +
89 + for _, d in pairs(devs) do
90 + for k,v in pairs(d.mod) do
91 + if combine[k] then
92 + if props[k]
93 + then props[k] = (combine[k])(v, props[k])
94 + else props[k] = v
95 + end
96 + end
97 + end
98 + end
99 +
100 + return props, devs
101 +end
28 102
29 103 local elixir_can_apply = function(elixir, potion)
30 104 -- accepts an elixir def and potion def
31 105 if elixir == nil or
32 - elixir._proto == nil or
33 106 potion == nil then return false end
34 107
35 - if elixir._proto.apply and potion.on_use then
108 + if elixir.apply and potion.on_use then
36 109 -- the ingredient is an elixir and at least one potion
37 110 -- is a fully enchanted, usable potion
38 - if elixir._proto.flag and potion._proto and
39 - potion._proto['no_' .. elixir._proto.flag] == true then
111 + if elixir.flag and potion._proto and
112 + potion._proto['no_' .. elixir.flag] == true then
40 113 -- does the elixir have a property used to denote
41 114 -- compatibility? if so, check the potion to see if it's
42 115 -- marked as incompatible
43 116 return false
44 117 else
45 118 return true
46 119 end
................................................................................
66 139 desc = desc;
67 140 affinity = aff;
68 141 }
69 142 end
70 143 ::skip::end
71 144 return tbl
72 145 end
146 +
147 +sorcery.alchemy.elixir_apply = function(elixir, potion)
148 + if not potion then return end
149 + local pdef = potion:get_definition()
150 + if elixir_can_apply(elixir, pdef) then
151 + elixir.apply(potion, pdef._proto)
152 + potion:get_meta():set_string('description', sorcery.lib.ui.tooltip {
153 + title = pdef._proto.name .. ' Draught';
154 + desc = pdef._proto.desc;
155 + color = sorcery.lib.color(pdef._proto.color):readable();
156 + props = effects_table(potion);
157 + });
158 + end
159 + return potion
160 +end
161 +
162 +sorcery.alchemy.infuse = function(infusion, potions)
163 + local ingredient = infusion:get_name()
164 + local creations = {}
165 + local brewed = false
166 + for i = 1,#potions do
167 + if potions[i]:is_empty() then goto skip end
168 + local base = potions[i]:get_name()
169 + local potion = potions[i]:get_definition()
170 + local elixir = infusion:get_definition()
171 + brewed = true
172 + if elixir_can_apply(elixir._proto, potion) then
173 + local newstack = sorcery.alchemy.elixir_apply(elixir._proto, potions[i])
174 + if newstack ~= nil then
175 + creations[i] = {
176 + output = newstack;
177 + elixir = elixir;
178 + enhance = true;
179 + }
180 + else return true end
181 + else
182 + for _,v in pairs(sorcery.register.infusions.db) do
183 + if v.infuse == ingredient and v.into == base then
184 + -- transform the base into the infusion
185 + local out = ItemStack(v.output)
186 + if out ~= nil then
187 + creations[i] = {
188 + recipe = v;
189 + output = out;
190 + proto = minetest.registered_items[v.output]._proto;
191 + brew = true;
192 + }
193 + else return true end
194 + end
195 + end
196 + end
197 + ::skip:: end
198 +
199 + local residue = ItemStack(sorcery.register.residue.db[ingredient])
200 + return creations, residue
201 +end
73 202
74 203 local infuser_timer = function(pos, elapsed)
75 204 local meta = minetest.get_meta(pos)
76 205
77 206 local inv = meta:get_inventory()
78 207 local infusion = inv:get_list('infusion')
79 208 local potions = inv:get_list('potions')
80 209 local elixir = infusion[1]:get_definition()
81 210 local probe = sorcery.spell.probe(pos)
211 + local fx = infuser_mods(pos)
82 212 if probe.disjunction then return true end
83 213
84 214 local potionct = 0
85 215
86 216 do
87 217 local ingredient -- *eyeroll*
88 218 if infusion[1]:is_empty() then goto cancel end
89 219 ingredient = infusion[1]:get_name()
90 220 for i = 1,#potions do
91 221 if potions[i]:is_empty() then goto skip end
92 222 potionct = potionct + 1
93 223 local base = potions[i]:get_name()
94 224 local potion = potions[i]:get_definition()
95 - if elixir_can_apply(elixir,potion) then
225 + if elixir_can_apply(elixir._proto,potion) then
96 226 -- at least one combination makes a valid potion;
97 227 -- we can start the infuser
98 228 goto start
99 229 end
100 230 for _,v in pairs(sorcery.register.infusions.db) do
101 231 if v.infuse == ingredient and v.into == base then
102 232 -- at least one combination makes a valid
................................................................................
112 242 end
113 243
114 244 ::start::
115 245 end
116 246
117 247 local time = meta:get_float("runtime") or 0
118 248 local newtime = time + elapsed
119 - local infusion_time = potionct * (15 * 60) -- 15 minutes per potion
249 + local infusion_time = potionct * (15 * 60) * (fx.brewtime or 1)-- 15 minutes per potion
120 250 -- FIXME make dependent on recipe
121 251 local percent = math.min(100, math.floor(100 * (newtime / infusion_time)))
122 252 local spawn = function(particle, scale, amt)
123 253 minetest.add_particlespawner {
124 - amount = amt;
125 - time = 15;
254 + amount = amt / 6;
255 + time = 2;
126 256 minpos = pos;
127 257 maxpos = pos;
128 258 minvel = {x = -0.1, y = 0.05, z = -0.1};
129 259 maxvel = {x = 0.1, y = 0.1, z = 0.1};
130 260 minacc = {x = 0, y = 0.1, z = 0};
131 261 maxacc = {x = 0, y = 0.4, z = 0};
132 262 minexptime = 2;
................................................................................
151 281 -- end
152 282
153 283 local discharge = sorcery.lib.node.discharger(pos)
154 284
155 285 if newtime >= infusion_time then
156 286 -- finished
157 287 local ingredient = infusion[1]:get_name()
158 - for i = 1,#potions do
159 - if potions[i]:is_empty() then goto skip end
160 - local base = potions[i]:get_name()
161 - local potion = potions[i]:get_definition()
162 - if elixir_can_apply(elixir, potion) then
163 - local newstack = inv:get_stack('potions',i)
164 - elixir._proto.apply(newstack, potion._proto)
165 - newstack:get_meta():set_string('description', sorcery.lib.ui.tooltip {
166 - title = potion._proto.name .. ' Draught';
167 - desc = potion._proto.desc;
168 - color = sorcery.lib.color(potion._proto.color):readable();
169 - props = effects_table(newstack);
170 - });
171 - inv:set_stack('potions',i,discharge(newstack))
172 - else
173 - for _,v in pairs(sorcery.register.infusions.db) do
174 - if v.infuse == ingredient and v.into == base then
175 - -- transform the base into the infusion
176 - inv:set_stack('potions',i,discharge(ItemStack(v.output)))
177 - end
178 - end
288 + local result, residue = sorcery.alchemy.infuse(infusion[1], potions)
289 + for i, r in pairs(result) do
290 + local out = r.output
291 + if r.brew then
292 + if fx.onbrew then out = fx.onbrew {
293 + pos = pos;
294 + stack = out;
295 + potion = r.proto;
296 + infusion = infusion[1];
297 + recipe = r.recipe;
298 + } end
299 + log.act(string.format('an infuser at %s has brewed a %s potion',
300 + minetest.pos_to_string(pos), out:get_name()))
301 + elseif r.enhance then
302 + if fx.onenhance then out = fx.onenhance {
303 + pos = pos;
304 + stack = out;
305 + potion = r.proto;
306 + elixir = r.elixir;
307 + } end
308 + log.act(dump(r))
309 + log.act(string.format('an infuser at %s has enhanced a %s potion with a %s elixir',
310 + minetest.pos_to_string(pos), out:get_name(), infusion[1]:get_name()))
179 311 end
180 - ::skip:: end
312 + inv:set_stack('potions',i,discharge(out))
313 + end
181 314
182 - inv:set_stack('infusion',1,ItemStack(sorcery.register.residue.db[ingredient]))
315 + inv:set_stack('infusion',1,residue)
183 316
184 317 infuser_stop(pos)
185 318 return false
186 319 else
187 320 meta:set_float('runtime', newtime)
188 - meta:set_string('formspec', infuser_formspec(percent))
321 + meta:set_string('formspec', infuser_formspec(percent, true))
189 322 meta:set_string('infotext', 'Infuser (active)')
190 323 return true
191 324 end
192 325 end
193 326
194 327 local infuser_start = function(pos)
195 328 local meta = minetest.get_meta(pos)
196 329 infuser_stop(pos)
197 330 infuser_timer(pos,0)
198 - minetest.get_node_timer(pos):start(15)
331 + minetest.get_node_timer(pos):start(2)
199 332 end
333 +
334 +local infrad = 0.42;
335 +local infbox = {
336 + type = 'fixed';
337 + fixed = {
338 + -infrad, -0.5, -infrad;
339 + infrad, 0.5, infrad;
340 + };
341 +};
200 342
201 343 minetest.register_node("sorcery:infuser", {
202 344 description = "Infuser";
203 345 drawtype = "mesh";
204 346 mesh = "sorcery-infuser.obj";
205 - paramtype2 = "facedir";
347 + sunlight_propagates = true;
348 + paramtype = "light";
206 349 after_dig_node = sorcery.lib.node.purge_container;
207 350 tiles = { -- FIXME
208 351 "default_stone.png",
209 352 "default_copper_block.png",
210 353 "default_steel_block.png",
211 354 "default_bronze_block.png",
212 355 "default_tin_block.png",
213 356 };
214 357 paramtype2 = 'facedir';
215 358 groups = {
216 - cracky = 2, oddly_breakable_by_hand = 1, heavy = 1;
359 + cracky = 2, dig_immediate = 2, heavy = 1;
217 360 sorcery_alchemy = 1, sorcery_magitech = 1;
218 361 };
219 362 _sorcery = {
220 363 recipe = {
221 364 note = 'Infuse special ingredients into liquids to create and alter powerful potions';
222 365 };
223 366 };
224 - selection_box = {
225 - type = 'fixed';
226 - fixed = {
227 - -0.37, -0.5, -0.37,
228 - 0.37, 0.5, 0.37
229 - };
230 - };
231 - collision_box = {
232 - type = 'fixed';
233 - fixed = {
234 - -0.37, -0.5, -0.37,
235 - 0.37, 0.5, 0.37
236 - };
237 - };
367 + selection_box = infbox, collision_box = infbox;
238 368
239 369 on_construct = function(pos)
240 370 local meta = minetest.get_meta(pos)
241 371 local inv = meta:get_inventory()
242 372 inv:set_size('infusion', 1)
243 373 inv:set_size('potions', 3)
244 374 meta:set_string('infotext','Infuser')
................................................................................
281 411 return 1
282 412 end
283 413 else
284 414 return 0
285 415 end
286 416 end;
287 417 })
418 +
419 +minetest.register_node("sorcery:infuser_accelerator", {
420 + description = "Infusion Accelerator";
421 + drawtype = "mesh";
422 + mesh = "sorcery-infuser-accelerator.obj";
423 + sunlight_propagates = true;
424 + paramtype = "light";
425 + paramtype2 = "facedir";
426 + tiles = { -- FIXME
427 + "basic_materials_brass_block.png",
428 + "default_stone.png",
429 + "default_copper_block.png",
430 + };
431 + paramtype2 = 'facedir';
432 + groups = {
433 + cracky = 2, heavy = 1;
434 + sorcery_alchemy = 1, sorcery_magitech = 1;
435 + };
436 + _sorcery = {
437 + recipe = {
438 + note = 'Connect to an infuser to speed up its operation; these can be stacked';
439 + };
440 + alchemy = {
441 + module = {
442 + attach = 'stack';
443 + brewtime = 0.6;
444 + };
445 + };
446 + };
447 + selection_box = infbox, collision_box = infbox;
448 +})
449 +
450 +sorcery.alchemy.purge_stand = function(pos, node, meta, who)
451 + sorcery.lib.node.purge_container(pos,node,meta,who);
452 + local mod = sorcery.alchemy.is_module(node.name)
453 + if not mod then return end
454 + if mod.stmod_connect then
455 + for _,ofs in pairs(mod.stmod_connect) do
456 + local p = vector.add(pos,ofs)
457 + local nn = sorcery.lib.node.force(p).name
458 + local pm = sorcery.alchemy.is_module(nn)
459 + if pm then -- drop any attached modules
460 + minetest.dig_node(p)
461 + end
462 + end
463 + end
464 +end
465 +
466 +minetest.register_node("sorcery:infuser_stand", {
467 + description = "Infuser Stand";
468 + drawtype = "mesh";
469 + mesh = "sorcery-infuser-stand.obj";
470 + paramtype2 = "facedir";
471 + after_dig_node = sorcery.alchemy.purge_stand;
472 + tiles = { -- FIXME
473 + "default_silver_sand.png",
474 + "default_stone.png",
475 + "default_copper_block.png",
476 + "default_wood.png",
477 + "default_aspen_wood.png",
478 + "default_steel_block.png",
479 + };
480 + paramtype2 = 'facedir';
481 + groups = {
482 + cracky = 2, choppy = 2, heavy = 1;
483 + sorcery_alchemy = 1, sorcery_magitech = 1;
484 + };
485 + _sorcery = {
486 + recipe = {
487 + note = 'Improve the effectiveness of an infuser by using a stand to attach modules';
488 + };
489 + alchemy = {
490 + module = {
491 + attach = 'stack';
492 + endstack = true;
493 + stmod_connect = {
494 + {x = 1, z = 0, y = 0};
495 + {x = -1, z = 0, y = 0};
496 + {x = 0, z = 1, y = 0};
497 + {x = 0, z = -1, y = 0};
498 + };
499 + };
500 + };
501 + };
502 + selection_box = {
503 + type = 'fixed', fixed = {
504 + -0.5, -0.5, -0.5,
505 + 0.5, 0.5, 0.5
506 + };
507 + };
508 + collision_box = {
509 + type = 'fixed', fixed = {
510 + -0.5, -0.5, -0.5,
511 + 0.5, 0.5, 0.5
512 + };
513 + };
514 +
515 + on_construct = function(pos)
516 + local meta = minetest.get_meta(pos)
517 + local inv = meta:get_inventory()
518 + inv:set_size('shelves',6 * 2)
519 + meta:set_string('infotext','Infuser Stand')
520 + meta:set_string('formspec', [[
521 + size[8,6.25]
522 + list[context;shelves;0,0;3,2;]
523 + list[context;shelves;5,0;3,2;6]
524 + list[current_player;main;0,2.5;8,4;]
525 + ]])
526 + end;
527 +})
528 +
529 +minetest.register_craft {
530 + output = 'sorcery:infuser_stand';
531 + recipe = {
532 + {'sorcery:screw_copper','sorcery:conduction_plate','sorcery:screw_copper'};
533 + {'group:wood','basic_materials:wet_cement','group:wood'};
534 + {'default:bronze_ingot','sorcery:inversion_matrix','default:bronze_ingot'}
535 + };
536 +}
537 +
538 +minetest.register_craft {
539 + output = 'sorcery:infuser_accelerator';
540 + recipe = {
541 + {'sorcery:brass_ingot','sorcery:conduction_plate','sorcery:brass_ingot'};
542 + {'basic_materials:motor','sorcery:catalytic_convector','basic_materials:motor'};
543 + {'default:stone','sorcery:leyline_stabilizer','default:stone'};
544 + };
545 +}
546 +
547 +sorcery.alchemy.register_mod = function(prop, m)
548 + minetest.register_node(prop.name, sorcery.lib.tbl.merge({
549 + sunlight_propagates = true;
550 + paramtype = 'light', paramtype2 = 'facedir';
551 + drawtype = 'mesh';
552 +
553 + groups = sorcery.lib.tbl.merge({
554 + cracky = 2;
555 + sorcery_magitech = 1;
556 + sorcery_alchemy = 1;
557 + }, prop.groups or {});
558 +
559 + _sorcery = sorcery.lib.tbl.merge({
560 + alchemy = {
561 + module = sorcery.lib.tbl.merge({attach = 'stand'}, prop.module);
562 + };
563 + recipe = {
564 + note = prop.note;
565 + }
566 + }, prop.func or {});
567 +
568 + node_placement_prediction = '';
569 +
570 + on_place = function(stack, user, where)
571 + if not where or where.type ~= 'node' then return nil end
572 + local nd = minetest.get_node(where.under)
573 + if not nd then return nil end
574 + local def = minetest.registered_nodes[nd.name]
575 + if def and def._sorcery and def._sorcery.alchemy and def._sorcery.alchemy.module then
576 + local mod = def._sorcery.alchemy.module
577 + if not mod.stmod_connect then return nil end
578 + for _, ofs in pairs(mod.stmod_connect) do
579 + ofs = vector.rotate(ofs, vector.dir_to_rotation(minetest.facedir_to_dir(nd.param2)))
580 + if vector.equals(vector.add(where.under, ofs), where.above)
581 + and sorcery.lib.node.is_air(where.above) then goto valid end
582 + end
583 + do return nil end
584 +
585 + ::valid::
586 + minetest.set_node(where.above, {
587 + name = prop.name;
588 + param2 = minetest.dir_to_facedir(vector.subtract(where.under, where.above));
589 + })
590 + stack:take_item(1)
591 + return stack
592 + end
593 + end;
594 + }, m))
595 +end
596 +
597 +sorcery.alchemy.register_mod({
598 + name = 'sorcery:infuser_mod_prolongator';
599 + note = 'Attached to an infuser using a stand, a Prolongator will cause it to produce longer-lasting potions';
600 + module = {
601 + onbrew = function(ctx)
602 + return sorcery.alchemy.elixir_apply(sorcery.data.elixirs.Longevity, ctx.stack)
603 + end;
604 + }
605 +}, {
606 + description = 'Infusion Prolongator';
607 + mesh = 'sorcery-infuser-mod-prolongator.obj';
608 + inventory_image = 'sorcery_infuser_mod_prolongator.png';
609 + tiles = {
610 + sorcery.lib.image('default_diamond_block.png'):multiply(sorcery.lib.color(255,50,150)):render();
611 + 'default_silver_sand.png';
612 + 'default_copper_block.png';
613 + 'default_steel_block.png';
614 + };
615 + selection_box = { type = 'fixed', fixed = { -0.23, -0.5, -0.2; 0.5, 0, 0.5; }; };
616 + collision_box = { type = 'fixed', fixed = { -0.23, -0.5, -0.2; 0.5, 0, 0.5; }; };
617 +})
618 +
619 +sorcery.alchemy.register_mod({
620 + name = 'sorcery:infuser_mod_amplifier';
621 + note = 'Attached to an infuser using a stand, an Amplifier will cause it to produce more powerful potions';
622 + module = {
623 + onbrew = function(ctx)
624 + return sorcery.alchemy.elixir_apply(sorcery.data.elixirs.Force, ctx.stack)
625 + end;
626 + }
627 +}, {
628 + description = 'Infusion Amplifier';
629 + mesh = 'sorcery-infuser-mod-amplifier.obj';
630 + inventory_image = 'sorcery_infuser_mod_amplifier.png';
631 + tiles = {
632 + sorcery.lib.image('default_diamond_block.png'):multiply(sorcery.lib.color(167,210,255)):render();
633 + 'default_silver_sand.png';
634 + 'default_copper_block.png';
635 + 'default_steel_block.png';
636 + 'default_wood.png';
637 + 'default_aspen_wood.png';
638 + };
639 + selection_box = { type = 'fixed', fixed = { -0.41, -0.5, -0.1; 0.25, 0.22, 0.5; }; };
640 + collision_box = { type = 'fixed', fixed = { -0.41, -0.5, -0.1; 0.25, 0.22, 0.5; }; };
641 +})
642 +
643 +-- sorcery.alchemy.register_mod({
644 +-- name = 'sorcery:infuser_mod_auxiliator';
645 +-- note = 'Attached to an infuser using a stand, provides an extra potion slot';
646 +-- module = {
647 +-- onbrew = function(ctx)
648 +-- end;
649 +-- }
650 +-- }, {
651 +-- description = 'Infusion Auxiliator';
652 +-- mesh = 'sorcery-infuser-mod-auxiliator.obj';
653 +-- inventory_image = 'sorcery_infuser_mod_auxiliator.png';
654 +-- tiles = {
655 +-- -- sorcery.lib.image('default_diamond_block.png'):multiply(sorcery.lib.color(167,210,255)):render();
656 +-- };
657 +-- selection_box = { type = 'fixed', fixed = { -0.41, -0.5, -0.1; 0.25, 0.22, 0.5; }; };
658 +-- collision_box = { type = 'fixed', fixed = { -0.41, -0.5, -0.1; 0.25, 0.22, 0.5; }; };
659 +-- })
660 +
661 +minetest.register_craft {
662 + output = 'sorcery:infuser_mod_prolongator';
663 + recipe = {
664 + -- this recipe is crap + way too cheap, come up with
665 + -- some fancy new ingredients and use them instead FIXME
666 + {'basic_materials:silver_wire','stairs:slab_copperblock',''};
667 + {'default:steel_ingot','sorcery:core_syncretic','default:steel_ingot'};
668 + {'sorcery:gem_ruby','default:copperblock','sorcery:gem_ruby'};
669 + };
670 +}
671 +
672 +minetest.register_craft {
673 + output = 'sorcery:infuser_mod_amplifier';
674 + recipe = {
675 + -- this recipe is crap + way too cheap, come up with
676 + -- some fancy new ingredients and use them instead FIXME
677 + {'basic_materials:silver_wire','stairs:slab_copperblock',''};
678 + {'default:wood','sorcery:core_syncretic','default:wood'};
679 + {'sorcery:gem_sapphire','default:copperblock','sorcery:gem_sapphire'};
680 + };
681 +}
682 +
683 +
684 +-- other mods:
685 +-- * amplifier
686 +-- * elixir enhancer
687 +-- * randomizer
688 +-- * device that enables some kind of higher-tier potionmaking
689 +-- * device that allows attaching 1 or 2 stand mods without terminating the stack
690 +-- * radia collector - captures spare radia, occasionally can produce an extra potion, sometimes random