Differences From
Artifact [b21ad56f71]:
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';