sorcery  Artifact [42c4d86138]

Artifact 42c4d8613829f994d88adffaaf665fe96f201b4e3e423d148a5fb45d81b803c7:

  • File gems.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: 9009) [annotate] [blame] [check-ins using]

--- gemstones
local shards_per_gem = 9

local register_gem = function(name,gem)
	local itemname = gem.foreign or 'sorcery:gem_' .. name
	local shardname = gem.foreign_shard or 'sorcery:gem_' .. name .. '_shard'
	local amuletname = gem.foreign_amulet or 'sorcery:gem_' .. name .. '_amulet'

	sorcery.data.gems[name].parts = {
		item = itemname;
		shard = shardname;
		amulet = amuletname;
	}

	local tools, armors = sorcery.matreg.tools, sorcery.matreg.armors
	if gem.tools then for t,c in pairs(tools) do
		sorcery.matreg.lookup[(gem.items and gem.items[t]) or ('sorcery:' .. t .. '_' .. name)] = {
			gem = true;
			id = name; data = gem;
			value = c.cost*shards_per_gem;
		}
	end end
	if gem.armor then for a,c in pairs(armors) do
		sorcery.matreg.lookup[(gem.items and gem.items[a]) or ('sorcery:' .. a .. '_' .. name)] = {
			gem = true;
			id = name, data = gem;
			value = c.cost*shards_per_gem;
		}
	end end

	if gem.foreign_shard then
		minetest.clear_craft {output=shardname}
	else
		minetest.register_craftitem(shardname, {
			description = sorcery.lib.str.capitalize(name) .. ' shard';
			inventory_image = 'sorcery_gem_' .. name .. '_shard.png';
			groups = { gemshard = 1; crystalshard = 1; sorcery_shard = 1; };
			_sorcery = {
				material = {
					gem = true;
					id = name, data = gem;
					raw = true, value = 1;
				};
				recipe = {
					canonical = {
						craft = {
							{'','xdecor:hammer',''};
							{'',itemname,''};
						};
					}
				};
			};
		})
	end
	if not gem.foreign_amulet then
		local img = sorcery.lib.image
		local img_stone = img('sorcery_amulet.png'):multiply(sorcery.lib.color(gem.tone))
		local img_sparkle = img('sorcery_amulet_sparkle.png')
		local useamulet = function(stack,user,target)
			local sp = sorcery.amulet.getspell(stack)
			if not sp or not sp.cast then return nil end
			local stats = sorcery.amulet.stats(stack)
			local probe = sorcery.spell.probe(user:get_pos())
			-- amulets don't work in antimagic fields, though some may want to 
			-- implement this logic themselves (for instance to check a range)
			if (probe.disjunction and not sp.ignore_disjunction) then return nil end

			local ctx = {
				caster = user;
				target = target;
				stats = stats;
				wield = stack;
				amulet = stack:get_definition()._sorcery.amulet;
				meta = stack:get_meta(); -- avoid spell boilerplate
				color = sorcery.lib.color(sp.tone);
				today = minetest.get_day_count();
				probe = probe;
				heading = {
					pos   = user:get_pos();
					yaw   = user:get_look_dir();
					pitch = user:get_look_vertical();
					angle = user:get_look_horizontal();
					eyeheight = user:get_properties().eye_height;
				};

				sound = "xdecor_enchanting"; --FIXME make own sounds
				sparkle = true;
			}
			local res = sp.cast(ctx)

			if res == nil or res == true then
				minetest.sound_play(ctx.sound, { 
					pos = user:get_pos();
					gain = 1;
				})
			end
			if ctx.sparkle then
				sorcery.vfx.cast_sparkle(user, ctx.color, stats.power,0.5)
			end
			if res == nil then
				if not minetest.check_player_privs(user, 'sorcery:infinirune') then
					sorcery.amulet.setrune(stack)
				end
			end

			return ctx.wield
		end;
		minetest.register_craftitem(amuletname, {
			description = sorcery.lib.str.capitalize(name) .. ' amulet';
			inventory_image = img_sparkle:blit(img_stone):render();
			wield_scale = { x = 0.6, y = 0.6, z = 0.6 };
			groups = { sorcery_amulet = 1 };
			on_use = useamulet;
			_sorcery = {
				material = {
					gem = true, id = name, data = gem;
					value = (5 * shards_per_gem) + 4;
				};
				amulet = { base = name };
			};
		}) 
		sorcery.register.metals.foreach('sorcery:mk-amulet-frames-'..name,{'sorcery:generate'}, function(metalid,metal)
			if not metal.amulet then return end
			local framedid = string.format("%s_frame_%s", amuletname, metalid)
			local img_frame = img(string.format('sorcery_amulet_frame_%s.png',metalid))
			minetest.register_craftitem(framedid, {
				description = string.format("%s-framed %s amulet",sorcery.lib.str.capitalize(metalid), name);
				inventory_image = img_sparkle:blit(img_frame):blit(img_stone):render();
				wield_scale = { x = 0.6, y = 0.6, z = 0.6 };
				groups = { sorcery_amulet = 1 };
				on_use = useamulet;
				_sorcery = {
					amulet = { base = name, frame = metalid };
				};
			})
			local frag = metal.parts.fragment
			minetest.register_craft {
				output = framedid;
				recipe = {
					{'',  frag,''};
					{frag,amuletname,frag};
					{'',  frag,''};
				};
			}
		end)
	end
	minetest.register_craft {
		type = 'shapeless';
		recipe = (minetest.get_modpath('xdecor') and {
			'xdecor:hammer', itemname;
		}) or { itemname };
		output = shardname .. ' 9';
		replacements = {
			{'xdecor:hammer','xdecor:hammer'};
		};
	}
	minetest.register_craft {
		type = 'shapeless';
		recipe = {
			shardname, shardname, shardname;
			shardname, shardname, shardname;
			shardname, shardname, shardname;
		};
		output = itemname;
	};
	minetest.register_craft {
		recipe = {
			{shardname,itemname,shardname};
			{itemname,itemname,itemname};
			{shardname,itemname,shardname};
		};
		output = amuletname;
	};

	-- generate lenses and crafting recipes
	for _, kind in pairs { 'amplifier','rectifier','concave','convex' } do
		local id = 'sorcery:lens_' .. kind .. '_' .. name
		minetest.register_tool(id, {
			inventory_image = sorcery.lib.image('sorcery_lens_overlay_gold.png'):
				blit(sorcery.lib.image('sorcery_lens_' .. kind .. '.png'):
					multiply(sorcery.lib.color(gem.tone):brighten(1.1))):
				render();
			description = sorcery.lib.str.capitalize(name) .. ' ' .. sorcery.lib.str.capitalize(kind) .. ' Lens';
			groups = { sorcery_enchanting_lens = 1 };
			_proto = {
				gem = name;
				kind = kind;
			};
		})
	end
	do local casing = 'sorcery:fragment_gold'
		minetest.register_craft {
			output = 'sorcery:lens_convex_' .. name;
			recipe = {
				{'',       casing, ''};
				{itemname, casing, itemname};
				{'',       casing, ''};
			};
		}
		minetest.register_craft {
			output = 'sorcery:lens_concave_' .. name;
			recipe = {
				{itemname, casing, itemname};
				{'',       casing, ''};
				{itemname, casing, itemname};
			};
		}
		minetest.register_craft {
			output = 'sorcery:lens_amplifier_' .. name;
			recipe = {
				{itemname, casing, itemname};
				{shardname,casing, shardname};
				{shardname,casing, shardname};
			};
		}
		minetest.register_craft {
			output = 'sorcery:lens_rectifier_' .. name;
			recipe = {
				{shardname,casing, shardname};
				{'basic_materials:silver_wire',casing,'basic_materials:silver_wire'};
				{itemname, casing, itemname};
			};
			replacements = {
				{'basic_materials:silver_wire', 'basic_materials:empty_spool'};
				{'basic_materials:silver_wire', 'basic_materials:empty_spool'};
			};
		}
	end

	if gem.foreign then return false end
	minetest.register_craftitem(itemname, {
		description = sorcery.lib.str.capitalize(name);
		inventory_image = 'sorcery_gem_' .. name .. '.png';
		groups = { gem = 1; crystal = 1; sorcery_gem = 1; };
		_sorcery = {
			material = {
				id = name, data = gem;
				raw = true, value = shards_per_gem;
			};
		};
	})
	local tools = gem.tools
	if tools == nil then tools = {
		'group:pickaxe';
		'group:pick'; -- FUCK YOU INSTANT_ORES
		'~default:enchanted_pick_'; -- FUCK YOU XDECOR
	} end

	local ores = gem.ores
	if ores == nil then ores = {
		['default:stone_with_coal'] = 1.0;
		['default:stone_with_iron'] = 0.7;
		['default:stone_with_copper'] = 0.6;
		['default:stone_with_tin'] = 0.8;
		['default:stone_with_gold'] = 1.5;
		--
		['sorcery:stone_with_cobalt'] = 0.9;
		['sorcery:stone_with_tungsten'] = 0.3;
		['sorcery:stone_with_platinum'] = 0.6;
		['sorcery:stone_with_iridium'] = 1.6;
		['sorcery:stone_with_lithium'] = 1.4;
	} end

	for ore,fac in pairs(ores) do
		local drops = minetest.registered_nodes[ore].drop
		local newdrops
		if type(drops) == 'string' then
			newdrops = {
				max_items = 1;
				items = {
					{ rarity = 1; items = { drops }; };
				};
			}
		else newdrops = sorcery.lib.tbl.copy(drops) end
		
		newdrops.max_items = newdrops.max_items + 1
		newdrops.items[#newdrops.items + 1] = {
			rarity = gem.rarity * fac;
			items = { itemname };
		};

		minetest.override_item(ore, {drop = newdrops})
		-- might be possible to just edit it in place, since we're
		-- referring to registered_nodes anyway, but i don't want
		-- to chance it; god knows what's going on under the hood
	end
end

-- for g,v in pairs(sorcery.data.gems) do sorcery.register_gem(g,v) end
sorcery.register.gems.foreach('sorcery:generate',{},register_gem)

sorcery.gem = {
	getdrops = function(fac)
		items = {}
		for g,v in pairs(sorcery.data.gems) do
			items[#items + 1] = {
				rarity = gem.rarity * fac;
				items = { itemname };
			};
		end
		return items
	end;
};
-- register gem cutting tools
--   - abrasive powder
--   - hand-drill

-- register gem cuts (cube, sphere, circlet, triangle, rod)
-- cube, sphere, and triangle are used in enchanting. all are used in crafting.