sorcery  Artifact [720c3d8102]

Artifact 720c3d81028cfd45271f85ae25e27457223523f7c6ef9483eb3a64be5dffbaa5:


-- a rune is an abstract object created by a runeforge, which can be
-- applied to an amulet in order to imbue that amulet with unique
-- and fearsome powers. the specific spell depends on the stone the
-- rune is applied to, and not all runes can necessarily be applied
-- to all stones.

return {
	translocate = {
		name = 'Translocate';
		tone = {0,235,233};
		minpower = 3;
		rarity = 15;
		amulets = {
			amethyst = {
				name = 'Joining';
				desc = 'Give this amulet to another and they can arrive safely at your side in a flash from anywhere in the world — though returning whence they came may be a more difficult matter';
				apply = function(ctx)
					local maker = ctx.user:get_player_name()
					ctx.meta:set_string('rune_join_target',maker)
				end;
				remove = function(ctx) ctx.meta:set_string('rune_join_target','') end;
				frame = {
					gold = {
						name = 'Exchange';
						desc = 'Give this amulet to another and they will be able to trade places with you no matter where in the world each of you might be.'; 
					};
					cobalt = {
						name = 'Sending';
						desc = 'Give this amulet to another and by wielding this amulet against another they will be able to transport them instantly to your side';
					};
					iridium = {
						name = 'Arrival';
						desc = "Give this amulet to another and they will be able to arrive at your side in a flash from anywhere in the world, carrying others with them in the spell's grip";
					};
				};
			};
			sapphire = {
				name = 'Return';
				desc = 'Use this amulet once to bind it to a particular point in the world, then discharge its spell to return instantly to that point.';
				remove = function(ctx)
					ctx.meta:set_string('rune_return_dest','')
				end;
				cast = function(ctx)
					if not ctx.meta:contains('rune_return_dest') then
						local pos = ctx.caster:get_pos()
						ctx.meta:set_string('rune_return_dest',minetest.pos_to_string(pos))
						return true -- play effects but do not break spell
					else
						local pos = minetest.string_to_pos(ctx.meta:get_string('rune_return_dest'))
						ctx.meta:set_string('rune_return_dest','')
						local subjects = { ctx.caster }
						local center = ctx.caster:get_pos()
						ctx.sparkle = false
						for _,s in pairs(subjects) do
							local offset = vector.subtract(s:get_pos(), center)
							local pt = sorcery.lib.node.get_arrival_point(vector.add(pos,offset))
							if pt then
								sorcery.vfx.body_sparkle(s,sorcery.lib.color(20,120,255),2)
								sorcery.vfx.body_sparkle(nil,sorcery.lib.color(20,255,120),2,pt)
								s:set_pos(pt)
							end
						end
					end
				end;
				frame = {
					iridium = {
						name = 'Mass Return';
						desc = 'Use this amulet once to bind it to a particular point in the world, then carry yourself and everyone around you back to that point in a flash simply by using it again';
					};
				};
			};
			emerald = {
				name = 'Banishment';
				desc = 'Use this amulet once to bind it to a particular point in the world, then wield it against a foe to whisk them away immediately to your chosen prison';
				frame = {
					iridium = {
						name = 'Mass Banishment';
						desc = 'Use this amulet once to bind it to a particular point in the world, then use it again to seize up everyone surrounding you in the grip of a fearsome magic that will deport them all in the blink of an eye to whatever destination you have chosen';
					};
				};
			};
			ruby = {
				name = 'Escape';
				desc = 'Immediately transport yourself out of a dangerous situation back to the last place you slept';
				frame = {
					cobalt = {
						name = 'Vengeful Exit';
						desc = 'Translocate away to the safety of your boudoir with a fearsome blast of dangerous radiance that will send bodies flying and deal heavy damage to those nearby';
					};
					iridium = {
						name = 'Mass Escape';
						desc = 'Break up even the fiercest of quarrels by transporting yourself and everyone around you out of harms\' way and immediately back to the last place each slept';
					};
				};
			};
			diamond = {
				name = 'Elevation';
				desc = 'Lift yourself and everything around you high up into the sky';
			};
		};
	};
	disjoin = {
		name = 'Disjoin';
		tone = {159,235,0};
		minpower = 4;
		rarity = 20;
		amulets = {
			amethyst = {
				name = 'Unsealing';
				desc = 'Wielding this amulet, a touch of your hand will unravel even the mightiest protective magics, leaving doors unsealed and walls free to tear down';
			};
			emerald = {
				name = 'Mundanity';
				desc = 'Strip away the effects of all active potions and spells in your immediate vicinity, leaving adversaries without their magicks to enhance and protect them, and allies free of any curses they may be hobbled by -- and, of course, vice versa';
			};
		}
	};
	repulse = {
		name = 'Repulse';
		tone = {0,180,235};
		minpower = 1;
		rarity = 7;
		amulets = {
			amethyst = {
				name = 'Hurling';
				desc = 'Wielding this amulet, a mere flick of your fingers will lift any target of your choice bodily into the air and press upon them with tremendous repulsive force, throwing them like a hapless ragdoll out of your path';
			};
			diamond = {
				name = 'Shockwave';
				desc = 'Unleash a tidal wave of force in every direction, blasting friends and foes alike away from you with enough violence to sprain and fracture bone';
			};
		};
	};
	obliterate = {
		name = 'Obliterate';
		tone = {255,0,10};
		minpower = 5;
		rarity = 30;
		amulets = {
			amethyst = {
				name = 'Sapping';
				desc = 'Punch a hole in enemy fortifications big enough to slip through but small enough to avoid immediate attention';
			};
			ruby = {
				name = 'Shattering';
				desc = 'Tear a violent wound in the earth with the destructive force of this amulet';
			};
			diamond = {
				name = 'Killing';
				desc = 'Wield this amulet against a foe to instantly snuff the life out of their mortal form, regardless of their physical protections.';
				cast = function(ctx)
					if not (ctx.target and ctx.target.type == 'object') then return false end
					local tgt = ctx.target.ref
					if not minetest.is_player(obj) then return false end
					local tgth = tgt:get_properties().eye_height
					sorcery.vfx.bloodburst(vector.add(tgt:get_pos(),{x=0,y=tgth/2,z=0}),20)
					minetest.sound_play('sorcery_bloody_burst', { pos = pos, gain = 1.5 })
					tgt:set_hp(0)
				end;
				frame = {
					iridium = {
						name = 'Massacre';
						desc = "Unleash the dark and wicked force that lurks within this fell amulet to instantaneously slay all those who surround you, friend and foe alike";
					};
				};
			};
		};
	};
	excavate = {
		name = 'Excavate';
		tone = {0,68,235};
		minpower = 3;
		rarity = 60;
		amulets = {
			sapphire = {
				name = 'Tunnelling';
				desc = 'Carve a long tunnel ahead of you into the rock';
			};
			emerald = {
				name = 'Boring';
				desc = 'Release the force of this amulet to punch a deep borehole down into the earth below';
			}
		};
	};
	genesis = {
		name = 'Genesis';
		tone = {235,0,175};
		minpower = 5;
		rarity = 50;
		amulets = {
			mese = {
				name = 'Duplication';
				desc = 'Generate a copy of any object or item, no matter how common or rare';
			};
		};
	};
	luminate = {
		name = 'Luminate';
		tone = {255,194,0};
		minpower = 1;
		rarity = 25;
		amulets = {
			luxite = {
				name = 'Glow';
				desc = 'Swathe yourself in an aura of sparkling radiance, casting light upon all the dark places where you voyage';
			};
			diamond = {
				name = 'Radiance';
				desc = 'Set the air around you alight with a mystic luminance, letting you see clearly a great distance in every direction for several minutes';
				frame = {
					iridium = {
						name = 'Sunshine';
						desc = 'Unleash the power of this amulet to seize ultimate control over the forces of nature and summon the Sun high into the nighttime sky';
					};
				};
			};
		};
	};
	dominate = {
		name = 'Dominate';
		tone = {235,0,228};
		minpower = 4;
		rarity = 40;
		amulets = {
			amethyst = {
				name = 'Suffocation';
				desc = 'Wrap this spell tightly around your victim\'s throat, cutting off their oxygen until you release them.';
			};
			ruby = {
				name = 'Exsanguination';
				desc = 'Rip the life force out of another, leaving them on the brink of death, and use it to mend your own wounds and invigorate your own being';
				cast = function(ctx)
					if not (ctx.target and ctx.target.type == 'object') then return false end
					local tgt = ctx.target.ref
					local takefac = math.min(99,50 + (ctx.stats.power * 5)) / 100
					local dmg = tgt:get_hp() * takefac
					print("!!! dmg calc",takefac,dmg,tgt:get_hp())

					local numhits = math.random(6,10+ctx.stats.power/2)
					local function dohit(hitsleft)
						if tgt == nil or tgt:get_properties() == nil then return end
						tgt:punch(ctx.caster, 1, {
							full_punch_interval = 1;
							damage_groups = { fleshy = dmg / numhits }
						})
						local tgth = tgt:get_properties().eye_height
						sorcery.vfx.bloodburst(vector.add(tgt:get_pos(),{x=0,y=tgth/2,z=0}),math.random(10 * takefac, 40 * takefac))
						ctx.caster:set_hp(ctx.caster:get_hp() + math.max(1,(dmg/numhits)*takefac))

						local sound = {'sorcery_bloody_hit','sorcery_crunch',false}
						sound = sound[math.random(#sound)]
						if sound ~= false then
							minetest.sound_play(sound, { pos = pos, gain = math.random(5,15)*0.1 })
						end

						local nexthit = math.random() * 0.4 + 0.1
						local dir = vector.subtract(ctx.caster:get_pos(), tgt:get_pos())
						local spark = sorcery.lib.image('sorcery_spark.png')
						minetest.add_particlespawner {
							amount = math.random(80*takefac,150*takefac);
							texture = spark:blit(spark:multiply(sorcery.lib.color(255,20,10))):render();
							time = nexthit;
							attached = tgt;
							minpos = {x = -0.3, y = -0.5, z = -0.3};
							maxpos = {x =  0.3, y = tgth, z = 0.3};
							minvel = vector.multiply(dir,0.5);
							maxvel = vector.multiply(dir,0.9);
							minacc = vector.multiply(dir,0.1);
							maxacc = vector.multiply(dir,0.2);
							minexptime = nexthit * 1.5;
							maxexptime = nexthit * 2;
							minsize = 0.5;
							maxsize = 5 * takefac;
							glow = 14;
							animation = {
								type = 'vertical_frames';
								aspect_w = 16, aspect_h = 16;
								length = nexthit*2 + 0.1;
							};
						}

						if hitsleft > 0 then
							minetest.after(nexthit, function() dohit(hitsleft-1) end)
						end
					end
					dohit(numhits)
				end;
			};
			amethyst = {
				name = 'Disarming';
				desc = 'Wield this amulet against a foe to rip all the weapons in their possession out of their grasp';
				frame = {
					iridium = {
						name = 'Peacemaking';
						desc = 'Confiscate all weapons held by those surrounding you';
					};
				};
			};
		};
	};
}