sorcery  Diff

Differences From Artifact [bd35ca52e8]:

  • File data/runes.lua — part of check-in [96c5289a2a] at 2020-10-21 03:35:35 on branch trunk — add rune forges, runes, amulet frames, write sacrifice spell, touch up amulet graphics, enable enchantment of amulets (though spells cannot yet be cast), defuckulate syncresis core icon, unfuckitize sneaky leycalc bug that's probably been the cause of some long-standing wackiness, add item classes, add some more textures, disbungle various other asstastrophes, remove sneaky old debug code, improve library code, add utility for uploading merge requests (user: lexi, size: 6898) [annotate] [blame] [check-ins using]

To Artifact [720c3d8102]:


9
10
11
12
13
14
15
16





17
18
19
20
21
22
23
..
27
28
29
30
31
32
33
34

























35
36
37
38
39
40
41
...
114
115
116
117
118
119
120









121
122
123
124
125
126
127
...
179
180
181
182
183
184
185




186
187
188
























































189
190
191
192
193
194
195
		name = 'Translocate';
		tone = {0,235,233};
		minpower = 3;
		rarity = 15;
		amulets = {
			amethyst = {
				name = 'Joining';
				desc = 'Give this amulet to another and they can arrive at your side in a flash from anywhere in the world — though returning whence they came may be a more difficult matter';





				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';
................................................................................
						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 use it again to return instantly to that point.';

























				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';
					};
				};
			};
................................................................................
			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.';









				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";
					};
				};
			};
................................................................................
	};
	dominate = {
		name = 'Dominate';
		tone = {235,0,228};
		minpower = 4;
		rarity = 40;
		amulets = {




			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';
























































			};
			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';







|
>
>
>
>
>







 







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>







 







>
>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
..
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
...
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
		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';
................................................................................
						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';
					};
				};
			};
................................................................................
			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";
					};
				};
			};
................................................................................
	};
	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';