sorcery  Artifact [9a3b11da34]

Artifact 9a3b11da34bd664af11b1fabfe8a34ef302dd488761a3a39c8e43b8bd35b4d47:

  • File disassembly.lua — part of check-in [3f6a913e4e] at 2020-09-29 12:40:28 on branch trunk — * remove former hacky registration system, replace with consistent and flexible API; rewrite metal/gem generation to take advantage of this new API; tweaks to init system to enable world-local tweaks to lore and sorcery behavior * initial documentation commit * initial steps towards calendar - add default date format, astrolabe; prepare infra for division/melding/transmutation spells, various tweaks and fixes (user: lexi, size: 5148) [annotate] [blame] [check-ins using]

local disassembler_formspec = function(pos)
	local m = minetest.get_meta(pos)
	local i = m:get_inventory()
	local form = [[
		formspec_version[3]
		size[10.25,7] real_coordinates[true]
		list[current_player;main;0.25,2;8,4]
	]]
	local slot = function(name,x,y,ghost)
		local s = string.format('list[context;%s;%f,%f;1,1;]', name, x, y)
		if ghost and i:is_empty(name) then
			s = string.format('image[%f,%f;1,1;sorcery_ui_ghost_%s.png]',x,y,ghost) .. s
		end
		form = form .. s
	end
	slot('item',0.25,0.5)
	slot('paper',2.25,0.5,'paper')
	slot('ink',3.50,0.5,'ink_bottle')
	slot('pen',4.75,0.5,'pen')
	slot('output',9,0.5)
	form = form .. [[
		listring[context;output]
		listring[current_player;main] listring[context;paper]
		listring[current_player;main] listring[context;ink]
		listring[current_player;main] listring[context;item]
		listring[current_player;main]
	]]
	m:set_string('formspec',form)
end
local update_disassembler = function(pos)
	local m = minetest.get_meta(pos)
	local i = m:get_inventory()
	local paper = i:get_stack('paper',1)
	local item = i:get_stack('item',1)
	local ink = i:get_stack('ink',1)
	local pen = i:get_stack('pen',1)

	local ink_count = ink:get_count()
	
	local maxrecs = math.min(ink_count, paper:get_count(), item:get_count())
	if pen:is_empty() then maxrecs = 0 end

	if maxrecs > 0 and sorcery.cookbook.classes.craft.find(item:get_name()) then
		local rec = ItemStack{name = 'sorcery:recipe', count = maxrecs}
		sorcery.cookbook.setrecipe(rec, 'craft', item:get_name())
		i:set_stack('output',1,rec)
	else
		i:set_stack('output',1,ItemStack())
	end
	disassembler_formspec(pos)
end
local dsbox = {
	type = 'fixed';
	fixed = {
		-0.5, -0.5, -0.5;
		 0.5,  0.0,  0.5;
	};
}
minetest.register_node('sorcery:disassembler', {
	description = 'Disassembly Kit';
	drawtype = 'mesh';
	mesh = 'sorcery-disassembler.obj';
	paramtype = 'light', sunlight_propagates = true;
	paramtype2 = 'facedir';
	groups = { cracky = 2, sorcery_tech = 1 };
	selection_box = dsbox;
	collision_box = dsbox;
	tiles = {
		'default_copper_block.png';
		'default_wood.png';
		'default_steel_block.png';
		'default_stone.png';
		'default_gold_block.png';
		'default_coal_block.png';
	};
	_sorcery = {
		recipe = {
			note = 'Destroy a device or object to learn how it is crafted';
		};
	};
	after_dig_node = sorcery.lib.node.purge_container;
	on_construct = function(pos)
		local m = minetest.get_meta(pos)
		local i = m:get_inventory()
		i:set_size('item',1)
		i:set_size('paper',1)
		i:set_size('ink',1)
		i:set_size('pen',1)
		i:set_size('output',1)
		m:set_string('infotext','Disassembly Kit')
		disassembler_formspec(pos)
	end;
	on_metadata_inventory_put = update_disassembler;
	on_metadata_inventory_take = function(pos,list,idx,stack,user)
		local m = minetest.get_meta(pos)
		local i = m:get_inventory()
		local paper = i:get_stack('paper',1)
		local item = i:get_stack('item',1)

		if list == 'output' then
			local count = stack:get_count()
			local leftover = sorcery.register.residue.db[item:get_name()]
			local lstack if leftover then
				lstack = ItemStack(leftover)
				lstack:set_count(lstack:get_count() * count)
				-- this slightly idiosyncratic code is used to ensure that
				-- itemstrings can be used in the residue table
			end
			item:take_item(count)
			if item:get_count() > 0 then
				if leftover then
					lstack = user:get_inventory():add_item(lstack)
					if lstack:get_count() > 0 then minetest.add_item(pos,lstack) end
				end
				i:set_stack('item',1,item)
			else
				if leftover then
					i:set_stack('item',1,lstack)
				else
					i:set_stack('item',1,ItemStack())
				end
			end
			local ink = i:get_stack('ink',1)
			local paper = i:get_stack('paper',1)
			ink:take_item(count)		paper:take_item(count)
			i:set_stack('ink',1,ink)	i:set_stack('paper',1,paper)
			local penstack = i:get_stack('pen',1)
			local pen = penstack:get_definition()._sorcery
			local uses = pen.material.data.durability * 0.10
			local dmg = 65535 / math.random(math.floor(uses*0.5),uses)
			print('adding damage',dmg,penstack:get_wear())
			penstack:add_wear(dmg)
			print('wear now',penstack:get_wear())
			i:set_stack('pen',1,penstack)
		end

		update_disassembler(pos)
	end;
	allow_metadata_inventory_put = function(pos,list,idx,stack,user)
		local name = stack:get_name()
		if list == 'paper' then
			if name == 'default:paper' then return stack:get_count() end
		elseif list == 'ink' then
			if minetest.get_item_group(name,'ink') > 0 then return stack:get_count() end
		elseif list == 'pen' then
			if minetest.get_item_group(name,'sorcery_pen') > 0 then return stack:get_count() end
		elseif list == 'item' then
			return stack:get_count()
		elseif list == 'output' then
			return 0
		end
		return 0
	end;
	allow_metadata_inventory_move = function(pos, fl, fi, tl, ti, count)
		if fl == 'ink' and tl == 'ink'
			then return count
			else return 0
		end
	end;
})

minetest.register_craft {
	output = 'sorcery:disassembler';
	recipe = {
		{'group:wood','default:gold_ingot','dye:black'};
		{'sorcery:vice','screwdriver:screwdriver','xdecor:hammer'};
		{'stairs:slab_stone', 'stairs:slab_stone', 'stairs:slab_stone'};
	};
}