sorcery  Diff

Differences From Artifact [eabb5d4796]:

  • File wands.lua — part of check-in [ea6e475e44] at 2020-10-19 09:52:11 on branch trunk — continue dev on celestial mechanics, add melding+division spells (resonance), refine itemclasses, add keypunch and punchcards, add paper pulp, add a shitload of visuals, add convenience scripts for working with the wiki, make the flamebolt spell actually useful instead of just a pretty lightshow, add essences, inferno crystal, and other goodies; iterate on wands, lots of shit i can't remember, various bugfixes (user: lexi, size: 27150) [annotate] [blame] [check-ins using]

To Artifact [e3e1a760a8]:


   100    100   			};
   101    101   			steel = {
   102    102   				tone = u.color(255,255,255);
   103    103   				tex = u.image('default_steel_block');
   104    104   				wandprops = {};
   105    105   			};
   106    106   		};
   107         -		gem = sorcery.lib.tbl.deepmerge(sorcery.data.gems, {
   108         -			sapphire = {
   109         -				wandprops = { sturdiness = 0.5 };
   110         -			};
   111         -			diamond = {
   112         -				wandprops = { sturdiness = (1/3) };
   113         -			};
   114         -		})
          107  +		gem = sorcery.data.gems;
   115    108   	};
   116    109   	util = {
   117    110   		baseid = function(wand)
   118    111   			local elts = {wand.wood}
   119    112   			if wand.gem  ~= nil then elts[#elts + 1] = wand.gem end
   120    113   			if wand.wire ~= nil then elts[#elts + 1] = wand.wire end
   121    114   			return 'sorcery:wand_' .. table.concat(elts,'_')
................................................................................
   255    248   			end
   256    249   		end
   257    250   	end
   258    251   
   259    252   	local uprops = user:get_properties();
   260    253   	local context = {
   261    254   		base = wand;
          255  +		stats = matprops;
   262    256   		meta = meta;
   263    257   		item = stack;
   264    258   		caster = user;
   265    259   		target = target;
   266    260   		today = minetest.get_day_count();
   267    261   		heading = {
   268    262   			pos   = user:get_pos();
................................................................................
   339    333   	if kind.gem then
   340    334   		img.gem = u.image('sorcery_wand_' .. kind.gem .. '_tip.png')
   341    335   		img.whole = img.gem:blit(img.whole)
   342    336   	end
   343    337   	return img
   344    338   end
   345    339   
          340  +local update_stand_info = function(pos)
          341  +	local woodname = minetest.registered_nodes[minetest.get_node(pos).name]._proto.wood
          342  +	local meta = minetest.get_meta(pos)
          343  +	local inv = meta:get_inventory()
          344  +	if inv:is_empty('wand') then
          345  +		meta:set_string('infotext',u.str.capitalize(woodname) .. ' wand stand')
          346  +	else
          347  +		local stack = inv:get_stack('wand',1)
          348  +		local spell = stack:get_meta():get_string('sorcery_wand_spell')
          349  +		local color = u.color(127,127,127)
          350  +		if spell ~= '' then
          351  +			color = u.color(sorcery.data.spells[spell].color):readable()
          352  +		end
          353  +		local wand_proto = sorcery.wands.util.getproto(stack)
          354  +		meta:set_string('infotext',color:fmt(sorcery.wands.util.fullname(stack) .. ' stand'))
          355  +	end
          356  +end
   346    357   local createstand = function(name, wood, desc, tex, extra)
   347    358   	local hitbox = {
   348    359   		type = "fixed";
   349    360   		fixed = {
   350    361   			-0.5, -0.5, -0.3;
   351    362   			0.5, -0.1, 0.3;
   352    363   		};
................................................................................
   359    370   		mesh = 'sorcery-wand-stand.obj';
   360    371   		sunlight_propagates = true;
   361    372   		paramtype = 'light';
   362    373   		paramtype2 = 'facedir';
   363    374   		tiles = images;
   364    375   		selection_box = hitbox;
   365    376   		collision_box = hitbox;
          377  +		after_dig_node = sorcery.lib.node.purge_container;
   366    378   		use_texture_alpha = true;
          379  +		on_construct = function(pos)
          380  +			local meta = minetest.get_meta(pos)
          381  +			local inv = meta:get_inventory()
          382  +			inv:set_size('wand', 1)
          383  +			update_stand_info(pos)
          384  +		end;
   367    385   		_proto = {
   368    386   			wood = wood;
   369    387   		};
   370    388   		groups = {
   371    389   			sorcery_wand_stand = 1;
   372    390   			choppy = 2;
   373    391   			oddly_breakable_by_hand = 2;
   374    392   		};
   375    393   	}
   376    394   	minetest.register_node(name, u.tbl.merge(auto,extra))
   377    395   end
   378         -local update_stand_info = function(pos)
   379         -	local woodname = minetest.registered_nodes[minetest.get_node(pos).name]._proto.wood
          396  +local rack_update = function(pos)
   380    397   	local meta = minetest.get_meta(pos)
   381    398   	local inv = meta:get_inventory()
   382         -	if inv:is_empty('wand') then
   383         -		meta:set_string('infotext',u.str.capitalize(woodname) .. ' wand stand')
   384         -	else
   385         -		local stack = inv:get_stack('wand',1)
   386         -		local spell = stack:get_meta():get_string('sorcery_wand_spell')
   387         -		local color = u.color(127,127,127)
   388         -		if spell ~= '' then
   389         -			color = u.color(sorcery.data.spells[spell].color):readable()
          399  +	local wandcount = 0
          400  +	local mkslot = function(slot,x,y)
          401  +		local stack = inv:get_stack('wands',slot)
          402  +		local im = stack:get_meta()
          403  +		local r = string.format([[ list[context;wands;%f,%f;1,1;%u] ]], x, y, slot-1)
          404  +		if stack:is_empty() then
          405  +			r = r .. string.format([[ image[%f,%f;1,1;sorcery_ui_ghost_wand.png] ]], x, y)
          406  +		else
          407  +			wandcount = wandcount + 1
          408  +			if im:contains('sorcery_wand_spell') then
          409  +				local spell = im:get_string('sorcery_wand_spell')
          410  +				local spname = u.str.capitalize(sorcery.data.spells[spell].name)
          411  +				local spclr = u.color(sorcery.data.spells[spell].color or {255,255,255})
          412  +
          413  +				r = r .. string.format([[
          414  +					label[%f,%f;%s]
          415  +				]], x + 1.25, y + 0.5, minetest.formspec_escape(spclr:fmt(spname)))
          416  +			end
   390    417   		end
   391         -		local wand_proto = sorcery.wands.util.getproto(stack)
   392         -		meta:set_string('infotext',color:fmt(sorcery.wands.util.fullname(stack) .. ' stand'))
          418  +		return r
   393    419   	end
          420  +	local spec = [[
          421  +		formspec_version[3] size[10.25,11.75] real_coordinates[true]
          422  +		list[current_player;main;0.25,6.75;8,4;]
          423  +		listring[current_player;main] listring[context;wands]
          424  +	]]
          425  +	for i=1,inv:get_size('wands') do
          426  +		local yo = ((i-1) % 5) * 1.25
          427  +		local xo = i > 5 and 5 or 0
          428  +		spec = spec .. mkslot(i, 0.25 + xo, 0.25 + yo)
          429  +	end
          430  +	meta:set_string('formspec',spec)
          431  +	if wandcount > 0 then
          432  +		meta:set_string('infotext',string.format('Wand rack with %u wands', wandcount))
          433  +	else
          434  +		meta:set_string('infotext','Wand rack')
          435  +	end
          436  +end
          437  +
          438  +local createrack = function(name, wood, tex, desc)
          439  +	local hitbox = {
          440  +		type = "fixed";
          441  +		fixed = {
          442  +			-0.5, -0.5, 0.5;
          443  +			 0.5,  0.5, 0.35;
          444  +		};
          445  +	}
          446  +	local rack = {
          447  +		description = desc;
          448  +		drawtype = 'mesh';
          449  +		mesh = 'sorcery-wand-rack.obj';
          450  +		sunlight_propagates = true;
          451  +		paramtype = 'light';
          452  +		paramtype2 = 'facedir';
          453  +		tiles = {
          454  +			u.image('default_diamond_block.png'):
          455  +				multiply(u.color{50,255,70}):render();
          456  +			tex:render();
          457  +			'default_diamond_block.png';
          458  +			'default_copper_block.png';
          459  +			'default_pine_wood.png';
          460  +			'default_junglewood.png';
          461  +		};
          462  +		selection_box = hitbox;
          463  +		collision_box = hitbox;
          464  +		use_texture_alpha = true;
          465  +		after_dig_node = sorcery.lib.node.purge_container;
          466  +		on_construct = function(pos)
          467  +			local meta = minetest.get_meta(pos)
          468  +			local inv = meta:get_inventory()
          469  +			inv:set_size('wands',10)
          470  +			rack_update(pos)
          471  +		end;
          472  +		allow_metadata_inventory_put = function(pos, lst, idx, stack, user)
          473  +			if minetest.get_item_group(stack:get_name(), 'sorcery_wand') ~= 0
          474  +				then return 1
          475  +				else return 0
          476  +			end
          477  +		end;
          478  +		on_metadata_inventory_move = rack_update;
          479  +		on_metadata_inventory_take = rack_update;
          480  +		on_metadata_inventory_put = rack_update;
          481  +		_proto = { wood = wood; };
          482  +		groups = {
          483  +			sorcery_wand_rack = 1;
          484  +			choppy = 2;
          485  +			oddly_breakable_by_hand = 2;
          486  +		};
          487  +	}
          488  +	minetest.register_node(name, rack)
   394    489   end
   395    490   for woodname, wood in pairs(sorcery.wands.materials.wood) do
   396    491   	local blank = u.image('sorcery_transparent.png'); -- haaaaack
   397    492   	local name = 'sorcery:wand_stand_' .. woodname
          493  +	local rackid = 'sorcery:wand_rack_' .. woodname
   398    494   	createstand(name, woodname,
   399         -		u.str.capitalize(woodname .. 'wood wand stand'),
          495  +		u.str.capitalize(woodname) .. 'wood wand stand',
   400    496   		{ wood.tex; blank; blank; blank; }, {
   401         -			on_construct = function(pos)
   402         -				local meta = minetest.get_meta(pos)
   403         -				local inv = meta:get_inventory()
   404         -				inv:set_size('wand', 1)
   405         -				update_stand_info(pos)
   406         -			end;
   407    497   			on_rightclick = function(pos,node,user,stack)
   408    498   				local meta = minetest.get_meta(pos)
   409    499   				local stand = meta:get_inventory()
   410    500   				local wand_proto = sorcery.wands.util.getproto(stack)
   411    501   				if minetest.get_item_group(stack:get_name(), 'sorcery_wand') ~= 0 then
   412    502   					stand:set_stack('wand',1,stack)
   413    503   					minetest.swap_node(pos, {
................................................................................
   417    507   					stack = ItemStack(nil)
   418    508   				end
   419    509   				update_stand_info(pos)
   420    510   				return stack
   421    511   			end
   422    512   		}
   423    513   	)
          514  +	createrack(rackid,woodname,wood.tex,
          515  +		u.str.capitalize(woodname) .. 'wood wand rack')
          516  +
   424    517   	local plank = wood.plank or 'default:' .. woodname .. '_wood'
   425    518   	minetest.register_craft {
          519  +		output = name;
   426    520   		recipe = {
          521  +			-- TODO: whittling/carving knife
   427    522   			{plank, 'default:stick', plank};
   428    523   			{plank, plank, plank};
   429    524   		};
   430         -		output = name
          525  +	}
          526  +
          527  +	minetest.register_craft {
          528  +		output = rackid;
          529  +		recipe = {
          530  +			{plank,'default:stick',plank};
          531  +			{'sorcery:screw_steel','screwdriver:screwdriver','sorcery:screw_steel'};
          532  +			{plank,name,plank};
          533  +		};
          534  +		replacements = {
          535  +			{'screwdriver:screwdriver','screwdriver:screwdriver'};
          536  +		};
   431    537   	}
   432    538   end
   433    539   
   434    540   sorcery.wands.createstands = function(kind)
   435    541   	-- big oof
   436    542   	for woodname, wood in pairs(sorcery.wands.materials.wood) do
   437    543   		local gemimg = u.image('default_diamond_block.png')
................................................................................
   577    683   
   578    684   	-- iterate through every wand in the tank to see if anything
   579    685   	-- needs to be done
   580    686   	local success = false
   581    687   	for i,wand in pairs(wands) do
   582    688   		local proto = wand.stack:get_definition()._proto
   583    689   		local wood = sorcery.wands.materials.wood[proto.wood]
   584         -		--print('considering ' .. proto.wood)
   585    690   		for spell,def in pairs(sorcery.data.spells) do
   586    691   			if not def.affinity then goto skip_spell end
   587    692   			local potions, found = {}, false
   588    693   			for _,a in pairs(def.affinity) do
   589    694   				if a == proto.wood then found = true else
   590    695   					potions[#potions + 1] = a
   591    696   				end
   592    697   			end
   593    698   			if not found then goto skip_spell end
   594         -		-- for spell,potions in pairs(wood.affinities) do
   595         -			--print(' + considering spell ' .. spell)
   596    699   			-- check whether all the necessary philters
   597    700   			-- are accounted for
   598    701   			if #potions ~= #philters then goto skip_spell end
   599    702   			for _,p in pairs(potions) do
   600    703   				for _,ph in pairs(philters) do
   601    704   					local def = ph.stack:get_definition()
   602         -					--print(' - + checking for philter ' .. def._protoname)
   603    705   					if def._protoname == p then goto found end
   604    706   				end
   605    707   				goto skip_spell
   606    708   			::found::end
   607    709   
   608    710   			success = true
   609    711   			-- we've confirmed that all the philters for this spell
   610    712   			-- are present, now we need to apply it to the wand
   611         -			--print('setting spell')
   612    713   			wand.stack:get_meta():set_string('sorcery_wand_spell',spell)
   613    714   			update_wand_description(wand.stack)
   614    715   			inv:set_stack('tank',wand.idx,wand.stack)
   615    716   
   616    717   			do break end -- }:<<<
   617    718   		::skip_spell::end
   618    719   	end
................................................................................
   636    737   	local slot = function(name,x,y,w,h)
   637    738   		return string.format('list[nodemeta:%d,%d,%d;%s;%f,%f;%f,%f;]',
   638    739   			pos.x, pos.y, pos.z,
   639    740   			name, x,y, w,h
   640    741   		)
   641    742   	end
   642    743   
   643         -	return 'size[8,6.5]' ..
          744  +	return 'size[8,6.25]' ..
   644    745   		slot('tank', 0.5,0, 2,2) ..
   645    746   		slot('wandparts', 5.5,0, 1,2) ..
   646    747   		slot('preview', 6.5,0.5, 1,1) ..
   647    748   		slot('input', 4.5,0.5, 1,1) .. [[
   648    749   		list[current_player;main;0,2.5;8,4;]
   649    750   		listring[]
   650    751   	]]