sorcery  Diff

Differences From Artifact [b21ad56f71]:

To Artifact [89adffa44b]:


    80     80   		end
    81     81   	end
    82     82   	return names[math.random(#names)]
    83     83   end end
    84     84   local find_builtin = function(out)
    85     85   	local rec = {}
    86     86   	local i = minetest.get_craft_recipe(out)
    87         -	if #i.items == 0 then return nil end
           87  +	if i == nil or i.items == nil or #i.items == 0 then return nil end
    88     88   	local w = (i.width == 0) and 3 or i.width
    89     89   	for j=1,#i.items do
    90     90   		local row = math.floor((j-1) / w)
    91     91   		local col = (j-1) % w
    92     92   		if i.items[j] then
    93     93   			rec[1 + (row * 3) + col] = i.items[j]
    94     94   		end
................................................................................
   111    111   	end
   112    112   	return i
   113    113   end
   114    114   local function desc_builtin(i)
   115    115   	local desc
   116    116   	i, desc = group_eval(i)
   117    117   	-- print('describing ',i,dump(minetest.registered_items[i]))
   118         -	if not minetest.registered_items[i] then
          118  +	local s = ItemStack(i)
          119  +	if not minetest.registered_items[s:get_name()] then
   119    120   		minetest.log('WARNING: unknown item in recipe ' .. i)
   120    121   		return 'Unknown Item'
   121    122   	end
   122         -	if not desc then desc = minetest.registered_items[i].description end
          123  +	if not desc then desc = minetest.registered_items[s:get_name()].description end
   123    124   	if not desc then return 'Peculiar Item' end
   124    125   
   125    126   	local eol = string.find(desc,'\n')
   126         -	if not eol then return desc else return string.sub(desc,1,eol-1) end
          127  +	if eol then desc = string.sub(desc,1,eol-1) end
          128  +
          129  +	if s:get_count() > 1 then
          130  +		desc = string.format("%s (%u)",desc,s:get_count())
          131  +	end
          132  +	return desc
   127    133   end;
   128    134   
   129    135   local bookadjs = { -- sets are in reverse order!
   130    136   	{'Celestial', 'Divine', 'Inspired', 'Heavenly';
   131    137   	 'Mystic', 'Diabolic', 'Luminous', 'Forsaken'};
   132    138   
   133    139   	{'Dark', 'Perfected', 'Flawless', 'Unthinkable';
................................................................................
   135    141   
   136    142   	{'Splendid', 'Magnificent', 'Sublime', 'Grand';
   137    143   	 'Beneficent', 'Mysterious', 'Peculiar', 'Eerie';
   138    144   	 'Fulsome', 'Fearsome', 'Curious', 'Fascinating';
   139    145        'Notorious', 'Infamous'};
   140    146   }
   141    147   
          148  +local cache = {
          149  +	populate_grindables = function(cache)
          150  +		if not cache.grindables then
          151  +			cache.grindables = {}
          152  +			for k,v in pairs(minetest.registered_items) do
          153  +				if sorcery.itemclass.get(k, 'grindable') then
          154  +					cache.grindables[#cache.grindables+1] = k
          155  +				end
          156  +			end
          157  +		end
          158  +	end;
          159  +}
   142    160   sorcery.cookbook.classes = {
   143    161   	craft = {
   144    162   		name = 'Crafting Guide';
   145    163   		node = 'xdecor:workbench';
   146    164   		booksuf = 'Manual';
   147    165   		w = 3, h = 3;
   148    166   		chance = 2;
................................................................................
   158    176   	-- 	slots = slot3x3;
   159    177   	-- };
   160    178   	cook = {
   161    179   		name = 'Cooking Recipe';
   162    180   		node = 'default:furnace';
   163    181   		booksuf = 'Cookbook';
   164    182   		w = 1, h = 1;
   165         -		chance = 5;
          183  +		chance = 3;
   166    184   		slots = {{-0.2,0}};
   167    185   		pick = pick_builtin('cooking');
   168    186   		find = find_builtin;
   169    187   		props = props_builtin;
   170    188   		apply_exclusions = true;
   171    189   	};
   172    190   	infuse = {
   173    191   		name = 'Infusion Recipe';
   174    192   		node = 'sorcery:infuser';
   175    193   		booksuf = 'Pharmacopeia';
   176    194   		w = 1, h = 2;
   177         -		chance = 2;
          195  +		chance = 4;
   178    196   		slots = {
   179    197   			{0,0};
   180    198   			{0,1};
   181    199   		};
   182    200   		pick = function(restrict)
   183    201   			-- TODO make sure affinity restrictions match
   184    202   			return sorcery.data.infusions[math.random(#sorcery.data.infusions)].output
   185    203   		end;
   186    204   		title = function(output)
   187    205   			for _,i in pairs(sorcery.data.infusions) do
   188         -				print(dump(i))
   189    206   				if i.output == output then
   190    207   					if i._proto and i._proto.name
   191    208   						then return i._proto.name
   192    209   						else break end
   193    210   				end
   194    211   			end
   195    212   			return 'Mysterious Potion'
................................................................................
   198    215   			for _,i in pairs(sorcery.data.infusions) do
   199    216   				if i.output == out then
   200    217   					return { i.infuse, i.into }
   201    218   				end
   202    219   			end
   203    220   		end;
   204    221   		props = function(out)
   205         -			local i = sorcery.cookbook.classes.infuse.find(out)
   206         -			if i.recipe then return i.info else return {} end
          222  +			for _,i in pairs(sorcery.data.infusions) do
          223  +				if i.output == out then
          224  +					if i.recipe then return i.recipe else return {} end
          225  +				end
          226  +			end
          227  +		end;
          228  +	};
          229  +	grind = {
          230  +		name = 'Milling Guide';
          231  +		node = 'sorcery:mill';
          232  +		booksuf = 'Manual';
          233  +		chance = 1;
          234  +		w = 1, h = 2;
          235  +		pick = function(restrict)
          236  +			cache:populate_grindables()
          237  +			local i = cache.grindables[math.random(#cache.grindables)]
          238  +			local pd = sorcery.itemclass.get(i, 'grindable')
          239  +			return pd.powder
          240  +		end;
          241  +		desc = desc_builtin;
          242  +		props = props_builtin;
          243  +		slots = {
          244  +			{0,1},
          245  +			{0,0};
          246  +		};
          247  +		find = function(out)
          248  +			cache:populate_grindables()
          249  +			for _,v in pairs(cache.grindables) do
          250  +				local g = sorcery.itemclass.get(v,'grindable')
          251  +				if g.powder == out then
          252  +					if g.grindcost then
          253  +						v = v .. ' ' .. tostring(g.grindcost)
          254  +					end
          255  +					local mbh = sorcery.lib.tbl.keys(sorcery.data.metals)
          256  +					table.sort(mbh, function(a,b)
          257  +						return sorcery.data.metals[a].hardness < sorcery.data.metals[b].hardness
          258  +					end)
          259  +					for _,metal in pairs(mbh) do
          260  +						local md = sorcery.data.metals[metal]
          261  +						if ((not md.no_tools) or md.grindhead) and md.hardness >= g.hardness then
          262  +							return {v, 'sorcery:mill_grindhead_' .. metal}
          263  +						end
          264  +					end
          265  +					return {v,''} -- !!
          266  +				end
          267  +			end
   207    268   		end;
   208    269   	};
   209    270   	-- wand = {
   210    271   	--	booksuf = 'Grimoire';
   211    272   	-- }
   212    273   	enchant = {
   213    274   		name = 'Enchantment Matrix';
   214    275   		node = 'sorcery:enchanter';
   215    276   		booksuf = 'Grimoire';
   216    277   		drawslots = false;
   217         -		chance = 1;
          278  +		chance = 6;
   218    279   		w = 2, h = 2;
   219    280   		pick = function(restrict)
   220    281   			-- TODO make sure affinity restrictions match
   221    282   			local names = {}
   222    283   			for k,v in pairs(sorcery.data.enchants) do
   223    284   				if v.recipe then names[#names+1] = k end
   224    285   			end
................................................................................
   283    344   sorcery.cookbook.pickrecipe = function(kind,restrict)
   284    345   	if kind == nil then
   285    346   		for k,v in pairs(recipe_kinds) do
   286    347   			if math.random(v.chance) == 1 then
   287    348   				kind = k break
   288    349   			end
   289    350   		end
   290         -		-- local rks = sorcery.lib.tbl.keys(recipe_kinds)
   291         -		-- kind = rks[math.random(#rks)]
          351  +		if kind == nil then -- oh well, we tried
          352  +			local rks = sorcery.lib.tbl.keys(recipe_kinds)
          353  +			kind = rks[math.random(#rks)]
          354  +		end
   292    355   	end
   293    356   
   294    357   	return recipe_kinds[kind].pick(restrict), kind
   295    358   end
   296    359   
   297         -local render_recipe = function(kind,ingredients,result)
          360  +local render_recipe = function(kind,ingredients,result,notes_right)
   298    361   	local k = recipe_kinds[kind]
   299    362   	local t = ''
   300    363   	for i=1,#k.slots do
   301    364   		local x, y = k.slots[i][1], k.slots[i][2]
   302    365   		if ingredients[i] and ingredients[i] ~= '' then
   303    366   			local tt
   304    367   			if k.indesc then tt = k.indesc(ingredients[i]) else tt = desc_builtin(ingredients[i]) end
................................................................................
   312    375   				t = string.format('box[%f,%f;0.1,0.1;#00000060]',x+0.45,y+0.45) .. t
   313    376   			end
   314    377   		end
   315    378   	end
   316    379   	local img, ot
   317    380   	local props = k.props(result)
   318    381   	if props.note then
          382  +		local nx, ny, nw, nh
          383  +		if notes_right then
          384  +			nx = 5 ny = 0
          385  +			nw = 3 nh = 3
          386  +		else
          387  +			nx = 0 ny = 3
          388  +			nw = 4 nh = 1
          389  +		end
   319    390   		t = t .. string.format([[
   320         -			textarea[0,3;4,1;;;%s]
   321         -		]], minetest.formspec_escape(props.note))
          391  +			textarea[%f,%f;%f,%f;;;%s]
          392  +		]], nx,ny,nw,nh, minetest.formspec_escape(props.note))
   322    393   	end
   323    394   	if k.icon then img = k.icon(result) end
   324    395   	if k.outdesc then ot = k.outdesc(result) else ot = desc_builtin(result) end
   325    396   		-- image[%f,%f;1,1;gui_furnace_arrow_bg.png^[transformR270]
   326    397   	return t .. string.format([[
   327    398   		item_image[%f,%f;1,1;%s]tooltip[%f,%f;1,1;%s]
   328    399   		]] --[[box[%f,%f;1,1;#850083A0]] .. [[
................................................................................
   332    403   		k.w, k.h/2 - 0.5, minetest.formspec_escape(minetest.registered_nodes[k.node].description),
   333    404   			-- k.w+1, k.h/2 - 0.5,
   334    405   		img and 'image' or 'item_image',
   335    406   			k.w+1.1, k.h/2 - 0.5, minetest.formspec_escape(img or result),
   336    407   			k.w+1.1, k.h/2 - 0.5, minetest.formspec_escape(ot))
   337    408   end;
   338    409   
   339         -local retrieve_recipe = function(kind,out)
          410  +local retrieve_recipe = function(kind,out,notes_right)
   340    411   	local rec = recipe_kinds[kind]
   341    412   	local ing = rec.find(out)
   342         -	return render_recipe(kind,ing,out), rec.w, rec.h
          413  +	return render_recipe(kind,ing,out,notes_right), rec.w, rec.h
   343    414   end
   344    415   
   345    416   sorcery.cookbook.setrecipe = function(stack,k,r,restrict)
   346    417   	local meta = stack:get_meta()
   347    418   	if not r then r,k = sorcery.cookbook.pickrecipe(k,restrict) end
   348    419   	local t = recipe_kinds[k]
   349    420   	meta:set_string('recipe_kind', k)
................................................................................
   442    513   		{2,1.3};
   443    514   		{2,4.5};
   444    515   		{2,7.7};
   445    516   		-- {0,1.3}, {4, 1.3};
   446    517   		-- {0,4.7}, {4, 4.7};
   447    518   		-- {0,8.1}, {4, 8.1};
   448    519   	}
   449         -	print('book:',dump(book))
   450         -	print('pgofs',pgofs)
   451    520   	for i=pgofs,(pgofs + constants.recipes_per_cookbook_page-1) do
   452    521   		local maxw, maxh = 3, 2
   453    522   		if not book.pages[i+1] then break end
   454    523   		local nr = 1+(i - pgofs)
   455    524   		local x,y = coords[nr][1], coords[nr][2]
   456    525   		local k = recipe_kinds[book.pages[i+1].kind]
   457    526   		local ox,oy = maxw - k.w, maxh - k.h
   458    527   		form = form .. string.format('container[%f,%f]%scontainer_end[]',(x+ox)-0.5,y,
   459         -			retrieve_recipe(book.pages[i+1].kind, book.pages[i+1].name))
          528  +			retrieve_recipe(book.pages[i+1].kind, book.pages[i+1].name, true))
   460    529   	end
   461    530   
   462    531   	minetest.show_formspec(user:get_player_name(), 'sorcery:cookbook', form)
   463    532   end
   464    533   
   465    534   minetest.register_craftitem('sorcery:cookbook', {
   466    535   	description = 'Catalog';